1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "icc_operator_privilege_controller.h"
17
18 #include <algorithm>
19 #include <charconv>
20 #include <chrono>
21 #include <mutex>
22
23 #include "inner_event.h"
24 #include "sim_data_type.h"
25 #include "telephony_log_wrapper.h"
26 #include "radio_event.h"
27
28 namespace OHOS {
29 namespace Telephony {
30 constexpr std::string_view ARAM_AID = "A00000015141434C00";
31 constexpr int32_t CLA = 0x80;
32 constexpr int32_t COMMAND = 0xCA;
33 constexpr int32_t P1 = 0xFF;
34 constexpr int32_t P2 = 0x40;
35 constexpr int32_t P2_EXTENDED_DATA = 0x60;
36 constexpr int32_t P3 = 0x00;
37 constexpr int32_t INT32_INTVALUE = 0;
38 constexpr int32_t INT32_ZERO = 0;
39 constexpr int32_t INT32_FST_NEGATIVE = -1;
40 constexpr size_t FST_POS = 0;
41 constexpr size_t TAG_BYTES = 4;
42 constexpr size_t LEN_BYTES = 2;
43 constexpr size_t CHR_BYTES = 2;
44 constexpr int32_t HEX = 16;
45
Strip(const std::string_view & src)46 static std::string_view Strip(const std::string_view &src)
47 {
48 size_t length = src.size();
49 while (length && std::isspace(src.at(length - 1))) {
50 --length;
51 }
52 size_t pos = FST_POS;
53 for (; pos < src.size(); ++pos) {
54 if (!std::isspace(src.at(pos))) {
55 break;
56 }
57 }
58 if (length <= pos) {
59 return "";
60 }
61 return src.substr(pos, length - pos);
62 }
63
IsOneTlvCompleted(const std::string_view & s)64 static bool IsOneTlvCompleted(const std::string_view &s)
65 {
66 if (s.size() < (TAG_BYTES + LEN_BYTES)) {
67 return false;
68 }
69 auto lenStr = s.substr(FST_POS + TAG_BYTES, LEN_BYTES);
70 size_t len = 0;
71 std::from_chars(std::addressof(lenStr.front()), std::addressof(lenStr.back()), len, HEX);
72 return (s.size() >= ((CHR_BYTES * len) + TAG_BYTES + LEN_BYTES));
73 }
74
GenCallBackEvent(const std::shared_ptr<AppExecFwk::EventHandler> & owner,const uint32_t eventId)75 static AppExecFwk::InnerEvent::Pointer GenCallBackEvent(
76 const std::shared_ptr<AppExecFwk::EventHandler> &owner, const uint32_t eventId)
77 {
78 AppExecFwk::InnerEvent::Pointer event = AppExecFwk::InnerEvent::Get(eventId);
79 if (event == nullptr) {
80 TELEPHONY_LOGE("event is nullptr!");
81 return AppExecFwk::InnerEvent::Pointer(nullptr, nullptr);
82 }
83 event->SetOwner(owner);
84 return event;
85 }
86
87 class IccOperatorPrivilegeController::LogicalStateMachine {
88 static constexpr size_t CALL_TIMEOUT = 60;
89 static constexpr size_t TRANSMIT_TIMEOUT = CALL_TIMEOUT * 3;
90 static constexpr size_t TIME_SLICE = 100;
91 bool isTransmitting_ = false;
92 bool isAvailable_ = false;
93 mutable std::mutex mtx_;
94 mutable std::condition_variable cv_;
95
96 public:
97 std::chrono::system_clock::time_point openChannelTp = std::chrono::system_clock::now();
98 int32_t currentChannelId = INT32_FST_NEGATIVE;
99 std::string currData;
100
101 public:
102 LogicalStateMachine() = default;
103
IsTimeOut() const104 inline bool IsTimeOut() const
105 {
106 return IsTimeOut(openChannelTp, TRANSMIT_TIMEOUT);
107 }
108
IsTimeOut(const std::chrono::system_clock::time_point & tp,const size_t timeout=CALL_TIMEOUT) const109 inline bool IsTimeOut(const std::chrono::system_clock::time_point &tp, const size_t timeout = CALL_TIMEOUT) const
110 {
111 auto now = std::chrono::system_clock::now();
112 auto duration = std::chrono::duration_cast<std::chrono::seconds>(now - tp).count();
113 auto seconds = static_cast<size_t>(duration);
114 return seconds > timeout;
115 }
116
IsAppropriateToOpenChannel() const117 bool IsAppropriateToOpenChannel() const
118 {
119 if (currentChannelId < INT32_INTVALUE) {
120 return true;
121 }
122 if (IsTimeOut()) {
123 return true;
124 }
125 return false;
126 }
127
IsSimAvailable() const128 inline bool IsSimAvailable() const
129 {
130 return isAvailable_;
131 }
132
SetSimAvailable(const bool available)133 void SetSimAvailable(const bool available)
134 {
135 isAvailable_ = available;
136 if (!isAvailable_) {
137 currentChannelId = INT32_FST_NEGATIVE;
138 }
139 cv_.notify_one();
140 }
141
SetForOpenChannel()142 void SetForOpenChannel()
143 {
144 isTransmitting_ = true;
145 currData.clear();
146 openChannelTp = std::chrono::system_clock::now();
147 currentChannelId = INT32_ZERO;
148 cv_.notify_one();
149 }
150
SetForCloseChannel()151 void SetForCloseChannel()
152 {
153 isTransmitting_ = false;
154 cv_.notify_one();
155 }
156
SuccessLoaded(const size_t timeSlice=TIME_SLICE) const157 bool SuccessLoaded(const size_t timeSlice = TIME_SLICE) const
158 {
159 auto now = std::chrono::system_clock::now();
160 std::unique_lock<std::mutex> lck(mtx_);
161 while (isAvailable_ && isTransmitting_) {
162 cv_.wait_for(lck, std::chrono::milliseconds(timeSlice));
163 if (IsTimeOut(now)) {
164 return false;
165 }
166 }
167 return isAvailable_ && !isTransmitting_;
168 }
169 };
170
IccOperatorPrivilegeController(std::shared_ptr<AppExecFwk::EventRunner> runner,std::shared_ptr<Telephony::ITelRilManager> telRilManager,std::shared_ptr<SimStateManager> simStateManager)171 IccOperatorPrivilegeController::IccOperatorPrivilegeController(std::shared_ptr<AppExecFwk::EventRunner> runner,
172 std::shared_ptr<Telephony::ITelRilManager> telRilManager,
173 std::shared_ptr<SimStateManager> simStateManager)
174 : AppExecFwk::EventHandler(runner), slotId_(0), telRilManager_(telRilManager),
175 simStateManager_(simStateManager), state_(new IccOperatorPrivilegeController::LogicalStateMachine())
176 {}
177
~IccOperatorPrivilegeController()178 IccOperatorPrivilegeController::~IccOperatorPrivilegeController()
179 {
180 delete state_;
181 }
182
Init(const int32_t slotId)183 void IccOperatorPrivilegeController::Init(const int32_t slotId)
184 {
185 this->slotId_ = slotId;
186 TELEPHONY_LOGI("IccOperatorPrivilegeController::Init begin");
187 if (telRilManager_ == nullptr) {
188 TELEPHONY_LOGE("telRilManager_ can not be nullptr!!");
189 return;
190 }
191 if (simStateManager_ == nullptr) {
192 TELEPHONY_LOGE("simStateManager_ can not be nullptr!!");
193 return;
194 }
195 if (this->GetEventRunner() == nullptr) {
196 auto runner = AppExecFwk::EventRunner::Create("UsimOperatorPrivilegeManager");
197 if (runner == nullptr) {
198 TELEPHONY_LOGE("IccOperatorPrivilegeController::Init Create thread fail!");
199 return;
200 }
201 this->SetEventRunner(runner);
202 if (runner->Run() != ERR_OK) {
203 TELEPHONY_LOGE("runner->Run() fail!!");
204 }
205 }
206 auto self = this->shared_from_this();
207 simStateManager_->RegisterCoreNotify(self, RadioEvent::RADIO_SIM_STATE_CHANGE);
208 /* try to load data */
209 ProcessSimStateChanged();
210 }
HasOperatorPrivileges(bool & hasOperatorPrivileges)211 int32_t IccOperatorPrivilegeController::HasOperatorPrivileges(bool &hasOperatorPrivileges)
212 {
213 constexpr std::string_view certHash = "ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4";
214 constexpr std::string_view packageName = "com.ohos.openharmony";
215 return HasOperatorPrivileges(certHash, packageName, hasOperatorPrivileges);
216 }
217
HasOperatorPrivileges(const std::string_view & certHash,const std::string_view & packageName,bool & hasOperatorPrivileges)218 int32_t IccOperatorPrivilegeController::HasOperatorPrivileges(
219 const std::string_view &certHash, const std::string_view &packageName, bool &hasOperatorPrivileges)
220 {
221 TELEPHONY_LOGI("IccOperatorPrivilegeController::HasOperatorPrivileges begin");
222 constexpr int32_t RETRY_TIMES = 3;
223 for (int32_t i = INT32_ZERO; i < RETRY_TIMES; ++i) {
224 const bool isLoaded = state_->SuccessLoaded();
225 if (isLoaded) {
226 break;
227 }
228 if (state_->IsTimeOut()) {
229 TELEPHONY_LOGI("retry to load data times %{public}d", i + 1);
230 ProcessSimStateChanged(); // retry to load
231 }
232 }
233 if (!state_->IsSimAvailable()) {
234 TELEPHONY_LOGE(
235 "IccOperatorPrivilegeController::HasOperatorPrivileges false with rules.size:%{public}zu and "
236 "simState:%{public}d",
237 rules_.size(),
238 ((simStateManager_ == nullptr) ? SimState::SIM_STATE_UNKNOWN : simStateManager_->GetSimState()));
239 hasOperatorPrivileges = false;
240 return TELEPHONY_ERR_NO_SIM_CARD;
241 }
242 if (!rules_.empty()) {
243 auto hash = Strip(certHash);
244 auto package = Strip(packageName);
245 for (const auto &rule : rules_) {
246 if (rule.Matche(hash, package)) {
247 TELEPHONY_LOGI("already found rule to match then return true");
248 hasOperatorPrivileges = true;
249 return TELEPHONY_ERR_SUCCESS;
250 }
251 }
252 }
253 TELEPHONY_LOGE("no rule can match then return false");
254 hasOperatorPrivileges = false;
255 return TELEPHONY_ERR_SUCCESS;
256 }
257
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)258 void IccOperatorPrivilegeController::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
259 {
260 if (event == nullptr) {
261 TELEPHONY_LOGE("event is nullptr!");
262 return;
263 }
264 const uint32_t id = event->GetInnerEventId();
265 switch (id) {
266 case RadioEvent::RADIO_SIM_STATE_CHANGE:
267 ProcessSimStateChanged();
268 break;
269 case MSG_OPEN_LOGICAL_CHANNEL_DONE:
270 ProcessOpenLogicalChannelDone(event);
271 break;
272 case MSG_TRANSMIT_LOGICAL_CHANNEL_DONE:
273 ProcessTransmitLogicalChannelDone(event);
274 break;
275 case MSG_CLOSE_LOGICAL_CHANNEL_DONE:
276 ProcessCloseLogicalChannelDone();
277 break;
278 default:
279 break;
280 }
281 }
282
ProcessSimStateChanged()283 void IccOperatorPrivilegeController::ProcessSimStateChanged()
284 {
285 const SimState state = simStateManager_->GetSimState();
286 TELEPHONY_LOGI("ProcessSimStateChanged simState:%{public}d", state);
287 switch (state) {
288 case SimState::SIM_STATE_UNKNOWN:
289 case SimState::SIM_STATE_NOT_READY:
290 case SimState::SIM_STATE_NOT_PRESENT:
291 TELEPHONY_LOGI("GetSimState is %{public}d then Operator privilege can not cussess loaded", state);
292 state_->SetSimAvailable(false);
293 rules_.clear();
294 break;
295 case SimState::SIM_STATE_LOADED:
296 case SimState::SIM_STATE_READY:
297 TELEPHONY_LOGI("GetSimState is %{public}d then try to reload operator privilege!", state);
298 state_->SetSimAvailable(true);
299 /* try to reload */
300 OpenChannel();
301 break;
302 default:
303 break;
304 }
305 }
306
OpenChannel()307 void IccOperatorPrivilegeController::OpenChannel()
308 {
309 TELEPHONY_LOGI("IccOperatorPrivilegeController::openChannel begin");
310 if (!state_->IsAppropriateToOpenChannel()) {
311 TELEPHONY_LOGI("now is not appropriate to open a new logical channel!!");
312 return;
313 }
314 TELEPHONY_LOGI("will to SimOpenLogicalChannel!");
315 rules_.clear();
316 state_->SetForOpenChannel();
317 auto response = GenCallBackEvent(shared_from_this(), MSG_OPEN_LOGICAL_CHANNEL_DONE);
318 telRilManager_->SimOpenLogicalChannel(slotId_, ARAM_AID.data(), P2, response);
319 }
320
ProcessOpenLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer & event)321 void IccOperatorPrivilegeController::ProcessOpenLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer &event)
322 {
323 TELEPHONY_LOGI("Open Logical Channel Done!!");
324 const bool timeout = state_->IsTimeOut();
325 if (timeout) {
326 TELEPHONY_LOGE("OpenLogical fail at isTimeout[%{public}d]", timeout);
327 state_->SetForCloseChannel();
328 state_->currentChannelId = INT32_FST_NEGATIVE;
329 return;
330 }
331 TELEPHONY_LOGI("Will to SimTransmitApduLogicalChannel");
332 auto resultPtr = event->GetUniqueObject<OpenLogicalChannelResponse>();
333 if (resultPtr == nullptr) {
334 TELEPHONY_LOGE("the data of result is nullptr! then will Close Logical Channel");
335 return;
336 }
337 state_->currentChannelId = resultPtr->channelId;
338 if (state_->currentChannelId <= INT32_ZERO) {
339 TELEPHONY_LOGE("the logical channel transmit Unexpected shutdown");
340 return;
341 }
342 auto transmitEvent = GenCallBackEvent(shared_from_this(), MSG_TRANSMIT_LOGICAL_CHANNEL_DONE);
343 ApduSimIORequestInfo reqInfo;
344 reqInfo.channelId = state_->currentChannelId;
345 reqInfo.type = CLA;
346 reqInfo.instruction = COMMAND;
347 reqInfo.p1 = P1;
348 reqInfo.p2 = P2;
349 reqInfo.p3 = P3;
350 reqInfo.data = "";
351 telRilManager_->SimTransmitApduLogicalChannel(slotId_, reqInfo, transmitEvent);
352 }
353
ProcessTransmitLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer & event)354 void IccOperatorPrivilegeController::ProcessTransmitLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer &event)
355 {
356 TELEPHONY_LOGI("Transmit Logical Channel Done!!");
357 auto resultPtr = event->GetUniqueObject<IccIoResultInfo>();
358 do {
359 if (resultPtr == nullptr) {
360 TELEPHONY_LOGE("the data of result is nullptr! then will Close Logical Channel");
361 break;
362 }
363 if (state_->currentChannelId <= INT32_ZERO) {
364 TELEPHONY_LOGE("the logical channel transmit Unexpected shutdown");
365 break;
366 }
367 if (state_->IsTimeOut()) {
368 TELEPHONY_LOGE("the logical channel transmit is timeout");
369 break;
370 }
371 state_->currData += resultPtr->response;
372 if (!IsOneTlvCompleted(state_->currData)) {
373 TELEPHONY_LOGI("need continue load TLV data");
374 auto transmitEvent = GenCallBackEvent(shared_from_this(), MSG_TRANSMIT_LOGICAL_CHANNEL_DONE);
375 ApduSimIORequestInfo reqInfo;
376 reqInfo.channelId = state_->currentChannelId;
377 reqInfo.type = CLA;
378 reqInfo.instruction = COMMAND;
379 reqInfo.p1 = P1;
380 reqInfo.p2 = P2_EXTENDED_DATA;
381 reqInfo.p3 = P3;
382 reqInfo.data = "";
383 telRilManager_->SimTransmitApduLogicalChannel(slotId_, reqInfo, transmitEvent);
384 return;
385 }
386 if (!IccOperatorRule::CreateFromTLV(state_->currData, rules_)) {
387 TELEPHONY_LOGE("Parse TLV data to Rules fail");
388 break;
389 }
390 } while (false);
391 auto closeEvent = GenCallBackEvent(shared_from_this(), MSG_CLOSE_LOGICAL_CHANNEL_DONE);
392 if (state_->currentChannelId > INT32_ZERO) {
393 telRilManager_->SimCloseLogicalChannel(slotId_, state_->currentChannelId, closeEvent);
394 }
395 state_->SetForCloseChannel();
396 return;
397 }
398
ProcessCloseLogicalChannelDone()399 void IccOperatorPrivilegeController::ProcessCloseLogicalChannelDone()
400 {
401 TELEPHONY_LOGI("Logical Transmit Cussessfully End!");
402 state_->currentChannelId = INT32_FST_NEGATIVE;
403 }
404 } // namespace Telephony
405 } // namespace OHOS
406