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   mfcDataLen = mfcTagCmdBuffLen + NCI_HEADER_SIZE;
57   int writtenDataLen = phNxpNciHal_write_internal(mfcDataLen, 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(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(const uint8_t * mfcData)266 void NxpMfcReader::SendIncDecRestoreCmdPart2(const uint8_t* mfcData) {
267   NFCSTATUS status = NFCSTATUS_SUCCESS;
268   /* Build TAG_CMD part 2 for Mifare increment ,decrement and restore commands*/
269   uint8_t incDecRestorePart2[] = {0x00, 0x00, 0x05, (uint8_t)eMfRawDataXchgHdr,
270                                   0x00, 0x00, 0x00, 0x00};
271   uint8_t incDecRestorePart2Size =
272       (sizeof(incDecRestorePart2) / sizeof(incDecRestorePart2[0]));
273   if (mfcData[3] == eMifareInc || mfcData[3] == eMifareDec) {
274     for (int i = 4; i < incDecRestorePart2Size; i++) {
275       incDecRestorePart2[i] = mfcData[i + 1];
276     }
277   }
278   sendRspToUpperLayer = false;
279   status = phNxpNciHal_send_ext_cmd(incDecRestorePart2Size, incDecRestorePart2);
280   if (status != NFCSTATUS_SUCCESS) {
281     NXPLOG_NCIHAL_E("Mifare Cmd for inc/dec/Restore part 2 failed");
282   }
283   return;
284 }
285 
286 /*******************************************************************************
287 **
288 ** Function          AnalyzeMfcResp
289 **
290 ** Description      Analyze type of MFC response and build MFC response from
291 **                  Tag cmd Intf response?
292 **
293 ** Returns          NFCSTATUS_SUCCESS - Data Reception is successful
294 **                  NFCSTATUS_FAILED  - Data Reception failed
295 **
296 *******************************************************************************/
AnalyzeMfcResp(uint8_t * pBuff,uint16_t * pBufflen)297 NFCSTATUS NxpMfcReader::AnalyzeMfcResp(uint8_t* pBuff, uint16_t* pBufflen) {
298   NFCSTATUS status = NFCSTATUS_SUCCESS;
299   uint16_t wPldDataSize = 0;
300   MfcRespId_t RecvdExtnRspId = eInvalidRsp;
301 
302   if (0 == (*pBufflen)) {
303     status = NFCSTATUS_FAILED;
304   } else {
305     RecvdExtnRspId = (MfcRespId_t)pBuff[0];
306     NXPLOG_NCIHAL_E("%s: RecvdExtnRspId=%d", __func__, RecvdExtnRspId);
307     switch (RecvdExtnRspId) {
308       case eMfXchgDataRsp: {
309         NFCSTATUS writeRespStatus = NFCSTATUS_SUCCESS;
310         /* check the status byte */
311         if (*pBufflen == 3) {
312           if ((pBuff[0] == 0x10) && (pBuff[1] != 0x0A)) {
313             NXPLOG_NCIHAL_E("Mifare Error in payload response");
314             *pBufflen = 0x1;
315             pBuff[0] = NFCSTATUS_FAILED;
316             return NFCSTATUS_FAILED;
317           } else {
318             pBuff[0] = NFCSTATUS_SUCCESS;
319             return NFCSTATUS_SUCCESS;
320           }
321         }
322         writeRespStatus = pBuff[*pBufflen - 1];
323 
324         if (NFCSTATUS_SUCCESS == writeRespStatus) {
325           status = NFCSTATUS_SUCCESS;
326           uint16_t wRecvDataSz = 0;
327 
328           wPldDataSize =
329               ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
330           wRecvDataSz = MAX_MFC_BUFF_SIZE;
331           if ((wPldDataSize) <= wRecvDataSz) {
332             /* Extract the data part from pBuff[2] & fill it to be sent to
333              * upper layer */
334             memmove(&(pBuff[0]), &(pBuff[1]), wPldDataSize);
335             /* update the number of bytes received from lower layer,excluding
336              * the status byte */
337             *pBufflen = wPldDataSize;
338           } else {
339             status = NFCSTATUS_FAILED;
340           }
341         } else {
342           status = NFCSTATUS_FAILED;
343         }
344       } break;
345 
346       case eMfcAuthRsp: {
347         /* check the status byte */
348         if (NFCSTATUS_SUCCESS == pBuff[1]) {
349           status = NFCSTATUS_SUCCESS;
350           /* DataLen = TotalRecvdLen - (sizeof(RspId) + sizeof(Status)) */
351           wPldDataSize =
352               ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
353           /* Extract the data part from pBuff[2] & fill it to be sent to upper
354            * layer */
355           pBuff[0] = pBuff[1];
356           /* update the number of bytes received from lower layer,excluding
357            * the status byte */
358           *pBufflen = wPldDataSize + 1;
359         } else {
360           pBuff[0] = pBuff[1];
361           *pBufflen = 1;
362           status = NFCSTATUS_FAILED;
363         }
364       } break;
365       default: {
366         status = NFCSTATUS_FAILED;
367       } break;
368     }
369   }
370   return status;
371 }
372 
373 /*******************************************************************************
374 **
375 ** Function         CheckMfcResponse
376 **
377 ** Description      This function is called to check if it's a valid Mfc
378 **                  response data
379 **
380 ** Returns          NFCSTATUS_SUCCESS
381 **                  NFCSTATUS_FAILED
382 **
383 *******************************************************************************/
CheckMfcResponse(uint8_t * pTransceiveData,uint16_t transceiveDataLen)384 NFCSTATUS NxpMfcReader::CheckMfcResponse(uint8_t* pTransceiveData,
385                                          uint16_t transceiveDataLen) {
386   NFCSTATUS status = NFCSTATUS_SUCCESS;
387 
388   if (transceiveDataLen == 3) {
389     if ((pTransceiveData)[0] == 0x10 && (pTransceiveData)[1] != 0x0A) {
390       NXPLOG_NCIHAL_E("Mifare Error in payload response");
391       transceiveDataLen = 0x1;
392       pTransceiveData += 1;
393       return NFCSTATUS_FAILED;
394     }
395   }
396   if ((pTransceiveData)[0] == 0x40) {
397     pTransceiveData += 1;
398     transceiveDataLen = 0x01;
399     if ((pTransceiveData)[0] == 0x03) {
400       transceiveDataLen = 0x00;
401       status = NFCSTATUS_FAILED;
402     }
403   } else if ((pTransceiveData)[0] == 0x10) {
404     pTransceiveData += 1;
405     transceiveDataLen = 0x10;
406   }
407   return status;
408 }
409