1 /******************************************************************************
2 *
3 * Copyright 2019-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 "NxpMfcReader.h"
19 #include <phNfcCompId.h>
20 #include <phNxpLog.h>
21 #include <phNxpNciHal_Adaptation.h>
22 #include <phNxpNciHal_ext.h>
23 #include "phNxpNciHal.h"
24
25 extern bool sendRspToUpperLayer;
26
getInstance()27 NxpMfcReader& NxpMfcReader::getInstance() {
28 static NxpMfcReader msNxpMfcReader;
29 return msNxpMfcReader;
30 }
31
32 /*******************************************************************************
33 **
34 ** Function Write
35 **
36 ** Description Wrapper API to handle Mifare Transceive to TAG_CMD interface
37 ** RAW read write.
38 **
39 ** Returns It returns number of bytes successfully written to NFCC.
40 **
41 *******************************************************************************/
Write(uint16_t mfcDataLen,const uint8_t * pMfcData)42 int NxpMfcReader::Write(uint16_t mfcDataLen, const uint8_t* pMfcData) {
43 uint16_t mfcTagCmdBuffLen = 0;
44 uint8_t mfcTagCmdBuff[MAX_MFC_BUFF_SIZE] = {0};
45
46 memcpy(mfcTagCmdBuff, pMfcData, mfcDataLen);
47 if (mfcDataLen >= 3) mfcTagCmdBuffLen = mfcDataLen - NCI_HEADER_SIZE;
48 BuildMfcCmd(&mfcTagCmdBuff[3], &mfcTagCmdBuffLen);
49
50 mfcTagCmdBuff[2] = mfcTagCmdBuffLen;
51 mfcDataLen = mfcTagCmdBuffLen + NCI_HEADER_SIZE;
52 int writtenDataLen = phNxpNciHal_write_internal(mfcDataLen, mfcTagCmdBuff);
53
54 /* send TAG_CMD part 2 for Mifare increment ,decrement and restore commands */
55 if (mfcTagCmdBuff[4] == eMifareDec || mfcTagCmdBuff[4] == eMifareInc ||
56 mfcTagCmdBuff[4] == eMifareRestore) {
57 SendIncDecRestoreCmdPart2(pMfcData);
58 }
59 return writtenDataLen;
60 }
61
62 /*******************************************************************************
63 **
64 ** Function BuildMfcCmd
65 **
66 ** Description builds the TAG CMD for Mifare Classic Tag.
67 **
68 ** Returns None
69 **
70 *******************************************************************************/
BuildMfcCmd(uint8_t * pData,uint16_t * pLength)71 void NxpMfcReader::BuildMfcCmd(uint8_t* pData, uint16_t* pLength) {
72 uint16_t cmdBuffLen = *pLength;
73 memcpy(mMfcTagCmdIntfData.sendBuf, pData, cmdBuffLen);
74 mMfcTagCmdIntfData.sendBufLen = cmdBuffLen;
75
76 switch (pData[0]) {
77 case eMifareAuthentA:
78 case eMifareAuthentB:
79 BuildAuthCmd();
80 break;
81 case eMifareRead16:
82 BuildReadCmd();
83 break;
84 case eMifareWrite16:
85 AuthForWrite();
86 BuildWrite16Cmd();
87 break;
88 case eMifareInc:
89 case eMifareDec:
90 BuildIncDecCmd();
91 break;
92 default:
93 BuildRawCmd();
94 break;
95 }
96
97 memcpy(pData, mMfcTagCmdIntfData.sendBuf, (mMfcTagCmdIntfData.sendBufLen));
98 *pLength = (mMfcTagCmdIntfData.sendBufLen);
99 return;
100 }
101
102 /*******************************************************************************
103 **
104 ** Function BuildAuthCmd
105 **
106 ** Description builds the TAG CMD for Mifare Auth.
107 **
108 ** Returns None
109 **
110 *******************************************************************************/
BuildAuthCmd()111 void NxpMfcReader::BuildAuthCmd() {
112 uint8_t byKey = 0x00, noOfKeys = 0x00;
113 bool isPreloadedKey = false;
114
115 if (mMfcTagCmdIntfData.sendBuf[0] == eMifareAuthentB) {
116 byKey |= MFC_ENABLE_KEY_B;
117 }
118 uint8_t aMfckeys[MFC_NUM_OF_KEYS][MFC_KEY_SIZE] = MFC_KEYS;
119 noOfKeys = sizeof(aMfckeys) / MFC_KEY_SIZE;
120 for (uint8_t byIndex = 0; byIndex < noOfKeys; byIndex++) {
121 if ((memcmp(aMfckeys[byIndex], &mMfcTagCmdIntfData.sendBuf[6],
122 MFC_AUTHKEYLEN) == 0x00)) {
123 byKey = byKey | byIndex;
124 isPreloadedKey = true;
125 break;
126 }
127 }
128 CalcSectorAddress();
129 mMfcTagCmdIntfData.sendBufLen = 0x03;
130 if (!isPreloadedKey) {
131 byKey |= MFC_EMBEDDED_KEY;
132 memmove(&mMfcTagCmdIntfData.sendBuf[3], &mMfcTagCmdIntfData.sendBuf[6],
133 MFC_AUTHKEYLEN);
134 mMfcTagCmdIntfData.sendBufLen += MFC_AUTHKEYLEN;
135 }
136
137 mMfcTagCmdIntfData.sendBuf[0] = eMfcAuthReq;
138 mMfcTagCmdIntfData.sendBuf[1] = mMfcTagCmdIntfData.byAddr;
139 mMfcTagCmdIntfData.sendBuf[2] = byKey;
140 return;
141 }
142
143 /*******************************************************************************
144 **
145 ** Function CalcSectorAddress
146 **
147 ** Description This function update the sector address for Mifare classic
148 **
149 ** Returns None
150 **
151 *******************************************************************************/
CalcSectorAddress()152 void NxpMfcReader::CalcSectorAddress() {
153 uint8_t BlockNumber = mMfcTagCmdIntfData.sendBuf[1];
154 if (BlockNumber >= MFC_4K_BLK128) {
155 mMfcTagCmdIntfData.byAddr =
156 (uint8_t)(MFC_SECTOR_NO32 +
157 ((BlockNumber - MFC_4K_BLK128) / MFC_BYTES_PER_BLOCK));
158 } else {
159 mMfcTagCmdIntfData.byAddr = BlockNumber / MFC_BLKS_PER_SECTOR;
160 }
161
162 return;
163 }
164
165 /*******************************************************************************
166 **
167 ** Function BuildReadCmd
168 **
169 ** Description builds the TAG CMD for Mifare Read.
170 **
171 ** Returns None
172 **
173 *******************************************************************************/
BuildReadCmd()174 void NxpMfcReader::BuildReadCmd() { BuildRawCmd(); }
175
176 /*******************************************************************************
177 **
178 ** Function BuildWrite16Cmd
179 **
180 ** Description builds the TAG CMD for Mifare write part 2.
181 **
182 ** Returns None
183 **
184 *******************************************************************************/
BuildWrite16Cmd()185 void NxpMfcReader::BuildWrite16Cmd() {
186 mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
187 mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen - 1;
188 memcpy(mMfcTagCmdIntfData.sendBuf + 1, mMfcTagCmdIntfData.sendBuf + 2,
189 mMfcTagCmdIntfData.sendBufLen);
190 }
191
192 /*******************************************************************************
193 **
194 ** Function BuildRawCmd
195 **
196 ** Description builds the TAG CMD for Raw transceive.
197 **
198 ** Returns None
199 **
200 *******************************************************************************/
BuildRawCmd()201 void NxpMfcReader::BuildRawCmd() {
202 mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen + 1;
203 uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
204 memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
205 memcpy(buff, mMfcTagCmdIntfData.sendBuf, mMfcTagCmdIntfData.sendBufLen);
206 memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
207 mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
208 }
209
210 /*******************************************************************************
211 **
212 ** Function BuildIncDecCmd
213 **
214 ** Description builds the TAG CMD for Mifare Inc/Dec.
215 **
216 ** Returns None
217 **
218 *******************************************************************************/
BuildIncDecCmd()219 void NxpMfcReader::BuildIncDecCmd() {
220 mMfcTagCmdIntfData.sendBufLen = 0x03; // eMfRawDataXchgHdr + cmd +
221 // blockaddress
222 uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
223 memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
224 memcpy(buff, mMfcTagCmdIntfData.sendBuf, mMfcTagCmdIntfData.sendBufLen);
225 memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
226 mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
227 }
228
229 /*******************************************************************************
230 **
231 ** Function AuthForWrite
232 **
233 ** Description send Mifare write Part 1.
234 **
235 ** Returns None
236 **
237 *******************************************************************************/
AuthForWrite()238 void NxpMfcReader::AuthForWrite() {
239 sendRspToUpperLayer = false;
240 NFCSTATUS status = NFCSTATUS_FAILED;
241 uint8_t authForWriteBuff[] = {0x00,
242 0x00,
243 0x03,
244 (uint8_t)eMfRawDataXchgHdr,
245 (uint8_t)mMfcTagCmdIntfData.sendBuf[0],
246 (uint8_t)mMfcTagCmdIntfData.sendBuf[1]};
247
248 status = phNxpNciHal_send_ext_cmd(
249 sizeof(authForWriteBuff) / sizeof(authForWriteBuff[0]), authForWriteBuff);
250 if (status != NFCSTATUS_SUCCESS) {
251 NXPLOG_NCIHAL_E("Mifare Auth for Transceive failed");
252 }
253 return;
254 }
255
256 /*******************************************************************************
257 **
258 ** Function SendIncDecRestoreCmdPart2
259 **
260 ** Description send Mifare Inc/Dec/Restore Command Part 2.
261 **
262 ** Returns None
263 **
264 *******************************************************************************/
SendIncDecRestoreCmdPart2(const uint8_t * mfcData)265 void NxpMfcReader::SendIncDecRestoreCmdPart2(const uint8_t* mfcData) {
266 NFCSTATUS status = NFCSTATUS_SUCCESS;
267 /* Build TAG_CMD part 2 for Mifare increment ,decrement and restore commands*/
268 uint8_t incDecRestorePart2[] = {0x00, 0x00, 0x05, (uint8_t)eMfRawDataXchgHdr,
269 0x00, 0x00, 0x00, 0x00};
270 uint8_t incDecRestorePart2Size =
271 (sizeof(incDecRestorePart2) / sizeof(incDecRestorePart2[0]));
272 if (mfcData[3] == eMifareInc || mfcData[3] == eMifareDec) {
273 for (int i = 4; i < incDecRestorePart2Size; i++) {
274 incDecRestorePart2[i] = mfcData[i + 1];
275 }
276 }
277 sendRspToUpperLayer = false;
278 status = phNxpNciHal_send_ext_cmd(incDecRestorePart2Size, incDecRestorePart2);
279 if (status != NFCSTATUS_SUCCESS) {
280 NXPLOG_NCIHAL_E("Mifare Cmd for inc/dec/Restore part 2 failed");
281 }
282 return;
283 }
284
285 /*******************************************************************************
286 **
287 ** Function AnalyzeMfcResp
288 **
289 ** Description Analyze type of MFC response and build MFC response from
290 ** Tag cmd Intf response?
291 **
292 ** Returns NFCSTATUS_SUCCESS - Data Reception is successful
293 ** NFCSTATUS_FAILED - Data Reception failed
294 **
295 *******************************************************************************/
AnalyzeMfcResp(uint8_t * pBuff,uint16_t * pBufflen)296 NFCSTATUS NxpMfcReader::AnalyzeMfcResp(uint8_t* pBuff, uint16_t* pBufflen) {
297 NFCSTATUS status = NFCSTATUS_SUCCESS;
298 uint16_t wPldDataSize = 0;
299 MfcRespId_t RecvdExtnRspId = eInvalidRsp;
300
301 if (0 == (*pBufflen)) {
302 status = NFCSTATUS_FAILED;
303 } else {
304 RecvdExtnRspId = (MfcRespId_t)pBuff[0];
305 NXPLOG_NCIHAL_E("%s: RecvdExtnRspId=%d", __func__, RecvdExtnRspId);
306 switch (RecvdExtnRspId) {
307 case eMfXchgDataRsp: {
308 NFCSTATUS writeRespStatus = NFCSTATUS_SUCCESS;
309 /* check the status byte */
310 if (*pBufflen == 3) {
311 if ((pBuff[0] == 0x10) && (pBuff[1] != 0x0A)) {
312 NXPLOG_NCIHAL_E("Mifare Error in payload response");
313 *pBufflen = 0x1;
314 pBuff[0] = NFCSTATUS_FAILED;
315 return NFCSTATUS_FAILED;
316 } else {
317 pBuff[0] = NFCSTATUS_SUCCESS;
318 return NFCSTATUS_SUCCESS;
319 }
320 }
321 writeRespStatus = pBuff[*pBufflen - 1];
322
323 if (NFCSTATUS_SUCCESS == writeRespStatus) {
324 status = NFCSTATUS_SUCCESS;
325 uint16_t wRecvDataSz = 0;
326
327 wPldDataSize =
328 ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
329 wRecvDataSz = MAX_MFC_BUFF_SIZE;
330 if ((wPldDataSize) <= wRecvDataSz) {
331 /* Extract the data part from pBuff[2] & fill it to be sent to
332 * upper layer */
333 memcpy(&(pBuff[0]), &(pBuff[1]), wPldDataSize);
334 /* update the number of bytes received from lower layer,excluding
335 * the status byte */
336 *pBufflen = wPldDataSize;
337 } else {
338 status = NFCSTATUS_FAILED;
339 }
340 } else {
341 status = NFCSTATUS_FAILED;
342 }
343 } break;
344
345 case eMfcAuthRsp: {
346 /* check the status byte */
347 if (NFCSTATUS_SUCCESS == pBuff[1]) {
348 status = NFCSTATUS_SUCCESS;
349 /* DataLen = TotalRecvdLen - (sizeof(RspId) + sizeof(Status)) */
350 wPldDataSize =
351 ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
352 /* Extract the data part from pBuff[2] & fill it to be sent to upper
353 * layer */
354 pBuff[0] = pBuff[1];
355 /* update the number of bytes received from lower layer,excluding
356 * the status byte */
357 *pBufflen = wPldDataSize + 1;
358 } else {
359 pBuff[0] = pBuff[1];
360 *pBufflen = 1;
361 status = NFCSTATUS_FAILED;
362 }
363 } break;
364 default: {
365 status = NFCSTATUS_FAILED;
366 } break;
367 }
368 }
369 return status;
370 }
371
372 /*******************************************************************************
373 **
374 ** Function CheckMfcResponse
375 **
376 ** Description This function is called to check if it's a valid Mfc
377 ** response data
378 **
379 ** Returns NFCSTATUS_SUCCESS
380 ** NFCSTATUS_FAILED
381 **
382 *******************************************************************************/
CheckMfcResponse(uint8_t * pTransceiveData,uint16_t transceiveDataLen)383 NFCSTATUS NxpMfcReader::CheckMfcResponse(uint8_t* pTransceiveData,
384 uint16_t transceiveDataLen) {
385 NFCSTATUS status = NFCSTATUS_SUCCESS;
386
387 if (transceiveDataLen == 3) {
388 if ((pTransceiveData)[0] == 0x10 && (pTransceiveData)[1] != 0x0A) {
389 NXPLOG_NCIHAL_E("Mifare Error in payload response");
390 transceiveDataLen = 0x1;
391 pTransceiveData += 1;
392 return NFCSTATUS_FAILED;
393 }
394 }
395 if ((pTransceiveData)[0] == 0x40) {
396 pTransceiveData += 1;
397 transceiveDataLen = 0x01;
398 if ((pTransceiveData)[0] == 0x03) {
399 transceiveDataLen = 0x00;
400 status = NFCSTATUS_FAILED;
401 }
402 } else if ((pTransceiveData)[0] == 0x10) {
403 pTransceiveData += 1;
404 transceiveDataLen = 0x10;
405 }
406 return status;
407 }
408