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