1 /******************************************************************************
2  *
3  *  Copyright 2018-2020 NXP
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 #include "VirtualISO.h"
19 #include <android-base/logging.h>
20 #include "NxpEse.h"
21 #include "SecureElement.h"
22 #include "eSEClient.h"
23 #include "hal_nxpese.h"
24 #include "phNxpEse_Apdu_Api.h"
25 #include "phNxpEse_Api.h"
26 using vendor::nxp::nxpese::V1_0::implementation::NxpEse;
27 namespace vendor {
28 namespace nxp {
29 namespace virtual_iso {
30 namespace V1_0 {
31 namespace implementation {
32 
33 #define LOG_TAG "nxpVIsoese@1.0-service"
34 
35 #define DEFAULT_BASIC_CHANNEL 0x00
36 
37 typedef struct gsTransceiveBuffer {
38   phNxpEse_data cmdData;
39   phNxpEse_data rspData;
40   hidl_vec<uint8_t>* pRspDataBuff;
41 } sTransceiveBuffer_t;
42 
43 static sTransceiveBuffer_t gsTxRxBuffer;
44 static hidl_vec<uint8_t> gsRspDataBuff(256);
45 static android::sp<ISecureElementHalCallback> cCallback;
46 std::vector<bool> VirtualISO::mOpenedChannels;
47 
VirtualISO()48 VirtualISO::VirtualISO()
49     : mMaxChannelCount(0), mOpenedchannelCount(0), mIsEseInitialized(false) {}
50 
init(const sp<::android::hardware::secure_element::V1_0::ISecureElementHalCallback> & clientCallback)51 Return<void> VirtualISO::init(
52     const sp<
53         ::android::hardware::secure_element::V1_0::ISecureElementHalCallback>&
54         clientCallback) {
55   ESESTATUS status = ESESTATUS_SUCCESS;
56   ESESTATUS deInitStatus = ESESTATUS_SUCCESS;
57   bool mIsInitDone = false;
58   phNxpEse_initParams initParams;
59   LOG(INFO) << "Virtual ISO::init Enter";
60   gsTxRxBuffer.pRspDataBuff = &gsRspDataBuff;
61   memset(&initParams, 0x00, sizeof(phNxpEse_initParams));
62   initParams.initMode = ESE_MODE_NORMAL;
63   initParams.mediaType = ESE_PROTOCOL_MEDIA_SPI_APDU_GATE;
64 
65   if (clientCallback == nullptr) {
66     return Void();
67   } else {
68     clientCallback->linkToDeath(this, 0 /*cookie*/);
69   }
70   if (ese_update != ESE_UPDATE_COMPLETED) {
71     cCallback = clientCallback;
72     clientCallback->onStateChange(false);
73     LOG(INFO) << "ESE JCOP Download in progress";
74     NxpEse::setVirtualISOCallBack(clientCallback);
75     return Void();
76     // Register
77   }
78   if (mIsEseInitialized) {
79     clientCallback->onStateChange(true);
80     return Void();
81   }
82   status = phNxpEse_open(initParams);
83   if (status == ESESTATUS_SUCCESS || ESESTATUS_BUSY == status) {
84     if (ESESTATUS_SUCCESS == phNxpEse_SetEndPoint_Cntxt(1) &&
85         ESESTATUS_SUCCESS == phNxpEse_init(initParams)) {
86       if (ESESTATUS_SUCCESS == phNxpEse_ResetEndPoint_Cntxt(1)) {
87         LOG(INFO) << "VISO init complete!!!";
88         mIsInitDone = true;
89       }
90       deInitStatus = phNxpEse_deInit();
91       if (ESESTATUS_SUCCESS != deInitStatus) mIsInitDone = false;
92     }
93     status = phNxpEse_close(deInitStatus);
94   }
95   if (status == ESESTATUS_SUCCESS && mIsInitDone) {
96     mMaxChannelCount = (GET_CHIP_OS_VERSION() >= OS_VERSION_6_2) ? 0x0C : 0x04;
97     mOpenedChannels.resize(mMaxChannelCount, false);
98     clientCallback->onStateChange(true);
99   } else {
100     LOG(ERROR) << "VISO-Hal Init failed";
101     clientCallback->onStateChange(false);
102   }
103   return Void();
104 }
105 
getAtr(getAtr_cb _hidl_cb)106 Return<void> VirtualISO::getAtr(getAtr_cb _hidl_cb) {
107   hidl_vec<uint8_t> response;
108   _hidl_cb(response);
109   return Void();
110 }
111 
isCardPresent()112 Return<bool> VirtualISO::isCardPresent() { return true; }
113 
transmit(const hidl_vec<uint8_t> & data,transmit_cb _hidl_cb)114 Return<void> VirtualISO::transmit(const hidl_vec<uint8_t>& data,
115                                   transmit_cb _hidl_cb) {
116   ESESTATUS status = ESESTATUS_FAILED;
117   hidl_vec<uint8_t> result;
118   phNxpEse_memset(&gsTxRxBuffer.cmdData, 0x00, sizeof(phNxpEse_data));
119   phNxpEse_memset(&gsTxRxBuffer.rspData, 0x00, sizeof(phNxpEse_data));
120   gsTxRxBuffer.cmdData.len = data.size();
121   gsTxRxBuffer.cmdData.p_data =
122       (uint8_t*)phNxpEse_memalloc(data.size() * sizeof(uint8_t));
123   if (NULL == gsTxRxBuffer.cmdData.p_data) {
124     LOG(ERROR) << "transmit failed to allocate the Memory!!!";
125     /*Return empty hidl_vec*/
126     _hidl_cb(result);
127     return Void();
128   }
129   memcpy(gsTxRxBuffer.cmdData.p_data, data.data(), gsTxRxBuffer.cmdData.len);
130   LOG(ERROR) << "Acquired the lock in VISO ";
131   status = phNxpEse_SetEndPoint_Cntxt(1);
132   if (status != ESESTATUS_SUCCESS) {
133     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
134   }
135   status = phNxpEse_Transceive(&gsTxRxBuffer.cmdData, &gsTxRxBuffer.rspData);
136 
137   if (status != ESESTATUS_SUCCESS) {
138     LOG(ERROR) << "transmit failed!!!";
139   } else {
140     result.resize(gsTxRxBuffer.rspData.len);
141     memcpy(&result[0], gsTxRxBuffer.rspData.p_data, gsTxRxBuffer.rspData.len);
142   }
143   status = phNxpEse_ResetEndPoint_Cntxt(1);
144   if (status != ESESTATUS_SUCCESS) {
145     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
146   }
147 
148   _hidl_cb(result);
149   if (NULL != gsTxRxBuffer.cmdData.p_data) {
150     phNxpEse_free(gsTxRxBuffer.cmdData.p_data);
151     gsTxRxBuffer.cmdData.p_data = NULL;
152   }
153   if (NULL != gsTxRxBuffer.rspData.p_data) {
154     phNxpEse_free(gsTxRxBuffer.rspData.p_data);
155     gsTxRxBuffer.rspData.p_data = NULL;
156   }
157 
158   return Void();
159 }
160 
openLogicalChannel(const hidl_vec<uint8_t> & aid,uint8_t p2,openLogicalChannel_cb _hidl_cb)161 Return<void> VirtualISO::openLogicalChannel(const hidl_vec<uint8_t>& aid,
162                                             uint8_t p2,
163                                             openLogicalChannel_cb _hidl_cb) {
164   hidl_vec<uint8_t> manageChannelCommand = {0x00, 0x70, 0x00, 0x00, 0x01};
165 
166   LogicalChannelResponse resApduBuff;
167 
168   LOG(INFO) << "Acquired the lock in VISO openLogicalChannel";
169 
170   resApduBuff.channelNumber = 0xff;
171   memset(&resApduBuff, 0x00, sizeof(resApduBuff));
172   if (!mIsEseInitialized) {
173     ESESTATUS status = seHalInit();
174     if (status != ESESTATUS_SUCCESS) {
175       LOG(ERROR) << "%s: seHalInit Failed!!!" << __func__;
176       _hidl_cb(resApduBuff, SecureElementStatus::IOERROR);
177       return Void();
178     }
179   }
180 
181   SecureElementStatus sestatus = SecureElementStatus::IOERROR;
182   ESESTATUS status = ESESTATUS_FAILED;
183   phNxpEse_data cmdApdu;
184   phNxpEse_data rspApdu;
185 
186   phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
187   phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
188 
189   cmdApdu.len = manageChannelCommand.size();
190   cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(manageChannelCommand.size() *
191                                                sizeof(uint8_t));
192   memcpy(cmdApdu.p_data, manageChannelCommand.data(), cmdApdu.len);
193 
194   memset(&sestatus, 0x00, sizeof(sestatus));
195 
196   status = phNxpEse_SetEndPoint_Cntxt(1);
197   if (status != ESESTATUS_SUCCESS) {
198     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
199   }
200   status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
201   if (status != ESESTATUS_SUCCESS) {
202     resApduBuff.channelNumber = 0xff;
203     if (NULL != rspApdu.p_data && rspApdu.len > 0) {
204       if ((rspApdu.p_data[0] == 0x64 && rspApdu.p_data[1] == 0xFF)) {
205         sestatus = SecureElementStatus::IOERROR;
206       }
207     }
208     if (SecureElementStatus::IOERROR != sestatus) {
209       sestatus = SecureElementStatus::FAILED;
210     }
211   } else if (rspApdu.p_data[rspApdu.len - 2] == 0x6A &&
212              rspApdu.p_data[rspApdu.len - 1] == 0x81) {
213     resApduBuff.channelNumber = 0xff;
214     sestatus = SecureElementStatus::CHANNEL_NOT_AVAILABLE;
215   } else if (rspApdu.p_data[rspApdu.len - 2] == 0x90 &&
216              rspApdu.p_data[rspApdu.len - 1] == 0x00) {
217     resApduBuff.channelNumber = rspApdu.p_data[0];
218     mOpenedchannelCount++;
219     mOpenedChannels[resApduBuff.channelNumber] = true;
220     sestatus = SecureElementStatus::SUCCESS;
221   } else if (((rspApdu.p_data[rspApdu.len - 2] == 0x6E) ||
222               (rspApdu.p_data[rspApdu.len - 2] == 0x6D)) &&
223              rspApdu.p_data[rspApdu.len - 1] == 0x00) {
224     sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
225   }
226 
227   /*Free the allocations*/
228   phNxpEse_free(cmdApdu.p_data);
229   phNxpEse_free(rspApdu.p_data);
230 
231   if (sestatus != SecureElementStatus::SUCCESS) {
232     if (mOpenedchannelCount == 0) {
233       sestatus = seHalDeInit();
234       if (sestatus != SecureElementStatus::SUCCESS) {
235         LOG(INFO) << "seDeInit Failed";
236       }
237     }
238     /*If manageChanle is failed in any of above cases
239     send the callback and return*/
240     status = phNxpEse_ResetEndPoint_Cntxt(1);
241     if (status != ESESTATUS_SUCCESS) {
242       LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
243     }
244     _hidl_cb(resApduBuff, sestatus);
245     return Void();
246   }
247   LOG(INFO) << "openLogicalChannel Sending selectApdu";
248   sestatus = SecureElementStatus::IOERROR;
249   status = ESESTATUS_FAILED;
250 
251   phNxpEse_7816_cpdu_t cpdu;
252   phNxpEse_7816_rpdu_t rpdu;
253   phNxpEse_memset(&cpdu, 0x00, sizeof(phNxpEse_7816_cpdu_t));
254   phNxpEse_memset(&rpdu, 0x00, sizeof(phNxpEse_7816_rpdu_t));
255 
256   if ((resApduBuff.channelNumber > 0x03) &&
257       (resApduBuff.channelNumber < 0x14)) {
258     /* update CLA byte accoridng to GP spec Table 11-12*/
259     cpdu.cla =
260         0x40 + (resApduBuff.channelNumber - 4); /* Class of instruction */
261   } else if ((resApduBuff.channelNumber > 0x00) &&
262              (resApduBuff.channelNumber < 0x04)) {
263     /* update CLA byte accoridng to GP spec Table 11-11*/
264     cpdu.cla = resApduBuff.channelNumber; /* Class of instruction */
265   } else {
266     LOG(ERROR) << StringPrintf("%s: Invalid Channel no: %02x", __func__,
267                                resApduBuff.channelNumber);
268     resApduBuff.channelNumber = 0xff;
269     _hidl_cb(resApduBuff, SecureElementStatus::IOERROR);
270     return Void();
271   }
272   cpdu.ins = 0xA4; /* Instruction code */
273   cpdu.p1 = 0x04;  /* Instruction parameter 1 */
274   cpdu.p2 = p2;    /* Instruction parameter 2 */
275   cpdu.lc = aid.size();
276   cpdu.le_type = 0x01;
277   cpdu.pdata = (uint8_t*)phNxpEse_memalloc(aid.size() * sizeof(uint8_t));
278   memcpy(cpdu.pdata, aid.data(), cpdu.lc);
279   cpdu.le = 256;
280 
281   rpdu.len = 0x02;
282   rpdu.pdata = (uint8_t*)phNxpEse_memalloc(cpdu.le * sizeof(uint8_t));
283 
284   status = phNxpEse_7816_Transceive(&cpdu, &rpdu);
285   if (status != ESESTATUS_SUCCESS) {
286     /*Transceive failed*/
287     if (rpdu.len > 0 && (rpdu.sw1 == 0x64 && rpdu.sw2 == 0xFF)) {
288       sestatus = SecureElementStatus::IOERROR;
289     } else {
290       sestatus = SecureElementStatus::FAILED;
291     }
292   } else {
293     /*Status word to be passed as part of response
294     So include additional length*/
295     uint16_t responseLen = rpdu.len + 2;
296     resApduBuff.selectResponse.resize(responseLen);
297     memcpy(&resApduBuff.selectResponse[0], rpdu.pdata, rpdu.len);
298     resApduBuff.selectResponse[responseLen - 1] = rpdu.sw2;
299     resApduBuff.selectResponse[responseLen - 2] = rpdu.sw1;
300 
301     /*Status is success*/
302     if (rpdu.sw1 == 0x90 && rpdu.sw2 == 0x00) {
303       sestatus = SecureElementStatus::SUCCESS;
304     }
305     /*AID provided doesn't match any applet on the secure element*/
306     else if (rpdu.sw1 == 0x6A && rpdu.sw2 == 0x82) {
307       sestatus = SecureElementStatus::NO_SUCH_ELEMENT_ERROR;
308     }
309     /*Operation provided by the P2 parameter is not permitted by the applet.*/
310     else if (rpdu.sw1 == 0x6A && rpdu.sw2 == 0x86) {
311       sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
312     } else {
313       sestatus = SecureElementStatus::FAILED;
314     }
315   }
316   if (sestatus != SecureElementStatus::SUCCESS) {
317     SecureElementStatus closeChannelStatus =
318         internalCloseChannel(resApduBuff.channelNumber);
319     if (closeChannelStatus != SecureElementStatus::SUCCESS) {
320       LOG(ERROR) << "%s: closeChannel Failed" << __func__;
321     } else {
322       resApduBuff.channelNumber = 0xff;
323     }
324   }
325   status = phNxpEse_ResetEndPoint_Cntxt(1);
326   if (status != ESESTATUS_SUCCESS) {
327     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
328   }
329   _hidl_cb(resApduBuff, sestatus);
330   phNxpEse_free(cpdu.pdata);
331   phNxpEse_free(rpdu.pdata);
332 
333   return Void();
334 }
335 
openBasicChannel(const hidl_vec<uint8_t> & aid,uint8_t p2,openBasicChannel_cb _hidl_cb)336 Return<void> VirtualISO::openBasicChannel(const hidl_vec<uint8_t>& aid,
337                                           uint8_t p2,
338                                           openBasicChannel_cb _hidl_cb) {
339   ESESTATUS status = ESESTATUS_SUCCESS;
340   phNxpEse_7816_cpdu_t cpdu;
341   phNxpEse_7816_rpdu_t rpdu;
342   hidl_vec<uint8_t> result;
343 
344   LOG(INFO) << "Acquired the lock in VISO openBasicChannel";
345 
346   if (!mIsEseInitialized) {
347     ESESTATUS status = seHalInit();
348     if (status != ESESTATUS_SUCCESS) {
349       LOG(ERROR) << "%s: seHalInit Failed!!!" << __func__;
350       _hidl_cb(result, SecureElementStatus::IOERROR);
351       return Void();
352     }
353   }
354 
355   phNxpEse_memset(&cpdu, 0x00, sizeof(phNxpEse_7816_cpdu_t));
356   phNxpEse_memset(&rpdu, 0x00, sizeof(phNxpEse_7816_rpdu_t));
357 
358   cpdu.cla = 0x00; /* Class of instruction */
359   cpdu.ins = 0xA4; /* Instruction code */
360   cpdu.p1 = 0x04;  /* Instruction parameter 1 */
361   cpdu.p2 = p2;    /* Instruction parameter 2 */
362   cpdu.lc = aid.size();
363   cpdu.le_type = 0x01;
364   cpdu.pdata = (uint8_t*)phNxpEse_memalloc(aid.size() * sizeof(uint8_t));
365   memcpy(cpdu.pdata, aid.data(), cpdu.lc);
366   cpdu.le = 256;
367 
368   rpdu.len = 0x02;
369   rpdu.pdata = (uint8_t*)phNxpEse_memalloc(cpdu.le * sizeof(uint8_t));
370 
371   status = phNxpEse_SetEndPoint_Cntxt(1);
372   status = phNxpEse_7816_Transceive(&cpdu, &rpdu);
373 
374   SecureElementStatus sestatus;
375   memset(&sestatus, 0x00, sizeof(sestatus));
376 
377   if (status != ESESTATUS_SUCCESS) {
378     /* Transceive failed */
379     if (rpdu.len > 0 && (rpdu.sw1 == 0x64 && rpdu.sw2 == 0xFF)) {
380       sestatus = SecureElementStatus::IOERROR;
381     } else {
382       sestatus = SecureElementStatus::FAILED;
383     }
384   } else {
385     /*Status word to be passed as part of response
386     So include additional length*/
387     uint16_t responseLen = rpdu.len + 2;
388     result.resize(responseLen);
389     memcpy(&result[0], rpdu.pdata, rpdu.len);
390     result[responseLen - 1] = rpdu.sw2;
391     result[responseLen - 2] = rpdu.sw1;
392 
393     /*Status is success*/
394     if ((rpdu.sw1 == 0x90) && (rpdu.sw2 == 0x00)) {
395       /*Set basic channel reference if it is not set */
396       if (!mOpenedChannels[0]) {
397         mOpenedChannels[0] = true;
398         mOpenedchannelCount++;
399       }
400 
401       sestatus = SecureElementStatus::SUCCESS;
402     }
403     /*AID provided doesn't match any applet on the secure element*/
404     else if (rpdu.sw1 == 0x6A && rpdu.sw2 == 0x82) {
405       sestatus = SecureElementStatus::NO_SUCH_ELEMENT_ERROR;
406     }
407     /*Operation provided by the P2 parameter is not permitted by the applet.*/
408     else if (rpdu.sw1 == 0x6A && rpdu.sw2 == 0x86) {
409       sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
410     } else {
411       sestatus = SecureElementStatus::FAILED;
412     }
413   }
414   status = phNxpEse_ResetEndPoint_Cntxt(1);
415   if (status != ESESTATUS_SUCCESS) {
416     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
417   }
418   if (sestatus != SecureElementStatus::SUCCESS) {
419     SecureElementStatus closeChannelStatus =
420         internalCloseChannel(DEFAULT_BASIC_CHANNEL);
421     if (closeChannelStatus != SecureElementStatus::SUCCESS) {
422       LOG(ERROR) << "%s: closeChannel Failed" << __func__;
423     }
424   }
425   _hidl_cb(result, sestatus);
426   phNxpEse_free(cpdu.pdata);
427   phNxpEse_free(rpdu.pdata);
428   return Void();
429 }
430 
431 Return<::android::hardware::secure_element::V1_0::SecureElementStatus>
internalCloseChannel(uint8_t channelNumber)432 VirtualISO::internalCloseChannel(uint8_t channelNumber) {
433   ESESTATUS status = ESESTATUS_SUCCESS;
434   SecureElementStatus sestatus = SecureElementStatus::FAILED;
435   phNxpEse_7816_cpdu_t cpdu;
436   phNxpEse_7816_rpdu_t rpdu;
437 
438   LOG(ERROR) << "internalCloseChannel Enter";
439   LOG(INFO) << StringPrintf("mMaxChannelCount = %d, Closing Channel = %d",
440                             mMaxChannelCount, channelNumber);
441   if (channelNumber < DEFAULT_BASIC_CHANNEL ||
442       channelNumber >= mMaxChannelCount) {
443     LOG(ERROR) << StringPrintf("invalid channel!!! %d", channelNumber);
444     sestatus = SecureElementStatus::FAILED;
445   } else if (channelNumber > DEFAULT_BASIC_CHANNEL) {
446     phNxpEse_memset(&cpdu, 0x00, sizeof(phNxpEse_7816_cpdu_t));
447     phNxpEse_memset(&rpdu, 0x00, sizeof(phNxpEse_7816_rpdu_t));
448     cpdu.cla = channelNumber; /* Class of instruction */
449     cpdu.ins = 0x70;          /* Instruction code */
450     cpdu.p1 = 0x80;           /* Instruction parameter 1 */
451     cpdu.p2 = channelNumber;  /* Instruction parameter 2 */
452     cpdu.lc = 0x00;
453     cpdu.le = 0x9000;
454     status = phNxpEse_SetEndPoint_Cntxt(1);
455     if (status != ESESTATUS_SUCCESS) {
456       LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
457     }
458     status = phNxpEse_7816_Transceive(&cpdu, &rpdu);
459 
460     if (status != ESESTATUS_SUCCESS) {
461       if (rpdu.len > 0 && (rpdu.sw1 == 0x64 && rpdu.sw2 == 0xFF)) {
462         sestatus = SecureElementStatus::FAILED;
463       } else {
464         sestatus = SecureElementStatus::FAILED;
465       }
466     } else {
467       if ((rpdu.sw1 == 0x90) && (rpdu.sw2 == 0x00)) {
468         sestatus = SecureElementStatus::SUCCESS;
469       } else {
470         sestatus = SecureElementStatus::FAILED;
471       }
472     }
473     status = phNxpEse_ResetEndPoint_Cntxt(1);
474     if (status != ESESTATUS_SUCCESS) {
475       LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
476     }
477   }
478   if (mOpenedChannels[channelNumber]) {
479     mOpenedChannels[channelNumber] = false;
480     mOpenedchannelCount--;
481   }
482   /*If there are no channels remaining close secureElement*/
483   if (mOpenedchannelCount == 0) {
484     sestatus = seHalDeInit();
485   } else {
486     sestatus = SecureElementStatus::SUCCESS;
487   }
488   return sestatus;
489 }
490 
491 Return<::android::hardware::secure_element::V1_0::SecureElementStatus>
closeChannel(uint8_t channelNumber)492 VirtualISO::closeChannel(uint8_t channelNumber) {
493   ESESTATUS status = ESESTATUS_SUCCESS;
494   SecureElementStatus sestatus = SecureElementStatus::FAILED;
495   phNxpEse_7816_cpdu_t cpdu;
496   phNxpEse_7816_rpdu_t rpdu;
497 
498   LOG(INFO) << "Acquired the lock in VISO closeChannel";
499   if (channelNumber < DEFAULT_BASIC_CHANNEL ||
500       channelNumber >= mMaxChannelCount) {
501     LOG(ERROR) << StringPrintf("invalid channel!!! %d for %d", channelNumber,
502                                mOpenedChannels[channelNumber]);
503     sestatus = SecureElementStatus::FAILED;
504   } else if (channelNumber > DEFAULT_BASIC_CHANNEL) {
505     phNxpEse_memset(&cpdu, 0x00, sizeof(phNxpEse_7816_cpdu_t));
506     phNxpEse_memset(&rpdu, 0x00, sizeof(phNxpEse_7816_rpdu_t));
507     cpdu.cla = channelNumber; /* Class of instruction */
508     cpdu.ins = 0x70;          /* Instruction code */
509     cpdu.p1 = 0x80;           /* Instruction parameter 1 */
510     cpdu.p2 = channelNumber;  /* Instruction parameter 2 */
511     cpdu.lc = 0x00;
512     cpdu.le = 0x9000;
513     status = phNxpEse_SetEndPoint_Cntxt(1);
514     if (status != ESESTATUS_SUCCESS) {
515       LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
516     }
517     status = phNxpEse_7816_Transceive(&cpdu, &rpdu);
518 
519     if (status != ESESTATUS_SUCCESS) {
520       if (rpdu.len > 0 && (rpdu.sw1 == 0x64 && rpdu.sw2 == 0xFF)) {
521         sestatus = SecureElementStatus::FAILED;
522       } else {
523         sestatus = SecureElementStatus::FAILED;
524       }
525     } else {
526       if ((rpdu.sw1 == 0x90) && (rpdu.sw2 == 0x00)) {
527         sestatus = SecureElementStatus::SUCCESS;
528       } else {
529         sestatus = SecureElementStatus::FAILED;
530       }
531     }
532     status = phNxpEse_ResetEndPoint_Cntxt(1);
533     if (status != ESESTATUS_SUCCESS) {
534       LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
535     }
536   }
537   if (mOpenedChannels[channelNumber]) {
538     mOpenedChannels[channelNumber] = false;
539     mOpenedchannelCount--;
540   }
541   /*If there are no channels remaining close secureElement*/
542   if (mOpenedchannelCount == 0) {
543     sestatus = seHalDeInit();
544   } else {
545     sestatus = SecureElementStatus::SUCCESS;
546   }
547   return sestatus;
548 }
seHalInit()549 ESESTATUS VirtualISO::seHalInit() {
550   ESESTATUS status = ESESTATUS_SUCCESS;
551   ESESTATUS deInitStatus = ESESTATUS_SUCCESS;
552   phNxpEse_initParams initParams;
553   memset(&initParams, 0x00, sizeof(phNxpEse_initParams));
554   initParams.initMode = ESE_MODE_NORMAL;
555   initParams.mediaType = ESE_PROTOCOL_MEDIA_SPI_APDU_GATE;
556 
557   status = phNxpEse_open(initParams);
558   if (ESESTATUS_SUCCESS == status || ESESTATUS_BUSY == status) {
559     if (ESESTATUS_SUCCESS == phNxpEse_SetEndPoint_Cntxt(1) &&
560         ESESTATUS_SUCCESS == phNxpEse_init(initParams)) {
561       if (ESESTATUS_SUCCESS == phNxpEse_ResetEndPoint_Cntxt(1)) {
562         mIsEseInitialized = true;
563         LOG(INFO) << "VISO init complete!!!";
564         return ESESTATUS_SUCCESS;
565       }
566       deInitStatus = phNxpEse_deInit();
567     }
568     phNxpEse_close(deInitStatus);
569     mIsEseInitialized = false;
570   }
571   return status;
572 }
573 
574 Return<::android::hardware::secure_element::V1_0::SecureElementStatus>
seHalDeInit()575 VirtualISO::seHalDeInit() {
576   ESESTATUS status = ESESTATUS_SUCCESS;
577   ESESTATUS deInitStatus = ESESTATUS_SUCCESS;
578   bool mIsDeInitDone = true;
579   SecureElementStatus sestatus = SecureElementStatus::FAILED;
580   status = phNxpEse_SetEndPoint_Cntxt(1);
581   if (status != ESESTATUS_SUCCESS) {
582     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
583     mIsDeInitDone = false;
584   }
585   deInitStatus = phNxpEse_deInit();
586   if (ESESTATUS_SUCCESS != deInitStatus) mIsDeInitDone = false;
587   status = phNxpEse_ResetEndPoint_Cntxt(1);
588   if (status != ESESTATUS_SUCCESS) {
589     LOG(ERROR) << "phNxpEse_SetEndPoint_Cntxt failed!!!";
590     mIsDeInitDone = false;
591   }
592   status = phNxpEse_close(deInitStatus);
593   if (status == ESESTATUS_SUCCESS && mIsDeInitDone) {
594     sestatus = SecureElementStatus::SUCCESS;
595     ;
596   } else {
597     LOG(ERROR) << "seHalDeInit: Failed";
598   }
599   // Clear all the flags as SPI driver is closed.
600   mIsEseInitialized = false;
601   for (uint8_t xx = 0; xx < mMaxChannelCount; xx++) {
602     mOpenedChannels[xx] = false;
603   }
604   mOpenedchannelCount = 0;
605   return sestatus;
606 }
607 
608 }  // namespace implementation
609 }  // namespace V1_0
610 }  // namespace virtual_iso
611 }  // namespace nxp
612 }  // namespace vendor
613