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