1 /******************************************************************************
2 *
3 * Copyright 2018-2019,2022 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 /**
19 * \addtogroup ISO7816-4_application_protocol_implementation
20 *
21 * @{ */
22 #define LOG_TAG "NxpEseHal"
23 #include <ese_logs.h>
24 #include <log/log.h>
25 #include <phNxpEse_Apdu_Api.h>
26 #include <phNxpEse_Api.h>
27
28 static ESESTATUS phNxpEse_7816_FrameCmd(pphNxpEse_7816_cpdu_t pCmd,
29 uint8_t** pcmd_data, uint32_t* cmd_len);
30
31 /******************************************************************************
32 * Function phNxpEse_7816_Transceive
33 *
34 * Description This function prepares C-APDU and sends to p61 and receives
35 * response from the p61. also it parses all required fields of
36 * the response PDU.
37 *
38 * Returns On Success ESESTATUS_SUCCESS else proper error code
39 *
40 ******************************************************************************/
phNxpEse_7816_Transceive(pphNxpEse_7816_cpdu_t pCmd,pphNxpEse_7816_rpdu_t pRsp)41 ESESTATUS phNxpEse_7816_Transceive(pphNxpEse_7816_cpdu_t pCmd,
42 pphNxpEse_7816_rpdu_t pRsp) {
43 ESESTATUS status = ESESTATUS_FAILED;
44 NXP_LOG_ESE_D(" %s Enter \n", __FUNCTION__);
45
46 uint32_t cmd_len = 0;
47 uint8_t* pCmd_data = NULL;
48 phNxpEse_data pCmdTrans;
49 phNxpEse_data pRspTrans;
50 phNxpEse_memset(&pCmdTrans, 0x00, sizeof(phNxpEse_data));
51 phNxpEse_memset(&pRspTrans, 0x00, sizeof(phNxpEse_data));
52
53 if (NULL == pCmd || NULL == pRsp) {
54 NXP_LOG_ESE_E(" %s Invalid parameter \n", __FUNCTION__);
55 status = ESESTATUS_INVALID_PARAMETER;
56 } else if (pCmd->cpdu_type > 1) {
57 NXP_LOG_ESE_E(" %s Invalid cpdu type \n", __FUNCTION__);
58 status = ESESTATUS_INVALID_CPDU_TYPE;
59 } else if (0 < pCmd->le_type && NULL == pRsp->pdata) {
60 /* if response is requested, but no valid res buffer
61 * provided by application */
62 NXP_LOG_ESE_E(" %s Invalid response buffer \n", __FUNCTION__);
63 status = ESESTATUS_INVALID_BUFFER;
64 } else {
65 status = phNxpEse_7816_FrameCmd(pCmd, &pCmd_data, &cmd_len);
66 if (ESESTATUS_SUCCESS == status) {
67 pCmdTrans.len = cmd_len;
68 pCmdTrans.p_data = pCmd_data;
69 status = phNxpEse_Transceive(&pCmdTrans, &pRspTrans);
70 if (ESESTATUS_SUCCESS != status) {
71 NXP_LOG_ESE_E(" %s phNxpEse_Transceive Failed \n", __FUNCTION__);
72 if ((pRspTrans.len > 0) && (pRspTrans.p_data != NULL)) {
73 pRsp->sw2 = *(pRspTrans.p_data + (pRspTrans.len - 1));
74 pRspTrans.len--;
75 pRsp->sw1 = *(pRspTrans.p_data + (pRspTrans.len - 1));
76 pRspTrans.len--;
77 pRsp->len = pRspTrans.len;
78 }
79 } else {
80 if ((pRspTrans.len > 0) && (pRspTrans.p_data != NULL)) {
81 pRsp->sw2 = *(pRspTrans.p_data + (pRspTrans.len - 1));
82 pRspTrans.len--;
83 pRsp->sw1 = *(pRspTrans.p_data + (pRspTrans.len - 1));
84 pRspTrans.len--;
85 pRsp->len = pRspTrans.len;
86 NXP_LOG_ESE_D("pRsp->len %d", pRsp->len);
87 if (pRspTrans.len > 0 && NULL != pRsp->pdata) {
88 phNxpEse_memcpy(pRsp->pdata, pRspTrans.p_data, pRspTrans.len);
89 status = ESESTATUS_SUCCESS;
90 } else if (pRspTrans.len == 0) {
91 status = ESESTATUS_SUCCESS;
92 } else {
93 /* if application response buffer is null and data is present */
94 NXP_LOG_ESE_E("Invalid Res buffer");
95 status = ESESTATUS_FAILED;
96 }
97 NXP_LOG_ESE_D("Freeing memory pRspTrans.p_data ");
98 phNxpEse_free(pRspTrans.p_data);
99 pRspTrans.p_data = NULL;
100 pRspTrans.len = 0;
101 } else {
102 NXP_LOG_ESE_E("pRspTrans.len error = %d", pRspTrans.len);
103 status = ESESTATUS_FAILED;
104 }
105 }
106 if (pCmd_data != NULL) {
107 NXP_LOG_ESE_D("Freeing memory pCmd_data");
108 phNxpEse_free(pCmd_data);
109 }
110 }
111 }
112 NXP_LOG_ESE_D(" %s Exit status 0x%x \n", __FUNCTION__, status);
113 return status;
114 }
115
116 /**
117 * \ingroup ISO7816-4_application_protocol_implementation
118 * \brief Frames ISO7816-4 command.
119 * pCmd: 7816 command structure.
120 * pcmd_data: command buffer pointer.
121 *
122 * \param[in] pCmd- Structure pointer passed from
123 *application
124 * \param[in] **pcmd_data - Hold the allocated memory buffer for
125 *command.
126 * \param[in] *cmd_len - Hold the buffer length, update by this
127 *function
128 *
129 * \retval ESESTATUS_SUCCESS on Success else proper error code
130 *
131 */
132
phNxpEse_7816_FrameCmd(pphNxpEse_7816_cpdu_t pCmd,uint8_t ** pcmd_data,uint32_t * cmd_len)133 static ESESTATUS phNxpEse_7816_FrameCmd(pphNxpEse_7816_cpdu_t pCmd,
134 uint8_t** pcmd_data,
135 uint32_t* cmd_len) {
136 uint32_t cmd_total_len = MIN_HEADER_LEN; /* header is always 4 bytes */
137 uint8_t* pbuff = NULL;
138 uint32_t index = 0;
139 uint8_t lc_len = 0;
140 uint8_t le_len = 0;
141
142 NXP_LOG_ESE_D("%s pCmd->lc = %d, pCmd->le_type = %d", __FUNCTION__, pCmd->lc,
143 pCmd->le_type);
144 /* calculate the total buffer length */
145 if (pCmd->lc > 0) {
146 if (pCmd->cpdu_type == 0) {
147 cmd_total_len += 1; /* 1 byte LC */
148 lc_len = 1;
149 } else {
150 cmd_total_len += 3; /* 3 byte LC */
151 lc_len = 3;
152 }
153
154 cmd_total_len += pCmd->lc; /* add data length */
155 if (pCmd->pdata == NULL) {
156 NXP_LOG_ESE_E("%s Invalid data buffer from application ", __FUNCTION__);
157 return ESESTATUS_INVALID_BUFFER;
158 }
159 } else {
160 lc_len = 0;
161 NXP_LOG_ESE_D("%s lc (data) field is not present %d", __FUNCTION__,
162 pCmd->lc);
163 }
164
165 if (pCmd->le_type > 0) {
166 if (pCmd->le_type == 1) {
167 cmd_total_len += 1; /* 1 byte LE */
168 le_len = 1;
169 } else if ((pCmd->le_type == 2 || pCmd->le_type == 3)) {
170 /* extended le */
171 if ((pCmd->le_type == 3) && (lc_len == 0)) {
172 /* if data field not present, than only LE would be three bytes */
173 cmd_total_len += 3; /* 3 byte LE */
174 le_len = 3;
175 } else if ((pCmd->le_type == 2) && (lc_len != 0)) {
176 /* if data field present, LE would be two bytes */
177 cmd_total_len += 2; /* 2 byte LE */
178 le_len = 2;
179 } else {
180 NXP_LOG_ESE_E("%s wrong LE type %d", __FUNCTION__, pCmd->le_type);
181 cmd_total_len += pCmd->le_type;
182 le_len = pCmd->le_type;
183 }
184 } else {
185 NXP_LOG_ESE_E("%s wrong cpdu_type value %d", __FUNCTION__,
186 pCmd->cpdu_type);
187 return ESESTATUS_INVALID_CPDU_TYPE;
188 }
189 } else {
190 le_len = 0;
191 NXP_LOG_ESE_D("%s le field is not present", __FUNCTION__);
192 }
193 NXP_LOG_ESE_D("%s cmd_total_len = %d, le_len = %d, lc_len = %d", __FUNCTION__,
194 cmd_total_len, le_len, lc_len);
195
196 pbuff = (uint8_t*)phNxpEse_calloc(cmd_total_len, sizeof(uint8_t));
197 if (pbuff == NULL) {
198 NXP_LOG_ESE_E("%s Error allocating memory", __FUNCTION__);
199 return ESESTATUS_INSUFFICIENT_RESOURCES;
200 }
201 *cmd_len = cmd_total_len;
202 *pcmd_data = pbuff;
203 index = 0;
204
205 *(pbuff + index) = pCmd->cla;
206 index++;
207
208 *(pbuff + index) = pCmd->ins;
209 index++;
210
211 *(pbuff + index) = pCmd->p1;
212 index++;
213
214 *(pbuff + index) = pCmd->p2;
215 index++;
216
217 /* lc_len can be 0, 1 or 3 bytes */
218 if (lc_len > 0) {
219 if (lc_len == 1) {
220 *(pbuff + index) = pCmd->lc;
221 index++;
222 } else {
223 /* extended cmd buffer*/
224 *(pbuff + index) = 0x00; /* three byte lc */
225 index++;
226 *(pbuff + index) = ((pCmd->lc & 0xFF00) >> 8);
227 index++;
228 *(pbuff + index) = (pCmd->lc & 0x00FF);
229 index++;
230 }
231 /* copy the lc bytes data */
232 phNxpEse_memcpy((pbuff + index), pCmd->pdata, pCmd->lc);
233 index += pCmd->lc;
234 }
235 /* le_len can be 0, 1, 2 or 3 bytes */
236 if (le_len > 0) {
237 if (le_len == 1) {
238 if (pCmd->le == 256) {
239 /* if le is 256 assign max value*/
240 *(pbuff + index) = 0x00;
241 } else {
242 *(pbuff + index) = (uint8_t)pCmd->le;
243 }
244 index++;
245 } else {
246 if (pCmd->le == 65536) {
247 if (le_len == 3) {
248 /* assign max value */
249 *(pbuff + index) = 0x00; /* three byte le */
250 index++;
251 }
252 *(pbuff + index) = 0x00;
253 index++;
254 *(pbuff + index) = 0x00;
255 index++;
256 } else {
257 if (le_len == 3) {
258 *(pbuff + index) = 0x00; /* three byte le */
259 index++;
260 }
261 *(pbuff + index) = ((pCmd->le & 0x0000FF00) >> 8);
262 index++;
263 *(pbuff + index) = (pCmd->le & 0x000000FF);
264 index++;
265 }
266 }
267 }
268 NXP_LOG_ESE_D("Exit %s cmd_total_len = %d, index = %d", __FUNCTION__, index,
269 cmd_total_len);
270 return ESESTATUS_SUCCESS;
271 }
272 /** @} */
273