1 /******************************************************************************
2  *
3  *  Copyright (C) 2018 ST Microelectronics S.A.
4  *  Copyright 2018 NXP
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  ******************************************************************************/
19 #define LOG_TAG "StEse_HalApi"
20 
21 #include "StEseApi.h"
22 #include <cutils/properties.h>
23 #include <ese_config.h>
24 #include <pthread.h>
25 #include "SpiLayerComm.h"
26 #include "T1protocol.h"
27 #include "android_logmsg.h"
28 
29 /*********************** Global Variables *************************************/
30 
31 /* ESE Context structure */
32 ese_Context_t ese_ctxt;
33 
34 const char* halVersion = "ST54-SE HAL1.0 Version 1.0.22";
35 
36 pthread_mutex_t mutex;
37 
38 bool ConfRead = 0;
39 unsigned int PollInt_confvalue = 1000;
40 unsigned int BGT_confvalue = 1000;
41 
42 /******************************************************************************
43  * Function         StEseLog_InitializeLogLevel
44  *
45  * Description      This function is called during StEse_init to initialize
46  *                  debug log level.
47  *
48  * Returns          None
49  *
50  ******************************************************************************/
51 
StEseLog_InitializeLogLevel()52 void StEseLog_InitializeLogLevel() { InitializeSTLogLevel(); }
53 
54 /******************************************************************************
55  * Function         StEse_init
56  *
57  * Description      This function is called by Jni during the
58  *                  initialization of the ESE. It opens the physical connection
59  *                  with ESE and creates required client thread for
60  *                  operation.
61  * Returns          This function return ESESTATUS_SUCCES (0) in case of success
62  *                  In case of failure returns other failure value.
63  *
64  ******************************************************************************/
StEse_init()65 ESESTATUS StEse_init() {
66   SpiDriver_config_t tSpiDriver;
67   ESESTATUS wConfigStatus = ESESTATUS_SUCCESS;
68   int ret;
69 
70   char ese_dev_node[64];
71   std::string ese_node;
72 
73   STLOG_HAL_D("%s : SteSE_open Enter halVersion = %s ", __func__, halVersion);
74   /*When spi channel is already opened return status as FAILED*/
75   if (ese_ctxt.EseLibStatus != ESE_STATUS_CLOSE) {
76     STLOG_HAL_D("already opened\n");
77     return ESESTATUS_BUSY;
78   }
79 
80   memset(&ese_ctxt, 0x00, sizeof(ese_ctxt));
81   memset(&tSpiDriver, 0x00, sizeof(tSpiDriver));
82 
83   /* initialize trace level */
84   StEseLog_InitializeLogLevel();
85 
86   /*Read device node path*/
87   ese_node = EseConfig::getString(NAME_ST_ESE_DEV_NODE, "/dev/st54j");
88   strcpy(ese_dev_node, ese_node.c_str());
89   tSpiDriver.pDevName = ese_dev_node;
90 
91   if (!ConfRead) {
92     PollInt_confvalue =
93         EseConfig::getUnsigned(NAME_ST_ESE_DEV_POLLING_INTERVAL, 1000);
94     BGT_confvalue = EseConfig::getUnsigned(NAME_ST_ESE_DEV_BGT, 1000);
95     ConfRead = true;
96   }
97 
98   tSpiDriver.polling_interval = PollInt_confvalue;
99   tSpiDriver.bgt = BGT_confvalue;
100 
101   /* Initialize SPI Driver layer */
102   if (T1protocol_init(&tSpiDriver) != ESESTATUS_SUCCESS) {
103     STLOG_HAL_E("T1protocol_init Failed");
104     if (intptr_t(tSpiDriver.pDevHandle) > 0) {
105       ese_ctxt.pDevHandle = tSpiDriver.pDevHandle;
106     }
107     goto clean_and_return;
108   }
109   /* Copying device handle to ESE Lib context*/
110   ese_ctxt.pDevHandle = tSpiDriver.pDevHandle;
111 
112   ret = pthread_mutex_init(&mutex, NULL);
113   if (ret != 0) {
114     STLOG_HAL_E("HAL: %s pthread_mutex_init failed", __func__);
115   }
116 
117   STLOG_HAL_D("wConfigStatus %x", wConfigStatus);
118   ese_ctxt.EseLibStatus = ESE_STATUS_OPEN;
119   return wConfigStatus;
120 
121 clean_and_return:
122   if (NULL != ese_ctxt.pDevHandle) {
123     SpiLayerInterface_close(ese_ctxt.pDevHandle);
124     memset(&ese_ctxt, 0x00, sizeof(ese_ctxt));
125   }
126   ese_ctxt.EseLibStatus = ESE_STATUS_CLOSE;
127   return ESESTATUS_FAILED;
128 }
129 
130 /******************************************************************************
131  * Function         StEseApi_isOpen
132  *
133  * \brief           Check if the hal is opened
134  *
135  * \retval return false if it is close, otherwise true.
136  *
137  ******************************************************************************/
StEseApi_isOpen()138 bool StEseApi_isOpen() {
139   STLOG_HAL_D(" %s  status 0x%x \n", __FUNCTION__, ese_ctxt.EseLibStatus);
140   return ese_ctxt.EseLibStatus != ESE_STATUS_CLOSE;
141 }
142 
143 /******************************************************************************
144  * Function         StEse_Transceive
145  *
146  * Description      This function update the len and provided buffer
147  *
148  * Returns          On Success ESESTATUS_SUCCESS else proper error code
149  *
150  ******************************************************************************/
StEse_Transceive(StEse_data * pCmd,StEse_data * pRsp)151 ESESTATUS StEse_Transceive(StEse_data* pCmd, StEse_data* pRsp) {
152   ESESTATUS status = ESESTATUS_SUCCESS;
153   static int pTxBlock_len = 0;
154   int retry_count = 0;
155   uint16_t pCmdlen = pCmd->len;
156 
157   STLOG_HAL_D("%s : Enter EseLibStatus = %d ", __func__, ese_ctxt.EseLibStatus);
158 
159   if ((NULL == pCmd) || (NULL == pRsp)) return ESESTATUS_INVALID_PARAMETER;
160 
161   if ((pCmd->len == 0) || pCmd->p_data == NULL) {
162     STLOG_HAL_E(" StEse_Transceive - Invalid Parameter no data\n");
163     return ESESTATUS_INVALID_PARAMETER;
164   } else if ((ESE_STATUS_CLOSE == ese_ctxt.EseLibStatus)) {
165     STLOG_HAL_E(" %s ESE Not Initialized \n", __FUNCTION__);
166     return ESESTATUS_NOT_INITIALISED;
167   }
168 
169   STLOG_HAL_D(" %s ESE - No access, waiting \n", __FUNCTION__);
170   pthread_mutex_lock(&mutex);
171 
172   STLOG_HAL_D(" %s ESE - Access granted, processing \n", __FUNCTION__);
173 
174   uint8_t* CmdPart = pCmd->p_data;
175 
176 retry:
177   while (pCmdlen > ATP.ifsc) {
178     pTxBlock_len = ATP.ifsc;
179 
180     int rc = T1protocol_transcieveApduPart(CmdPart, pTxBlock_len, false,
181                                            (StEse_data*)pRsp, I_block);
182 
183     if ((rc == -2) && (retry_count < 3)) {
184       retry_count++;
185       STLOG_HAL_E(" %s ESE - resync was needed, resend the whole frame retry"
186                   " = %d\n", __FUNCTION__, retry_count);
187       pCmdlen = pCmd->len;
188       CmdPart = pCmd->p_data;
189       goto retry;
190     } else if (rc < 0) {
191       STLOG_HAL_E(" %s ESE - Error, release access \n", __FUNCTION__);
192       status = ESESTATUS_FAILED;
193       retry_count = 0;
194       pthread_mutex_unlock(&mutex);
195 
196       return status;
197     } else {
198       retry_count = 0;
199     }
200 
201     pCmdlen -= pTxBlock_len;
202     CmdPart = CmdPart + pTxBlock_len;
203   }
204 
205   int rc = T1protocol_transcieveApduPart(CmdPart, pCmdlen, true,
206                                          (StEse_data*)pRsp, I_block);
207   if ((rc == -2) && (retry_count < 3)) {
208     retry_count++;
209     STLOG_HAL_E(" %s ESE - resync was needed, resend retry = %d\n",
210                 __FUNCTION__, retry_count);
211     pCmdlen = pCmd->len;
212     CmdPart = pCmd->p_data;
213     goto retry;
214   } else if (rc < 0)
215     status = ESESTATUS_FAILED;
216 
217   if (ESESTATUS_SUCCESS != status) {
218     STLOG_HAL_E(" %s T1protocol_transcieveApduPart- Failed \n", __FUNCTION__);
219   }
220   retry_count = 0;
221   STLOG_HAL_D(" %s ESE - Processing complete, release access \n", __FUNCTION__);
222 
223   pthread_mutex_unlock(&mutex);
224 
225   STLOG_HAL_D(" %s Exit status 0x%x \n", __FUNCTION__, status);
226 
227   return status;
228 }
229 
230 /******************************************************************************
231  * Function         StEse_close
232  *
233  * Description      This function close the ESE interface and free all
234  *                  resources.
235  *
236  * Returns          Always return ESESTATUS_SUCCESS (0).
237  *
238  ******************************************************************************/
StEse_close(void)239 ESESTATUS StEse_close(void) {
240   ESESTATUS status = ESESTATUS_SUCCESS;
241 
242   if ((ESE_STATUS_CLOSE == ese_ctxt.EseLibStatus)) {
243     STLOG_HAL_E(" %s ESE Not Initialized \n", __FUNCTION__);
244     return ESESTATUS_NOT_INITIALISED;
245   }
246 
247   if (NULL != ese_ctxt.pDevHandle) {
248     SpiLayerInterface_close(ese_ctxt.pDevHandle);
249     memset(&ese_ctxt, 0x00, sizeof(ese_ctxt));
250     STLOG_HAL_D("StEse_close - ESE Context deinit completed");
251     ese_ctxt.EseLibStatus = ESE_STATUS_CLOSE;
252   }
253 
254   pthread_mutex_destroy(&mutex);
255   /* Return success always */
256   return status;
257 }
258 
259 /******************************************************************************
260  * Function         StEse_getAtr
261  *
262  * Description      This function get the last ATR received.
263  *
264  * Returns          pointer to the ATR array.
265  *
266  ******************************************************************************/
StEse_getAtr(void)267 uint8_t* StEse_getAtr(void) {
268   STLOG_HAL_D("%s : Enter", __func__);
269   // The ATR is not supported by SPI in the secure element
270   return nullptr;
271 }
272 
273 /******************************************************************************
274  * Function         StEse_Reset
275  *
276  * Description      This function resets the eSE SPI interface by sending a
277  *                  SE reset and negotiating the ifs.
278  *
279  * Returns          ESESTATUS_SUCCESS is successful, ESESTATUS_SUCCESS otherwise
280  *
281  ******************************************************************************/
StEse_Reset(void)282 ESESTATUS StEse_Reset(void) {
283   STLOG_HAL_D("%s : Enter", __func__);
284   if (SpiLayerInterface_setup() != 0) {
285     return ESESTATUS_FAILED;
286   }
287 
288   return ESESTATUS_SUCCESS;
289 }
290