• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "loghelper.h"
17 #include "app_data_parser.h"
18 #include "external_deps_proxy.h"
19 #include "host_card_emulation_manager.h"
20 #include "ability_manager_client.h"
21 #include "nfc_sdk_common.h"
22 #include "accesstoken_kit.h"
23 #include "hap_token_info.h"
24 
25 namespace OHOS {
26 namespace NFC {
27 #ifdef VENDOR_APPLICATIONS_ENABLED
28 static const int CODE_SEND_FIELD_DEACTIVATE = 0;
29 static const int CODE_SEND_FIELD_ACTIVATE = 1;
30 static const int CODE_SEND_APDU_DATA = 2;
31 #endif
32 const uint32_t SELECT_APDU_HDR_LENGTH = 5;
33 const uint8_t INSTR_SELECT = 0xA4;
34 const uint32_t MINIMUM_AID_LENGTH = 5;
35 const uint8_t SELECT_00 = 0x00;
36 const uint8_t SELECT_P1 = 0x04;
37 const uint32_t INDEX_CLASS_BYTE = 0;
38 const uint32_t INDEX_CHAIN_INSTRUCTION = 1;
39 const uint32_t INDEX_P1 = 2;
40 const uint32_t INDEX_3 = 3;
41 const uint32_t INDEX_AID_LEN = 4;
42 using OHOS::AppExecFwk::ElementName;
HostCardEmulationManager(std::weak_ptr<NfcService> nfcService,std::weak_ptr<NCI::INciCeInterface> nciCeProxy)43 HostCardEmulationManager::HostCardEmulationManager(std::weak_ptr<NfcService> nfcService,
44                                                    std::weak_ptr<NCI::INciCeInterface> nciCeProxy)
45     : nfcService_(nfcService), nciCeProxy_(nciCeProxy)
46 {
47     hceState_ = HostCardEmulationManager::INITIAL_STATE;
48     queueHceData_.clear();
49     abilityConnection_ = new (std::nothrow) NfcAbilityConnectionCallback();
50 }
~HostCardEmulationManager()51 HostCardEmulationManager::~HostCardEmulationManager()
52 {
53     hceState_ = HostCardEmulationManager::INITIAL_STATE;
54     queueHceData_.clear();
55     abilityConnection_ = nullptr;
56     bundleNameToHceCmdRegData_.clear();
57 }
58 
OnHostCardEmulationDataNfcA(const std::vector<uint8_t> & data)59 void HostCardEmulationManager::OnHostCardEmulationDataNfcA(const std::vector<uint8_t>& data)
60 {
61     if (data.empty()) {
62         InfoLog("onHostCardEmulationDataNfcA: no data");
63         return;
64     }
65     std::string dataStr = KITS::NfcSdkCommon::BytesVecToHexString(&data[0], data.size());
66     InfoLog("onHostCardEmulationDataNfcA: Data Length = %{public}zu; Data as "
67             "String = %{public}s",
68             data.size(), dataStr.c_str());
69 
70 #ifdef VENDOR_APPLICATIONS_ENABLED
71     // send data to vendor
72     sptr<IOnCardEmulationNotifyCb> notifyApduDataCallback =
73         ExternalDepsProxy::GetInstance().GetNotifyCardEmulationCallback();
74     if (notifyApduDataCallback != nullptr) {
75         notifyApduDataCallback->OnCardEmulationNotify(CODE_SEND_APDU_DATA, dataStr);
76     }
77 #endif
78 
79     std::string aid = ParseSelectAid(data);
80     InfoLog("selectAid = %{public}s", aid.c_str());
81     InfoLog("onHostCardEmulationDataNfcA: state %{public}d", hceState_);
82     ElementName aidElement;
83     SearchElementByAid(aid, aidElement);
84 
85     std::lock_guard<std::mutex> lock(hceStateMutex_);
86     switch (hceState_) {
87         case HostCardEmulationManager::INITIAL_STATE: {
88             InfoLog("got data on state INITIAL_STATE");
89             return;
90         }
91         case HostCardEmulationManager::WAIT_FOR_SELECT: {
92             HandleDataOnW4Select(aid, aidElement, data);
93             break;
94         }
95         case HostCardEmulationManager::WAIT_FOR_SERVICE: {
96             InfoLog("got data on state w4 service");
97             return;
98         }
99         case HostCardEmulationManager::DATA_TRANSFER: {
100             HandleDataOnDataTransfer(aid, aidElement, data);
101             break;
102         }
103         case HostCardEmulationManager::WAIT_FOR_DEACTIVATE: {
104             InfoLog("got data on state w4 deactivate");
105             return;
106         }
107         default: break;
108     }
109 }
110 
SearchElementByAid(const std::string & aid,ElementName & aidElement)111 void HostCardEmulationManager::SearchElementByAid(const std::string& aid, ElementName& aidElement)
112 {
113     if (aid.empty()) {
114         InfoLog("aid is empty");
115         return;
116     }
117     std::vector<ElementName> searchElementNames;
118     ExternalDepsProxy::GetInstance().GetHceAppsByAid(aid, searchElementNames);
119     if (searchElementNames.empty()) {
120         InfoLog("No applications found");
121         return;
122     }
123     if (searchElementNames.size() > 1) {
124         InfoLog("Found too many applications");
125     }
126     for (const ElementName& elementName : searchElementNames) {
127         InfoLog("ElementName: %{public}s", elementName.GetBundleName().c_str());
128         InfoLog("ElementValue: %{public}s", elementName.GetAbilityName().c_str());
129     }
130     ElementName element = searchElementNames[0];
131     aidElement.SetBundleName(element.GetBundleName());
132     aidElement.SetAbilityName(element.GetAbilityName());
133     aidElement.SetDeviceID(element.GetDeviceID());
134     aidElement.SetModuleName(element.GetModuleName());
135 }
136 
OnCardEmulationActivated()137 void HostCardEmulationManager::OnCardEmulationActivated()
138 {
139     InfoLog("OnCardEmulationActivated: state %{public}d", hceState_);
140     std::lock_guard<std::mutex> lock(hceStateMutex_);
141     hceState_ = HostCardEmulationManager::WAIT_FOR_SELECT;
142 
143 #ifdef VENDOR_APPLICATIONS_ENABLED
144     // send data to vendor
145     sptr<IOnCardEmulationNotifyCb> notifyApduDataCallback =
146         ExternalDepsProxy::GetInstance().GetNotifyCardEmulationCallback();
147     if (notifyApduDataCallback != nullptr) {
148         std::string data{};
149         notifyApduDataCallback->OnCardEmulationNotify(CODE_SEND_FIELD_ACTIVATE, data);
150     }
151 #endif
152 
153     queueHceData_.clear();
154 }
155 
OnCardEmulationDeactivated()156 void HostCardEmulationManager::OnCardEmulationDeactivated()
157 {
158     InfoLog("OnCardEmulationDeactivated: state %{public}d", hceState_);
159     std::lock_guard<std::mutex> lock(hceStateMutex_);
160     hceState_ = HostCardEmulationManager::INITIAL_STATE;
161 
162 #ifdef VENDOR_APPLICATIONS_ENABLED
163     // send data to vendor
164     sptr<IOnCardEmulationNotifyCb> notifyApduDataCallback =
165         ExternalDepsProxy::GetInstance().GetNotifyCardEmulationCallback();
166     if (notifyApduDataCallback != nullptr) {
167         std::string data{};
168         notifyApduDataCallback->OnCardEmulationNotify(CODE_SEND_FIELD_DEACTIVATE, data);
169     }
170 #endif
171 
172     queueHceData_.clear();
173     ErrCode releaseCallRet = AAFwk::AbilityManagerClient::GetInstance()->ReleaseCall(
174         abilityConnection_, abilityConnection_->GetConnectedElement());
175     InfoLog("Release call end. ret = %{public}d", releaseCallRet);
176 }
177 
HandleDataOnW4Select(const std::string & aid,ElementName & aidElement,const std::vector<uint8_t> & data)178 void HostCardEmulationManager::HandleDataOnW4Select(const std::string& aid, ElementName& aidElement,
179                                                     const std::vector<uint8_t>& data)
180 {
181     bool exitService = ExistService(aidElement);
182     if (!aid.empty()) {
183         if (exitService) {
184             InfoLog("HandleDataOnW4Select: existing service, try to send data "
185                     "directly.");
186             hceState_ = HostCardEmulationManager::DATA_TRANSFER;
187             SendDataToService(data);
188             return;
189         } else {
190             InfoLog("HandleDataOnW4Select: try to connect service.");
191             queueHceData_ = std::move(data);
192             bool startService = DispatchAbilitySingleApp(aidElement);
193             if (startService) {
194                 hceState_ = HostCardEmulationManager::WAIT_FOR_SERVICE;
195             }
196             return;
197         }
198     } else if (exitService) {
199         InfoLog("HandleDataOnW4Select: existing service, try to send data "
200                 "directly.");
201         hceState_ = HostCardEmulationManager::DATA_TRANSFER;
202         SendDataToService(data);
203         return;
204     } else {
205         InfoLog("no aid got");
206     }
207 }
208 
HandleDataOnDataTransfer(const std::string & aid,ElementName & aidElement,const std::vector<uint8_t> & data)209 void HostCardEmulationManager::HandleDataOnDataTransfer(const std::string& aid, ElementName& aidElement,
210                                                         const std::vector<uint8_t>& data)
211 {
212     bool exitService = ExistService(aidElement);
213     if (!aid.empty()) {
214         if (exitService) {
215             InfoLog("HandleDataOnDataTransfer: existing service, try to send "
216                     "data directly.");
217             hceState_ = HostCardEmulationManager::DATA_TRANSFER;
218             SendDataToService(data);
219             return;
220         } else {
221             InfoLog("HandleDataOnDataTransfer: existing service, try to "
222                     "connect service.");
223             queueHceData_ = std::move(data);
224             bool startService = DispatchAbilitySingleApp(aidElement);
225             if (startService) {
226                 hceState_ = HostCardEmulationManager::WAIT_FOR_SERVICE;
227             }
228             return;
229         }
230     } else if (exitService) {
231         InfoLog("HandleDataOnDataTransfer: existing service, try to send data "
232                 "directly.");
233         hceState_ = HostCardEmulationManager::DATA_TRANSFER;
234         SendDataToService(data);
235         return;
236     } else {
237         InfoLog("no service, drop apdu data.");
238     }
239 }
ExistService(ElementName & aidElement)240 bool HostCardEmulationManager::ExistService(ElementName& aidElement)
241 {
242     if (!abilityConnection_->ServiceConnected()) {
243         InfoLog("no service connected.");
244         return false;
245     }
246     std::string bundleName = abilityConnection_->GetConnectedElement().GetBundleName();
247     std::lock_guard<std::mutex> lock(regInfoMutex_);
248     auto it = bundleNameToHceCmdRegData_.find(bundleName);
249     if (it == bundleNameToHceCmdRegData_.end()) {
250         ErrorLog("no register data for %{public}s", abilityConnection_->GetConnectedElement().GetURI().c_str());
251         return false;
252     }
253     if (it->second.callback_ == nullptr) {
254         ErrorLog("callback is null");
255         return false;
256     }
257 
258     if (aidElement.GetBundleName().empty()) {
259         InfoLog("aid is empty.");
260         // normal data not select data
261         return true;
262     }
263     // only verify the element name for select data
264     if (aidElement.GetBundleName() == abilityConnection_->GetConnectedElement().GetBundleName() &&
265         aidElement.GetAbilityName() == abilityConnection_->GetConnectedElement().GetAbilityName()) {
266         InfoLog("ability is already connected.");
267         return true;
268     } else {
269         WarnLog("not the same element");
270         return false;
271     }
272 }
273 
ParseSelectAid(const std::vector<uint8_t> & data)274 std::string HostCardEmulationManager::ParseSelectAid(const std::vector<uint8_t>& data)
275 {
276     if (data.empty() || data.size() < SELECT_APDU_HDR_LENGTH + MINIMUM_AID_LENGTH) {
277         InfoLog("invalid data. Data size less than hdr length plus minumum length.");
278         return "";
279     }
280 
281     if (data[INDEX_CLASS_BYTE] == SELECT_00 && data[INDEX_CHAIN_INSTRUCTION] == INSTR_SELECT &&
282         data[INDEX_P1] == SELECT_P1) {
283         if (data[INDEX_3] != SELECT_00) {
284             InfoLog("not supported aid");
285             return "";
286         }
287 
288         int aidLength = data[INDEX_AID_LEN];
289         if (data.size() < SELECT_APDU_HDR_LENGTH + aidLength) {
290             InfoLog("invalid data. Data size less than hdr length plus aid declared length.");
291             return "";
292         }
293 
294         std::vector<uint8_t> aidVec(data.begin() + SELECT_APDU_HDR_LENGTH,
295                                     data.begin() + SELECT_APDU_HDR_LENGTH + aidLength);
296         return KITS::NfcSdkCommon::BytesVecToHexString(&aidVec[0], aidVec.size());
297     }
298 
299     return "";
300 }
301 
RegHceCmdCallback(const sptr<KITS::IHceCmdCallback> & callback,const std::string & type,Security::AccessToken::AccessTokenID callerToken)302 bool HostCardEmulationManager::RegHceCmdCallback(const sptr<KITS::IHceCmdCallback>& callback,
303                                                  const std::string& type,
304                                                  Security::AccessToken::AccessTokenID callerToken)
305 {
306     if (nfcService_.expired()) {
307         ErrorLog("RegHceCmdCallback: nfcService_ is nullptr.");
308         return false;
309     }
310     if (!nfcService_.lock()->IsNfcEnabled()) {
311         ErrorLog("RegHceCmdCallback: NFC not enabled, do not set ");
312         return false;
313     }
314     InfoLog("RegHceCmdCallback start, register size =%{public}zu.", bundleNameToHceCmdRegData_.size());
315     Security::AccessToken::HapTokenInfo hapTokenInfo;
316     int result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(callerToken, hapTokenInfo);
317 
318     InfoLog("get hap token info, result = %{public}d", result);
319     if (result) {
320         return false;
321     }
322     if (hapTokenInfo.bundleName.empty()) {
323         ErrorLog("RegHceCmdCallback: not got bundle name");
324         return false;
325     }
326     HostCardEmulationManager::HceCmdRegistryData regData;
327 
328     regData.callback_ = callback;
329     regData.callerToken_ = callerToken;
330     std::lock_guard<std::mutex> lock(regInfoMutex_);
331     if (bundleNameToHceCmdRegData_.find(hapTokenInfo.bundleName) != bundleNameToHceCmdRegData_.end()) {
332         InfoLog("override the register data for  %{public}s", hapTokenInfo.bundleName.c_str());
333     }
334     bundleNameToHceCmdRegData_[hapTokenInfo.bundleName] = regData;
335 
336     InfoLog("RegHceCmdCallback end, register size =%{public}zu.", bundleNameToHceCmdRegData_.size());
337     return true;
338 }
339 
SendHostApduData(std::string hexCmdData,bool raw,std::string & hexRespData,Security::AccessToken::AccessTokenID callerToken)340 bool HostCardEmulationManager::SendHostApduData(std::string hexCmdData, bool raw, std::string& hexRespData,
341                                                 Security::AccessToken::AccessTokenID callerToken)
342 {
343     if (nfcService_.expired()) {
344         ErrorLog("SendHostApduData: nfcService_ is nullptr.");
345         return false;
346     }
347     if (!nfcService_.lock()->IsNfcEnabled()) {
348         ErrorLog("SendHostApduData: NFC not enabled, do not send.");
349         return false;
350     }
351     if (!IsCorrespondentService(callerToken)) {
352         ErrorLog("SendHostApduData: not the connected app, do not send.");
353         return false;
354     }
355 
356     return nciCeProxy_.lock()->SendRawFrame(hexCmdData);
357 }
IsCorrespondentService(Security::AccessToken::AccessTokenID callerToken)358 bool HostCardEmulationManager::IsCorrespondentService(Security::AccessToken::AccessTokenID callerToken)
359 {
360     Security::AccessToken::HapTokenInfo hapTokenInfo;
361     int result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(callerToken, hapTokenInfo);
362 
363     InfoLog("get hap token info, result = %{public}d", result);
364 #ifdef VENDOR_APPLICATIONS_ENABLED
365     if (result) {
366         WarnLog("vendor application, allow to send raw frame.");
367         return true;
368     }
369 #endif
370     if (!hapTokenInfo.bundleName.empty() &&
371         hapTokenInfo.bundleName == abilityConnection_->GetConnectedElement().GetBundleName()) {
372         return true;
373     }
374     ErrorLog("SendHostApduData: diff app, the call app %{public}s , the connected app %{public}s",
375              hapTokenInfo.bundleName.c_str(), abilityConnection_->GetConnectedElement().GetBundleName().c_str());
376     return false;
377 }
378 
HandleQueueData()379 void HostCardEmulationManager::HandleQueueData()
380 {
381     bool shouldSendQueueData = hceState_ == HostCardEmulationManager::WAIT_FOR_SERVICE && !queueHceData_.empty();
382 
383     std::string queueData = KITS::NfcSdkCommon::BytesVecToHexString(&queueHceData_[0], queueHceData_.size());
384     InfoLog("RegHceCmdCallback queue data %{public}s, hceState= %{public}d, "
385             "service connected= %{public}d",
386             queueData.c_str(), hceState_, abilityConnection_->ServiceConnected());
387     if (shouldSendQueueData) {
388         InfoLog("RegHceCmdCallback should send queue data");
389         hceState_ = HostCardEmulationManager::DATA_TRANSFER;
390         SendDataToService(queueHceData_);
391         queueHceData_.clear();
392     }
393 }
394 
SendDataToService(const std::vector<uint8_t> & data)395 void HostCardEmulationManager::SendDataToService(const std::vector<uint8_t>& data)
396 {
397     std::string bundleName = abilityConnection_->GetConnectedElement().GetBundleName();
398     InfoLog("SendDataToService register size =%{public}zu.", bundleNameToHceCmdRegData_.size());
399     std::lock_guard<std::mutex> lock(regInfoMutex_);
400     auto it = bundleNameToHceCmdRegData_.find(bundleName);
401     if (it == bundleNameToHceCmdRegData_.end()) {
402         ErrorLog("no register data for %{public}s", abilityConnection_->GetConnectedElement().GetURI().c_str());
403         return;
404     }
405     if (it->second.callback_ == nullptr) {
406         ErrorLog("callback is null");
407         return;
408     }
409     it->second.callback_->OnCeApduData(data);
410 }
411 
DispatchAbilitySingleApp(ElementName & element)412 bool HostCardEmulationManager::DispatchAbilitySingleApp(ElementName& element)
413 {
414     abilityConnection_->SetHceManager(shared_from_this());
415     if (element.GetBundleName().empty()) {
416         ErrorLog("DispatchAbilitySingleApp element empty");
417         return false;
418     }
419 
420     InfoLog("DispatchAbilitySingleApp for element  %{public}s", element.GetURI().c_str());
421     AAFwk::Want want;
422     want.SetElement(element);
423 
424     if (AAFwk::AbilityManagerClient::GetInstance() == nullptr) {
425         ErrorLog("DispatchAbilitySingleApp AbilityManagerClient is null");
426         return false;
427     }
428     ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartAbilityByCall(want, abilityConnection_);
429     InfoLog("DispatchAbilitySingleApp call StartAbility end. ret = %{public}d", err);
430     if (err == ERR_NONE) {
431         ExternalDepsProxy::GetInstance().WriteHceSwipeResultHiSysEvent(element.GetBundleName(), DEFAULT_COUNT);
432         return true;
433     }
434     return false;
435 }
UnRegHceCmdCallback(const std::string & type,Security::AccessToken::AccessTokenID callerToken)436 bool HostCardEmulationManager::UnRegHceCmdCallback(const std::string& type,
437                                                    Security::AccessToken::AccessTokenID callerToken)
438 {
439     return EraseHceCmdCallback(callerToken);
440 }
EraseHceCmdCallback(Security::AccessToken::AccessTokenID callerToken)441 bool HostCardEmulationManager::EraseHceCmdCallback(Security::AccessToken::AccessTokenID callerToken)
442 {
443     InfoLog("EraseHceCmdCallback start, register size =%{public}zu.", bundleNameToHceCmdRegData_.size());
444     Security::AccessToken::HapTokenInfo hapTokenInfo;
445     int result = Security::AccessToken::AccessTokenKit::GetHapTokenInfo(callerToken, hapTokenInfo);
446 
447     InfoLog("get hap token info, result = %{public}d", result);
448     if (result) {
449         return false;
450     }
451     if (hapTokenInfo.bundleName.empty()) {
452         ErrorLog("EraseHceCmdCallback: not got bundle name");
453         return false;
454     }
455     std::lock_guard<std::mutex> lock(regInfoMutex_);
456 
457     if (bundleNameToHceCmdRegData_.find(hapTokenInfo.bundleName) != bundleNameToHceCmdRegData_.end()) {
458         InfoLog("unregister data for  %{public}s", hapTokenInfo.bundleName.c_str());
459     }
460     bundleNameToHceCmdRegData_.erase(hapTokenInfo.bundleName);
461     InfoLog("EraseHceCmdCallback end, register size =%{public}zu.", bundleNameToHceCmdRegData_.size());
462     return true;
463 }
464 
UnRegAllCallback(Security::AccessToken::AccessTokenID callerToken)465 bool HostCardEmulationManager::UnRegAllCallback(Security::AccessToken::AccessTokenID callerToken)
466 {
467     return EraseHceCmdCallback(callerToken);
468 }
469 } // namespace NFC
470 } // namespace OHOS