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