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