1 /******************************************************************************
2 *
3 * Copyright (C) 2018 ST Microelectronics S.A.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *
18 ******************************************************************************/
19 #define LOG_TAG "StEse-SecureElement"
20 #include "SecureElement.h"
21 #include <android_logmsg.h>
22 #include <dlfcn.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 typedef int (*STAram_init)(void);
28 typedef int (*StAram_Transceive)(StEse_data*, StEse_data*);
29 static StAram_Transceive Aram_transceive = nullptr;
30 static int aram_channel = 0;
31
32 extern bool ese_debug_enabled;
33 static bool OpenLogicalChannelProcessing = false;
34 static bool OpenBasicChannelProcessing = false;
35
36 namespace android {
37 namespace hardware {
38 namespace secure_element {
39 namespace V1_0 {
40 namespace implementation {
41
42 sp<V1_0::ISecureElementHalCallback> SecureElement::mCallbackV1_0 = nullptr;
43
SecureElement()44 SecureElement::SecureElement()
45 : mOpenedchannelCount(0), mOpenedChannels{false, false, false, false} {}
46
init(const sp<::android::hardware::secure_element::V1_0::ISecureElementHalCallback> & clientCallback)47 Return<void> SecureElement::init(
48 const sp<
49 ::android::hardware::secure_element::V1_0::ISecureElementHalCallback>&
50 clientCallback) {
51 ESESTATUS status = ESESTATUS_SUCCESS;
52 aram_channel = 0;
53 STLOG_HAL_D("%s: Enter", __func__);
54 if (clientCallback == nullptr) {
55 return Void();
56 } else {
57 mCallbackV1_0 = clientCallback;
58 if (!mCallbackV1_0->linkToDeath(this, 0 /*cookie*/)) {
59 STLOG_HAL_E("%s: Failed to register death notification", __func__);
60 }
61 }
62
63 if (isSeInitialized()) {
64 clientCallback->onStateChange(true);
65 return Void();
66 }
67
68 // Ignore this dlopen if you don't have libstpreprocess.so
69 #if defined(ST_LIB_32)
70 void* stdll = dlopen("/vendor/lib/libstpreprocess.so", RTLD_NOW);
71 #else
72 void* stdll = dlopen("/vendor/lib64/libstpreprocess.so", RTLD_NOW);
73 #endif
74 if (stdll) {
75 STAram_init fn_init = (STAram_init)dlsym(stdll, "STAram_init");
76 if (fn_init) {
77 if (ESESTATUS_SUCCESS == fn_init()) {
78 STLOG_HAL_D("%s: Enter", __func__);
79 Aram_transceive = (StAram_Transceive)dlsym(stdll, "StAram_Transceive");
80 } else {
81 Aram_transceive = nullptr;
82 STLOG_HAL_E("%s: Error in loading StAram_Transceive", __func__);
83 }
84 }
85 }
86
87 status = seHalInit();
88 if (status != ESESTATUS_SUCCESS) {
89 clientCallback->onStateChange(false);
90 return Void();
91 } else {
92 clientCallback->onStateChange(true);
93 return Void();
94 }
95 }
96
getAtr(getAtr_cb _hidl_cb)97 Return<void> SecureElement::getAtr(getAtr_cb _hidl_cb) {
98 STLOG_HAL_D("%s: Enter", __func__);
99 hidl_vec<uint8_t> response;
100 uint8_t* ATR;
101 ATR = StEse_getAtr();
102 if (ATR != nullptr) {
103 uint8_t len = *ATR;
104 if (len) {
105 response.resize(len);
106 memcpy(&response[0], ATR, len);
107 }
108 }
109 _hidl_cb(response);
110 return Void();
111 }
112
isCardPresent()113 Return<bool> SecureElement::isCardPresent() { return true; }
114
transmit(const hidl_vec<uint8_t> & data,transmit_cb _hidl_cb)115 Return<void> SecureElement::transmit(const hidl_vec<uint8_t>& data,
116 transmit_cb _hidl_cb) {
117 ESESTATUS status = ESESTATUS_FAILED;
118 StEse_data cmdApdu;
119 StEse_data rspApdu;
120 memset(&cmdApdu, 0x00, sizeof(StEse_data));
121 memset(&rspApdu, 0x00, sizeof(StEse_data));
122
123 STLOG_HAL_D("%s: Enter", __func__);
124 cmdApdu.len = data.size();
125 if (cmdApdu.len >= MIN_APDU_LENGTH) {
126 cmdApdu.p_data = (uint8_t*)malloc(data.size() * sizeof(uint8_t));
127 memcpy(cmdApdu.p_data, data.data(), cmdApdu.len);
128 /* Check aram_channel number after open logic channel */
129 if (aram_channel && (0x03 & cmdApdu.p_data[0]) == aram_channel &&
130 Aram_transceive) {
131 /* Replace responses for ARAM operations*/
132 status = (ESESTATUS)Aram_transceive(&cmdApdu, &rspApdu);
133 } else {
134 status = StEse_Transceive(&cmdApdu, &rspApdu);
135 }
136 }
137
138 hidl_vec<uint8_t> result;
139 if (status != ESESTATUS_SUCCESS) {
140 STLOG_HAL_E("%s: transmit failed!!!", __func__);
141 seHalResetSe();
142 } else {
143 result.resize(rspApdu.len);
144 memcpy(&result[0], rspApdu.p_data, rspApdu.len);
145 }
146 _hidl_cb(result);
147 free(cmdApdu.p_data);
148 free(rspApdu.p_data);
149 return Void();
150 }
151
openLogicalChannel(const hidl_vec<uint8_t> & aid,uint8_t p2,openLogicalChannel_cb _hidl_cb)152 Return<void> SecureElement::openLogicalChannel(const hidl_vec<uint8_t>& aid,
153 uint8_t p2,
154 openLogicalChannel_cb _hidl_cb) {
155 hidl_vec<uint8_t> manageChannelCommand = {0x00, 0x70, 0x00, 0x00, 0x01};
156 hidl_vec<uint8_t> ARA_M_AID = {0xA0, 0x00, 0x00, 0x01, 0x51,
157 0x41, 0x43, 0x4C, 0x00};
158 OpenLogicalChannelProcessing = true;
159 LogicalChannelResponse resApduBuff;
160 resApduBuff.channelNumber = 0xff;
161 memset(&resApduBuff, 0x00, sizeof(resApduBuff));
162 STLOG_HAL_D("%s: Enter", __func__);
163
164 if (aid.size() > 16) {
165 STLOG_HAL_E("%s: Invalid AID size: %u", __func__, (unsigned)aid.size());
166 _hidl_cb(resApduBuff, SecureElementStatus::FAILED);
167 OpenLogicalChannelProcessing = false;
168 return Void();
169 }
170
171 if (!isSeInitialized()) {
172 STLOG_HAL_D("%s: Enter SeInitialized", __func__);
173 ESESTATUS status = seHalInit();
174 if (status != ESESTATUS_SUCCESS) {
175 STLOG_HAL_E("%s: seHalInit Failed!!!", __func__);
176 _hidl_cb(resApduBuff, SecureElementStatus::IOERROR);
177 OpenLogicalChannelProcessing = false;
178 return Void();
179 }
180 }
181
182 SecureElementStatus sestatus = SecureElementStatus::FAILED;
183 ESESTATUS status = ESESTATUS_FAILED;
184 StEse_data cmdApdu;
185 StEse_data rspApdu;
186
187 memset(&cmdApdu, 0x00, sizeof(StEse_data));
188 memset(&rspApdu, 0x00, sizeof(StEse_data));
189
190 cmdApdu.len = manageChannelCommand.size();
191 cmdApdu.p_data =
192 (uint8_t*)malloc(manageChannelCommand.size() * sizeof(uint8_t));
193 if (cmdApdu.p_data != NULL) {
194 memcpy(cmdApdu.p_data, manageChannelCommand.data(), cmdApdu.len);
195 status = StEse_Transceive(&cmdApdu, &rspApdu);
196 }
197 if (status != ESESTATUS_SUCCESS) {
198 /*Transceive failed*/
199 sestatus = SecureElementStatus::IOERROR;
200 } else if (rspApdu.p_data[rspApdu.len - 2] == 0x90 &&
201 rspApdu.p_data[rspApdu.len - 1] == 0x00) {
202 /*ManageChannel successful*/
203 resApduBuff.channelNumber = rspApdu.p_data[0];
204 mOpenedchannelCount++;
205 mOpenedChannels[resApduBuff.channelNumber] = true;
206 sestatus = SecureElementStatus::SUCCESS;
207 if (ARA_M_AID == aid) {
208 STLOG_HAL_D("%s: ARAM AID match", __func__);
209 aram_channel = resApduBuff.channelNumber;
210 } else {
211 /* Clear aram_channel number */
212 if (aram_channel == resApduBuff.channelNumber) aram_channel = 0;
213 }
214 } else if (rspApdu.p_data[rspApdu.len - 2] == 0x6A &&
215 rspApdu.p_data[rspApdu.len - 1] == 0x81) {
216 sestatus = SecureElementStatus::CHANNEL_NOT_AVAILABLE;
217 } else if (((rspApdu.p_data[rspApdu.len - 2] == 0x6E) ||
218 (rspApdu.p_data[rspApdu.len - 2] == 0x6D)) &&
219 rspApdu.p_data[rspApdu.len - 1] == 0x00) {
220 sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
221 }
222 /*Free the allocations*/
223 free(cmdApdu.p_data);
224 cmdApdu.p_data = NULL;
225 free(rspApdu.p_data);
226 rspApdu.p_data = NULL;
227 if (sestatus != SecureElementStatus::SUCCESS) {
228 /* if the SE is unresponsive, reset it */
229 if (sestatus == SecureElementStatus::IOERROR) {
230 seHalResetSe();
231 }
232
233 /*If manageChannel is failed in any of above cases
234 send the callback and return*/
235 _hidl_cb(resApduBuff, sestatus);
236 STLOG_HAL_E("%s: Exit - manage channel failed!!", __func__);
237 OpenLogicalChannelProcessing = false;
238 return Void();
239 }
240
241 STLOG_HAL_D("%s: Sending selectApdu", __func__);
242 /*Reset variables if manageChannel is success*/
243 sestatus = SecureElementStatus::FAILED;
244 status = ESESTATUS_FAILED;
245
246 memset(&cmdApdu, 0x00, sizeof(StEse_data));
247 memset(&rspApdu, 0x00, sizeof(StEse_data));
248
249 cmdApdu.len = (int32_t)(6 + aid.size());
250 cmdApdu.p_data = (uint8_t*)malloc(cmdApdu.len * sizeof(uint8_t));
251 if (cmdApdu.p_data != NULL) {
252 uint8_t xx = 0;
253 cmdApdu.p_data[xx++] = resApduBuff.channelNumber;
254 cmdApdu.p_data[xx++] = 0xA4; // INS
255 cmdApdu.p_data[xx++] = 0x04; // P1
256 cmdApdu.p_data[xx++] = p2; // P2
257 cmdApdu.p_data[xx++] = aid.size(); // Lc
258 memcpy(&cmdApdu.p_data[xx], aid.data(), aid.size());
259 cmdApdu.p_data[xx + aid.size()] = 0x00; // Le
260
261 if (Aram_transceive && (aram_channel == resApduBuff.channelNumber)) {
262 status = (ESESTATUS)Aram_transceive(&cmdApdu, &rspApdu);
263 } else {
264 status = StEse_Transceive(&cmdApdu, &rspApdu);
265 }
266 }
267
268 if (status != ESESTATUS_SUCCESS) {
269 /*Transceive failed*/
270 sestatus = SecureElementStatus::IOERROR;
271 } else {
272 uint8_t sw1 = rspApdu.p_data[rspApdu.len - 2];
273 uint8_t sw2 = rspApdu.p_data[rspApdu.len - 1];
274 /*Return response on success, empty vector on failure*/
275 /*Status is success*/
276 if (sw1 == 0x90 && sw2 == 0x00) {
277 /*Copy the response including status word*/
278 resApduBuff.selectResponse.resize(rspApdu.len);
279 memcpy(&resApduBuff.selectResponse[0], rspApdu.p_data, rspApdu.len);
280 sestatus = SecureElementStatus::SUCCESS;
281 }
282 /*AID provided doesn't match any applet on the secure element*/
283 else if (sw1 == 0x6A && sw2 == 0x82) {
284 sestatus = SecureElementStatus::NO_SUCH_ELEMENT_ERROR;
285 }
286 /*Operation provided by the P2 parameter is not permitted by the applet.*/
287 else if (sw1 == 0x6A && sw2 == 0x86) {
288 sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
289 }
290 }
291
292 if (sestatus != SecureElementStatus::SUCCESS) {
293 /* if the SE is unresponsive, reset it */
294 if (sestatus == SecureElementStatus::IOERROR) {
295 seHalResetSe();
296 } else {
297 STLOG_HAL_E("%s: Select APDU failed! Close channel..", __func__);
298 SecureElementStatus closeChannelStatus =
299 closeChannel(resApduBuff.channelNumber);
300 if (closeChannelStatus != SecureElementStatus::SUCCESS) {
301 STLOG_HAL_E("%s: closeChannel Failed", __func__);
302 } else {
303 resApduBuff.channelNumber = 0xff;
304 }
305 }
306 }
307 _hidl_cb(resApduBuff, sestatus);
308 free(cmdApdu.p_data);
309 free(rspApdu.p_data);
310 STLOG_HAL_V("%s: Exit", __func__);
311 OpenLogicalChannelProcessing = false;
312 return Void();
313 }
314
openBasicChannel(const hidl_vec<uint8_t> & aid,uint8_t p2,openBasicChannel_cb _hidl_cb)315 Return<void> SecureElement::openBasicChannel(const hidl_vec<uint8_t>& aid,
316 uint8_t p2,
317 openBasicChannel_cb _hidl_cb) {
318 hidl_vec<uint8_t> result;
319 OpenBasicChannelProcessing = true;
320 STLOG_HAL_D("%s: Enter", __func__);
321
322 if (aid.size() > 16) {
323 STLOG_HAL_E("%s: Invalid AID size: %u", __func__, (unsigned)aid.size());
324 _hidl_cb(result, SecureElementStatus::FAILED);
325 OpenBasicChannelProcessing = false;
326 return Void();
327 }
328
329 if (!isSeInitialized()) {
330 ESESTATUS status = seHalInit();
331 if (status != ESESTATUS_SUCCESS) {
332 STLOG_HAL_E("%s: seHalInit Failed!!!", __func__);
333 _hidl_cb(result, SecureElementStatus::IOERROR);
334 OpenBasicChannelProcessing = false;
335 return Void();
336 }
337 }
338
339 SecureElementStatus sestatus = SecureElementStatus::FAILED;
340 ESESTATUS status = ESESTATUS_FAILED;
341 StEse_data cmdApdu;
342 StEse_data rspApdu;
343
344 memset(&cmdApdu, 0x00, sizeof(StEse_data));
345 memset(&rspApdu, 0x00, sizeof(StEse_data));
346
347 cmdApdu.len = (int32_t)(6 + aid.size());
348 cmdApdu.p_data = (uint8_t*)malloc(cmdApdu.len * sizeof(uint8_t));
349 if (cmdApdu.p_data != NULL) {
350 uint8_t xx = 0;
351 cmdApdu.p_data[xx++] = 0x00; // basic channel
352 cmdApdu.p_data[xx++] = 0xA4; // INS
353 cmdApdu.p_data[xx++] = 0x04; // P1
354 cmdApdu.p_data[xx++] = p2; // P2
355 cmdApdu.p_data[xx++] = aid.size(); // Lc
356 memcpy(&cmdApdu.p_data[xx], aid.data(), aid.size());
357 cmdApdu.p_data[xx + aid.size()] = 0x00; // Le
358
359 status = StEse_Transceive(&cmdApdu, &rspApdu);
360 }
361
362 if (status != ESESTATUS_SUCCESS) {
363 /* Transceive failed */
364 sestatus = SecureElementStatus::IOERROR;
365 } else {
366 uint8_t sw1 = rspApdu.p_data[rspApdu.len - 2];
367 uint8_t sw2 = rspApdu.p_data[rspApdu.len - 1];
368 /*Return response on success, empty vector on failure*/
369 /*Status is success*/
370 if ((sw1 == 0x90) && (sw2 == 0x00)) {
371 /*Copy the response including status word*/
372 result.resize(rspApdu.len);
373 memcpy(&result[0], rspApdu.p_data, rspApdu.len);
374 /*Set basic channel reference if it is not set */
375 if (!mOpenedChannels[0]) {
376 mOpenedChannels[0] = true;
377 mOpenedchannelCount++;
378 }
379 sestatus = SecureElementStatus::SUCCESS;
380 }
381 /*AID provided doesn't match any applet on the secure element*/
382 else if (sw1 == 0x6A && sw2 == 0x82) {
383 sestatus = SecureElementStatus::NO_SUCH_ELEMENT_ERROR;
384 }
385 /*Operation provided by the P2 parameter is not permitted by the applet.*/
386 else if (sw1 == 0x6A && sw2 == 0x86) {
387 sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
388 }
389 }
390
391 /* if the SE is unresponsive, reset it */
392 if (sestatus == SecureElementStatus::IOERROR) {
393 seHalResetSe();
394 }
395
396 if ((sestatus != SecureElementStatus::SUCCESS) && mOpenedChannels[0]) {
397 SecureElementStatus closeChannelStatus =
398 closeChannel(DEFAULT_BASIC_CHANNEL);
399 if (closeChannelStatus != SecureElementStatus::SUCCESS) {
400 STLOG_HAL_E("%s: closeChannel Failed", __func__);
401 }
402 }
403 _hidl_cb(result, sestatus);
404 free(cmdApdu.p_data);
405 free(rspApdu.p_data);
406 STLOG_HAL_V("%s: Exit", __func__);
407 OpenBasicChannelProcessing = false;
408 return Void();
409 }
410
411 Return<::android::hardware::secure_element::V1_0::SecureElementStatus>
closeChannel(uint8_t channelNumber)412 SecureElement::closeChannel(uint8_t channelNumber) {
413 ESESTATUS status = ESESTATUS_FAILED;
414 SecureElementStatus sestatus = SecureElementStatus::FAILED;
415
416 StEse_data cmdApdu;
417 StEse_data rspApdu;
418
419 STLOG_HAL_D("%s: Enter : %d", __func__, channelNumber);
420
421 if ((channelNumber < DEFAULT_BASIC_CHANNEL) ||
422 (channelNumber >= MAX_LOGICAL_CHANNELS) ||
423 (mOpenedChannels[channelNumber] == false)) {
424 STLOG_HAL_E("%s: invalid channel!!!", __func__);
425 sestatus = SecureElementStatus::FAILED;
426 } else if (channelNumber > DEFAULT_BASIC_CHANNEL) {
427 /* Reset aram_channel to 0 */
428 if (channelNumber == aram_channel) aram_channel = 0;
429
430 memset(&cmdApdu, 0x00, sizeof(StEse_data));
431 memset(&rspApdu, 0x00, sizeof(StEse_data));
432 cmdApdu.p_data = (uint8_t*)malloc(5 * sizeof(uint8_t));
433 if (cmdApdu.p_data != NULL) {
434 uint8_t xx = 0;
435
436 cmdApdu.p_data[xx++] = channelNumber;
437 cmdApdu.p_data[xx++] = 0x70; // INS
438 cmdApdu.p_data[xx++] = 0x80; // P1
439 cmdApdu.p_data[xx++] = channelNumber; // P2
440 cmdApdu.p_data[xx++] = 0x00; // Lc
441 cmdApdu.len = xx;
442
443 status = StEse_Transceive(&cmdApdu, &rspApdu);
444 }
445 if (status != ESESTATUS_SUCCESS) {
446 sestatus = SecureElementStatus::FAILED;
447 } else if ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
448 (rspApdu.p_data[rspApdu.len - 1] == 0x00)) {
449 sestatus = SecureElementStatus::SUCCESS;
450 } else {
451 sestatus = SecureElementStatus::FAILED;
452 }
453 free(cmdApdu.p_data);
454 free(rspApdu.p_data);
455 }
456
457 if ((channelNumber == DEFAULT_BASIC_CHANNEL) ||
458 (sestatus == SecureElementStatus::SUCCESS)) {
459 mOpenedChannels[channelNumber] = false;
460 mOpenedchannelCount--;
461 /*If there are no channels remaining close secureElement*/
462 if ((mOpenedchannelCount == 0) && !OpenLogicalChannelProcessing &&
463 !OpenBasicChannelProcessing) {
464 sestatus = seHalDeInit();
465 } else {
466 sestatus = SecureElementStatus::SUCCESS;
467 }
468 }
469
470 STLOG_HAL_V("%s: Exit", __func__);
471 return sestatus;
472 }
473
serviceDied(uint64_t,const wp<IBase> &)474 void SecureElement::serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) {
475 STLOG_HAL_E("%s: SecureElement serviceDied!!!", __func__);
476 /* Reset aram_channel to 0 */
477 aram_channel = 0;
478 SecureElementStatus sestatus = seHalDeInit();
479 if (sestatus != SecureElementStatus::SUCCESS) {
480 STLOG_HAL_E("%s: seHalDeInit Faliled!!!", __func__);
481 }
482 if (mCallbackV1_0 != nullptr) {
483 mCallbackV1_0->unlinkToDeath(this);
484 }
485 }
486
isSeInitialized()487 bool SecureElement::isSeInitialized() { return StEseApi_isOpen(); }
488
seHalInit()489 ESESTATUS SecureElement::seHalInit() {
490 ESESTATUS status = ESESTATUS_SUCCESS;
491
492 STLOG_HAL_D("%s: Enter", __func__);
493 aram_channel = 0;
494 status = StEse_init();
495 if (status != ESESTATUS_SUCCESS) {
496 STLOG_HAL_E("%s: SecureElement open failed!!!", __func__);
497 }
498 STLOG_HAL_V("%s: Exit", __func__);
499 return status;
500 }
501
seHalResetSe()502 void SecureElement::seHalResetSe() {
503 ESESTATUS status = ESESTATUS_SUCCESS;
504
505 STLOG_HAL_D("%s: Enter", __func__);
506 if (!isSeInitialized()) {
507 ESESTATUS status = seHalInit();
508 if (status != ESESTATUS_SUCCESS) {
509 STLOG_HAL_E("%s: seHalInit Failed!!!", __func__);
510 }
511 }
512
513 if (status == ESESTATUS_SUCCESS) {
514 mCallbackV1_0->onStateChange(false);
515
516 status = StEse_Reset();
517 if (status != ESESTATUS_SUCCESS) {
518 STLOG_HAL_E("%s: SecureElement reset failed!!", __func__);
519 } else {
520 for (uint8_t xx = 0; xx < MAX_LOGICAL_CHANNELS; xx++) {
521 mOpenedChannels[xx] = false;
522 }
523 mOpenedchannelCount = 0;
524 mCallbackV1_0->onStateChange(true);
525 }
526 }
527 STLOG_HAL_V("%s: Exit", __func__);
528 }
529
530 Return<::android::hardware::secure_element::V1_0::SecureElementStatus>
seHalDeInit()531 SecureElement::seHalDeInit() {
532 STLOG_HAL_D("%s: Enter", __func__);
533 ESESTATUS status = ESESTATUS_SUCCESS;
534 SecureElementStatus sestatus = SecureElementStatus::FAILED;
535 status = StEse_close();
536 if (status != ESESTATUS_SUCCESS) {
537 sestatus = SecureElementStatus::FAILED;
538 } else {
539 sestatus = SecureElementStatus::SUCCESS;
540
541 for (uint8_t xx = 0; xx < MAX_LOGICAL_CHANNELS; xx++) {
542 mOpenedChannels[xx] = false;
543 }
544 mOpenedchannelCount = 0;
545 }
546 STLOG_HAL_V("%s: Exit", __func__);
547 return sestatus;
548 }
549
550 } // namespace implementation
551 } // namespace V1_0
552 } // namespace secure_element
553 } // namespace hardware
554 } // namespace android
555