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(¶ms);
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