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