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