• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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