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 "radio_event.h"
25 #include "sim_data_type.h"
26 #include "telephony_log_wrapper.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<Telephony::ITelRilManager> telRilManager,std::shared_ptr<SimStateManager> simStateManager)171 IccOperatorPrivilegeController::IccOperatorPrivilegeController(
172 std::shared_ptr<Telephony::ITelRilManager> telRilManager, std::shared_ptr<SimStateManager> simStateManager)
173 : TelEventHandler("IccOperatorPrivilegeController"), slotId_(0), telRilManager_(telRilManager),
174 simStateManager_(simStateManager), state_(new IccOperatorPrivilegeController::LogicalStateMachine())
175 {}
176
~IccOperatorPrivilegeController()177 IccOperatorPrivilegeController::~IccOperatorPrivilegeController()
178 {
179 delete state_;
180 }
181
Init(const int32_t slotId)182 void IccOperatorPrivilegeController::Init(const int32_t slotId)
183 {
184 this->slotId_ = slotId;
185 TELEPHONY_LOGI("IccOperatorPrivilegeController::Init begin");
186 if (telRilManager_ == nullptr) {
187 TELEPHONY_LOGE("telRilManager_ can not be nullptr!!");
188 return;
189 }
190 if (simStateManager_ == nullptr) {
191 TELEPHONY_LOGE("simStateManager_ can not be nullptr!!");
192 return;
193 }
194 auto self = this->shared_from_this();
195 simStateManager_->RegisterCoreNotify(self, RadioEvent::RADIO_SIM_STATE_CHANGE);
196 /* try to load data */
197 ProcessSimStateChanged();
198 }
HasOperatorPrivileges(bool & hasOperatorPrivileges)199 int32_t IccOperatorPrivilegeController::HasOperatorPrivileges(bool &hasOperatorPrivileges)
200 {
201 constexpr std::string_view certHash = "ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4";
202 constexpr std::string_view packageName = "com.ohos.openharmony";
203 return HasOperatorPrivileges(certHash, packageName, hasOperatorPrivileges);
204 }
205
HasOperatorPrivileges(const std::string_view & certHash,const std::string_view & packageName,bool & hasOperatorPrivileges)206 int32_t IccOperatorPrivilegeController::HasOperatorPrivileges(
207 const std::string_view &certHash, const std::string_view &packageName, bool &hasOperatorPrivileges)
208 {
209 TELEPHONY_LOGI("IccOperatorPrivilegeController::HasOperatorPrivileges begin");
210 constexpr int32_t RETRY_TIMES = 3;
211 for (int32_t i = INT32_ZERO; i < RETRY_TIMES; ++i) {
212 const bool isLoaded = state_->SuccessLoaded();
213 if (isLoaded) {
214 break;
215 }
216 if (state_->IsTimeOut()) {
217 TELEPHONY_LOGI("retry to load data times %{public}d", i + 1);
218 ProcessSimStateChanged(); // retry to load
219 }
220 }
221 if (!state_->IsSimAvailable()) {
222 TELEPHONY_LOGE(
223 "IccOperatorPrivilegeController::HasOperatorPrivileges false with rules.size:%{public}zu and "
224 "simState:%{public}d",
225 rules_.size(),
226 ((simStateManager_ == nullptr) ? SimState::SIM_STATE_UNKNOWN : simStateManager_->GetSimState()));
227 hasOperatorPrivileges = false;
228 return TELEPHONY_ERR_NO_SIM_CARD;
229 }
230 if (!rules_.empty()) {
231 auto hash = Strip(certHash);
232 auto package = Strip(packageName);
233 for (const auto &rule : rules_) {
234 if (rule.Matche(hash, package)) {
235 TELEPHONY_LOGI("already found rule to match then return true");
236 hasOperatorPrivileges = true;
237 return TELEPHONY_ERR_SUCCESS;
238 }
239 }
240 }
241 TELEPHONY_LOGE("no rule can match then return false");
242 hasOperatorPrivileges = false;
243 return TELEPHONY_ERR_SUCCESS;
244 }
245
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)246 void IccOperatorPrivilegeController::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
247 {
248 if (event == nullptr) {
249 TELEPHONY_LOGE("event is nullptr!");
250 return;
251 }
252 const uint32_t id = event->GetInnerEventId();
253 switch (id) {
254 case RadioEvent::RADIO_SIM_STATE_CHANGE:
255 ProcessSimStateChanged();
256 break;
257 case MSG_OPEN_LOGICAL_CHANNEL_DONE:
258 ProcessOpenLogicalChannelDone(event);
259 break;
260 case MSG_TRANSMIT_LOGICAL_CHANNEL_DONE:
261 ProcessTransmitLogicalChannelDone(event);
262 break;
263 case MSG_CLOSE_LOGICAL_CHANNEL_DONE:
264 ProcessCloseLogicalChannelDone();
265 break;
266 default:
267 break;
268 }
269 }
270
ProcessSimStateChanged()271 void IccOperatorPrivilegeController::ProcessSimStateChanged()
272 {
273 const SimState state = simStateManager_->GetSimState();
274 TELEPHONY_LOGI("ProcessSimStateChanged simState:%{public}d", state);
275 switch (state) {
276 case SimState::SIM_STATE_UNKNOWN:
277 case SimState::SIM_STATE_NOT_READY:
278 case SimState::SIM_STATE_NOT_PRESENT:
279 TELEPHONY_LOGI("GetSimState is %{public}d then Operator privilege can not cussess loaded", state);
280 state_->SetSimAvailable(false);
281 rules_.clear();
282 break;
283 case SimState::SIM_STATE_LOADED:
284 case SimState::SIM_STATE_READY:
285 TELEPHONY_LOGI("GetSimState is %{public}d then try to reload operator privilege!", state);
286 state_->SetSimAvailable(true);
287 /* try to reload */
288 OpenChannel();
289 break;
290 default:
291 break;
292 }
293 }
294
OpenChannel()295 void IccOperatorPrivilegeController::OpenChannel()
296 {
297 TELEPHONY_LOGI("IccOperatorPrivilegeController::openChannel begin");
298 if (!state_->IsAppropriateToOpenChannel()) {
299 TELEPHONY_LOGI("now is not appropriate to open a new logical channel!!");
300 return;
301 }
302 TELEPHONY_LOGI("will to SimOpenLogicalChannel!");
303 rules_.clear();
304 state_->SetForOpenChannel();
305 auto response = GenCallBackEvent(shared_from_this(), MSG_OPEN_LOGICAL_CHANNEL_DONE);
306 telRilManager_->SimOpenLogicalChannel(slotId_, ARAM_AID.data(), P2, response);
307 }
308
ProcessOpenLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer & event)309 void IccOperatorPrivilegeController::ProcessOpenLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer &event)
310 {
311 TELEPHONY_LOGI("Open Logical Channel Done!!");
312 const bool timeout = state_->IsTimeOut();
313 if (timeout) {
314 TELEPHONY_LOGE("OpenLogical fail at isTimeout[%{public}d]", timeout);
315 state_->SetForCloseChannel();
316 state_->currentChannelId = INT32_FST_NEGATIVE;
317 return;
318 }
319 TELEPHONY_LOGI("Will to SimTransmitApduLogicalChannel");
320 auto resultPtr = event->GetSharedObject<OpenLogicalChannelResponse>();
321 if (resultPtr == nullptr) {
322 TELEPHONY_LOGE("the data of result is nullptr! then will Close Logical Channel");
323 return;
324 }
325 state_->currentChannelId = resultPtr->channelId;
326 if (state_->currentChannelId <= INT32_ZERO) {
327 TELEPHONY_LOGE("the logical channel transmit Unexpected shutdown");
328 return;
329 }
330 auto transmitEvent = GenCallBackEvent(shared_from_this(), MSG_TRANSMIT_LOGICAL_CHANNEL_DONE);
331 ApduSimIORequestInfo reqInfo;
332 reqInfo.channelId = state_->currentChannelId;
333 reqInfo.type = CLA;
334 reqInfo.instruction = COMMAND;
335 reqInfo.p1 = P1;
336 reqInfo.p2 = P2;
337 reqInfo.p3 = P3;
338 reqInfo.data = "";
339 telRilManager_->SimTransmitApduLogicalChannel(slotId_, reqInfo, transmitEvent);
340 }
341
ProcessTransmitLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer & event)342 void IccOperatorPrivilegeController::ProcessTransmitLogicalChannelDone(const AppExecFwk::InnerEvent::Pointer &event)
343 {
344 TELEPHONY_LOGI("Transmit Logical Channel Done!!");
345 auto resultPtr = event->GetSharedObject<IccIoResultInfo>();
346 do {
347 if (resultPtr == nullptr) {
348 TELEPHONY_LOGE("the data of result is nullptr! then will Close Logical Channel");
349 break;
350 }
351 if (state_->currentChannelId <= INT32_ZERO) {
352 TELEPHONY_LOGE("the logical channel transmit Unexpected shutdown");
353 break;
354 }
355 if (state_->IsTimeOut()) {
356 TELEPHONY_LOGE("the logical channel transmit is timeout");
357 break;
358 }
359 state_->currData += resultPtr->response;
360 if (!IsOneTlvCompleted(state_->currData)) {
361 TELEPHONY_LOGI("need continue load TLV data");
362 auto transmitEvent = GenCallBackEvent(shared_from_this(), MSG_TRANSMIT_LOGICAL_CHANNEL_DONE);
363 ApduSimIORequestInfo reqInfo;
364 reqInfo.channelId = state_->currentChannelId;
365 reqInfo.type = CLA;
366 reqInfo.instruction = COMMAND;
367 reqInfo.p1 = P1;
368 reqInfo.p2 = P2_EXTENDED_DATA;
369 reqInfo.p3 = P3;
370 reqInfo.data = "";
371 telRilManager_->SimTransmitApduLogicalChannel(slotId_, reqInfo, transmitEvent);
372 return;
373 }
374 if (!IccOperatorRule::CreateFromTLV(state_->currData, rules_)) {
375 TELEPHONY_LOGE("Parse TLV data to Rules fail");
376 break;
377 }
378 } while (false);
379 auto closeEvent = GenCallBackEvent(shared_from_this(), MSG_CLOSE_LOGICAL_CHANNEL_DONE);
380 if (state_->currentChannelId > INT32_ZERO) {
381 telRilManager_->SimCloseLogicalChannel(slotId_, state_->currentChannelId, closeEvent);
382 }
383 state_->SetForCloseChannel();
384 return;
385 }
386
ProcessCloseLogicalChannelDone()387 void IccOperatorPrivilegeController::ProcessCloseLogicalChannelDone()
388 {
389 TELEPHONY_LOGI("Logical Transmit Cussessfully End!");
390 state_->currentChannelId = INT32_FST_NEGATIVE;
391 }
392 } // namespace Telephony
393 } // namespace OHOS
394