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