• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2019-2023 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 
20 #include <log/log.h>
21 #include <phNfcCompId.h>
22 #include <phNxpLog.h>
23 #include <phNxpNciHal_Adaptation.h>
24 #include <phNxpNciHal_ext.h>
25 
26 #include "phNxpNciHal.h"
27 
28 extern bool sendRspToUpperLayer;
29 extern bool bEnableMfcExtns;
30 extern bool bDisableLegacyMfcExtns;
31 
getInstance()32 NxpMfcReader& NxpMfcReader::getInstance() {
33   static NxpMfcReader msNxpMfcReader;
34   return msNxpMfcReader;
35 }
36 
37 /*******************************************************************************
38 **
39 ** Function         Write
40 **
41 ** Description      Wrapper API to handle Mifare Transceive to TAG_CMD interface
42 **                  RAW read write.
43 **
44 ** Returns          It returns number of bytes successfully written to NFCC.
45 **
46 *******************************************************************************/
Write(uint16_t mfcDataLen,const uint8_t * pMfcData)47 int NxpMfcReader::Write(uint16_t mfcDataLen, const uint8_t* pMfcData) {
48   // Eg:- From the App pMfcData- {|PART1-00 00 06 C1 04| PART2-01 00 00 00|}
49   uint16_t mfcTagCmdBuffLen = 0;
50   uint8_t mfcTagCmdBuff[MAX_MFC_BUFF_SIZE] = {0};
51   uint16_t mfcTagCmdRemainingCmdLen = mfcDataLen;
52 
53   if (mfcDataLen > MAX_MFC_BUFF_SIZE) {
54     android_errorWriteLog(0x534e4554, "169259605");
55     mfcDataLen = MAX_MFC_BUFF_SIZE;
56   }
57   memcpy(mfcTagCmdBuff, pMfcData, mfcDataLen);
58   if (mfcDataLen >= 3) mfcTagCmdBuffLen = mfcDataLen - NCI_HEADER_SIZE;
59   BuildMfcCmd(&mfcTagCmdBuff[3], &mfcTagCmdBuffLen);
60 
61   mfcTagCmdBuff[2] = mfcTagCmdBuffLen;
62 
63   if (checkIsMFCIncDecRestore(pMfcData[3])) {
64     if (sem_init(&mNacksem, 0, 0) != 0) {
65       NXPLOG_NCIHAL_E("%s : sem_init failed", __func__);
66       return 0;
67     }
68   }
69   int writtenDataLen = phNxpNciHal_write_internal(
70       mfcTagCmdBuffLen + NCI_HEADER_SIZE, mfcTagCmdBuff);
71 
72   /* send TAG_CMD part 2 for Mifare increment ,decrement and restore commands */
73   if (checkIsMFCIncDecRestore(pMfcData[3])) {
74     MfcWaitForAck();
75     if (isAck) {
76       NXPLOG_NCIHAL_D("part 1 command Acked");
77       SendIncDecRestoreCmdPart2(
78           mfcTagCmdRemainingCmdLen - MFC_TAG_INCR_DECR_CMD_PART1_LEN,
79           &pMfcData[0]);
80     } else {
81       NXPLOG_NCIHAL_E("part 1 command NACK");
82     }
83     sem_destroy(&mNacksem);
84   }
85   return writtenDataLen;
86 }
87 
88 /*******************************************************************************
89 **
90 ** Function         BuildMfcCmd
91 **
92 ** Description      builds the TAG CMD for Mifare Classic Tag.
93 **
94 ** Returns          None
95 **
96 *******************************************************************************/
BuildMfcCmd(uint8_t * pData,uint16_t * pLength)97 void NxpMfcReader::BuildMfcCmd(uint8_t* pData, uint16_t* pLength) {
98   uint16_t cmdBuffLen = *pLength;
99   memcpy(mMfcTagCmdIntfData.sendBuf, pData, cmdBuffLen);
100   mMfcTagCmdIntfData.sendBufLen = cmdBuffLen;
101 
102   switch (pData[0]) {
103     case eMifareAuthentA:
104     case eMifareAuthentB:
105       BuildAuthCmd();
106       break;
107     case eMifareRead16:
108       BuildReadCmd();
109       break;
110     case eMifareWrite16:
111       AuthForWrite();
112       BuildWrite16Cmd();
113       break;
114     case eMifareInc:
115     case eMifareDec:
116       BuildIncDecCmd();
117       break;
118     default:
119       BuildRawCmd();
120       break;
121   }
122 
123   memcpy(pData, mMfcTagCmdIntfData.sendBuf, (mMfcTagCmdIntfData.sendBufLen));
124   *pLength = (mMfcTagCmdIntfData.sendBufLen);
125   return;
126 }
127 
128 /*******************************************************************************
129 **
130 ** Function         BuildAuthCmd
131 **
132 ** Description      builds the TAG CMD for Mifare Auth.
133 **
134 ** Returns          None
135 **
136 *******************************************************************************/
BuildAuthCmd()137 void NxpMfcReader::BuildAuthCmd() {
138   uint8_t byKey = 0x00, noOfKeys = 0x00;
139   bool isPreloadedKey = false;
140 
141   if (mMfcTagCmdIntfData.sendBuf[0] == eMifareAuthentB) {
142     byKey |= MFC_ENABLE_KEY_B;
143   }
144   uint8_t aMfckeys[MFC_NUM_OF_KEYS][MFC_KEY_SIZE] = MFC_KEYS;
145   noOfKeys = sizeof(aMfckeys) / MFC_KEY_SIZE;
146   for (uint8_t byIndex = 0; byIndex < noOfKeys; byIndex++) {
147     if ((memcmp(aMfckeys[byIndex], &mMfcTagCmdIntfData.sendBuf[6],
148                 MFC_AUTHKEYLEN) == 0x00)) {
149       byKey = byKey | byIndex;
150       isPreloadedKey = true;
151       break;
152     }
153   }
154   CalcSectorAddress();
155   mMfcTagCmdIntfData.sendBufLen = 0x03;
156   if (!isPreloadedKey) {
157     byKey |= MFC_EMBEDDED_KEY;
158     memmove(&mMfcTagCmdIntfData.sendBuf[3], &mMfcTagCmdIntfData.sendBuf[6],
159             MFC_AUTHKEYLEN);
160     mMfcTagCmdIntfData.sendBufLen += MFC_AUTHKEYLEN;
161   }
162 
163   mMfcTagCmdIntfData.sendBuf[0] = eMfcAuthReq;
164   mMfcTagCmdIntfData.sendBuf[1] = mMfcTagCmdIntfData.byAddr;
165   mMfcTagCmdIntfData.sendBuf[2] = byKey;
166   return;
167 }
168 
169 /*******************************************************************************
170 **
171 ** Function         CalcSectorAddress
172 **
173 ** Description      This function update the sector address for Mifare classic
174 **
175 ** Returns          None
176 **
177 *******************************************************************************/
CalcSectorAddress()178 void NxpMfcReader::CalcSectorAddress() {
179   uint8_t BlockNumber = mMfcTagCmdIntfData.sendBuf[1];
180   if (BlockNumber >= MFC_4K_BLK128) {
181     mMfcTagCmdIntfData.byAddr =
182         (uint8_t)(MFC_SECTOR_NO32 +
183                   ((BlockNumber - MFC_4K_BLK128) / MFC_BYTES_PER_BLOCK));
184   } else {
185     mMfcTagCmdIntfData.byAddr = BlockNumber / MFC_BLKS_PER_SECTOR;
186   }
187 
188   return;
189 }
190 
191 /*******************************************************************************
192 **
193 ** Function         BuildReadCmd
194 **
195 ** Description      builds the TAG CMD for Mifare Read.
196 **
197 ** Returns          None
198 **
199 *******************************************************************************/
BuildReadCmd()200 void NxpMfcReader::BuildReadCmd() { BuildRawCmd(); }
201 
202 /*******************************************************************************
203 **
204 ** Function         checkIsMFCIncDecRestore
205 **
206 ** Description      Check command is MF Increment/Decrement or Restore.
207 **
208 ** Returns          True/False
209 **
210 *******************************************************************************/
checkIsMFCIncDecRestore(uint8_t cmdInst)211 bool NxpMfcReader::checkIsMFCIncDecRestore(uint8_t cmdInst) {
212   return (cmdInst == eMifareDec || cmdInst == eMifareInc ||
213           cmdInst == eMifareRestore);
214 }
215 
216 /*******************************************************************************
217 **
218 ** Function         BuildWrite16Cmd
219 **
220 ** Description      builds the TAG CMD for Mifare write part 2.
221 **
222 ** Returns          None
223 **
224 *******************************************************************************/
BuildWrite16Cmd()225 void NxpMfcReader::BuildWrite16Cmd() {
226   mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
227   mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen - 1;
228   uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
229   memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
230   memcpy(buff, mMfcTagCmdIntfData.sendBuf + 2,
231          (mMfcTagCmdIntfData.sendBufLen - 1));
232   memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff,
233          (mMfcTagCmdIntfData.sendBufLen - 1));
234 }
235 
236 /*******************************************************************************
237 **
238 ** Function         BuildRawCmd
239 **
240 ** Description      builds the TAG CMD for Raw transceive.
241 **
242 ** Returns          None
243 **
244 *******************************************************************************/
BuildRawCmd()245 void NxpMfcReader::BuildRawCmd() {
246   mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen + 1;
247   uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
248   memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
249   memcpy(buff, mMfcTagCmdIntfData.sendBuf, mMfcTagCmdIntfData.sendBufLen);
250   memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
251   mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
252 }
253 
254 /*******************************************************************************
255 **
256 ** Function         BuildIncDecCmd
257 **
258 ** Description      builds the TAG CMD for Mifare Inc/Dec.
259 **
260 ** Returns          None
261 **
262 *******************************************************************************/
BuildIncDecCmd()263 void NxpMfcReader::BuildIncDecCmd() {
264   mMfcTagCmdIntfData.sendBufLen = 0x03;  // eMfRawDataXchgHdr + cmd +
265                                          // blockaddress
266   uint8_t buff[mMfcTagCmdIntfData.sendBufLen];
267   memset(buff, 0, mMfcTagCmdIntfData.sendBufLen);
268   memcpy(buff, mMfcTagCmdIntfData.sendBuf, mMfcTagCmdIntfData.sendBufLen);
269   memcpy(mMfcTagCmdIntfData.sendBuf + 1, buff, mMfcTagCmdIntfData.sendBufLen);
270   mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr;
271 }
272 
273 /*******************************************************************************
274 **
275 ** Function         AuthForWrite
276 **
277 ** Description      send Mifare write Part 1.
278 **
279 ** Returns          None
280 **
281 *******************************************************************************/
AuthForWrite()282 void NxpMfcReader::AuthForWrite() {
283   sendRspToUpperLayer = false;
284   NFCSTATUS status = NFCSTATUS_FAILED;
285   uint8_t authForWriteBuff[] = {0x00,
286                                 0x00,
287                                 0x03,
288                                 (uint8_t)eMfRawDataXchgHdr,
289                                 (uint8_t)mMfcTagCmdIntfData.sendBuf[0],
290                                 (uint8_t)mMfcTagCmdIntfData.sendBuf[1]};
291 
292   status = phNxpNciHal_send_ext_cmd(
293       sizeof(authForWriteBuff) / sizeof(authForWriteBuff[0]), authForWriteBuff);
294   if (status != NFCSTATUS_SUCCESS) {
295     NXPLOG_NCIHAL_E("Mifare Auth for Transceive failed");
296   }
297   return;
298 }
299 
300 /*******************************************************************************
301 **
302 ** Function         SendIncDecRestoreCmdPart2
303 **
304 ** Description      send Mifare Inc/Dec/Restore Command Part 2.
305 **
306 ** Returns          None
307 **
308 *******************************************************************************/
SendIncDecRestoreCmdPart2(uint16_t mfcDataLen,const uint8_t * mfcData)309 void NxpMfcReader::SendIncDecRestoreCmdPart2(uint16_t mfcDataLen,
310                                              const uint8_t* mfcData) {
311   NFCSTATUS status = NFCSTATUS_SUCCESS;
312   bool isError = false;
313   /* Build TAG_CMD part 2 for Mifare increment ,decrement and restore commands*/
314   uint8_t incDecRestorePart2[] = {0x00, 0x00, 0x05, (uint8_t)eMfRawDataXchgHdr,
315                                   0x00, 0x00, 0x00, 0x00};
316   uint8_t incDecRestorePart2Size =
317       (sizeof(incDecRestorePart2) / sizeof(incDecRestorePart2[0]));
318   if (mfcData[3] == eMifareInc || mfcData[3] == eMifareDec) {
319     if (mfcDataLen > MFC_TAG_INCR_DECR_CMD_PART2_LEN) {
320       isError = true;
321       incDecRestorePart2Size = MFC_TAG_INCR_DECR_CMD_PART2_LEN;
322     } else if (mfcDataLen < MFC_TAG_INCR_DECR_CMD_PART2_LEN) {
323       isError = true;
324       incDecRestorePart2Size = mfcDataLen;
325     }
326   }
327   if (isError) {
328     android_errorWriteLog(0x534e4554, "238177877");
329   }
330   for (int i = 4; i < incDecRestorePart2Size; i++) {
331     incDecRestorePart2[i] = mfcData[i + 1];
332   }
333   sendRspToUpperLayer = false;
334   status = phNxpNciHal_send_ext_cmd(incDecRestorePart2Size, incDecRestorePart2);
335   if (status != NFCSTATUS_SUCCESS) {
336     NXPLOG_NCIHAL_E("Mifare Cmd for inc/dec/Restore part 2 failed");
337   }
338   return;
339 }
340 
341 /*******************************************************************************
342 **
343 ** Function          AnalyzeMfcResp
344 **
345 ** Description      Analyze type of MFC response and build MFC response from
346 **                  Tag cmd Intf response?
347 **
348 ** Returns          NFCSTATUS_SUCCESS - Data Reception is successful
349 **                  NFCSTATUS_FAILED  - Data Reception failed
350 **
351 *******************************************************************************/
AnalyzeMfcResp(uint8_t * pBuff,uint16_t * pBufflen)352 NFCSTATUS NxpMfcReader::AnalyzeMfcResp(uint8_t* pBuff, uint16_t* pBufflen) {
353   NFCSTATUS status = NFCSTATUS_SUCCESS;
354   uint16_t wPldDataSize = 0;
355   MfcRespId_t RecvdExtnRspId = eInvalidRsp;
356 
357   if (0 == (*pBufflen)) {
358     status = NFCSTATUS_FAILED;
359   } else {
360     RecvdExtnRspId = (MfcRespId_t)pBuff[0];
361     NXPLOG_NCIHAL_E("%s: RecvdExtnRspId=%d", __func__, RecvdExtnRspId);
362     switch (RecvdExtnRspId) {
363       case eMfXchgDataRsp: {
364         NFCSTATUS writeRespStatus = NFCSTATUS_SUCCESS;
365         /* check the status byte */
366         if (*pBufflen == 3) {
367           if ((pBuff[0] == 0x10) && (pBuff[1] != 0x0A)) {
368             NXPLOG_NCIHAL_E("Mifare Error in payload response");
369             *pBufflen = 0x1;
370             pBuff[0] = NFCSTATUS_FAILED;
371             return NFCSTATUS_FAILED;
372           } else {
373             pBuff[0] = NFCSTATUS_SUCCESS;
374             return NFCSTATUS_SUCCESS;
375           }
376         }
377         writeRespStatus = pBuff[*pBufflen - 1];
378 
379         if (NFCSTATUS_SUCCESS == writeRespStatus) {
380           status = NFCSTATUS_SUCCESS;
381           uint16_t wRecvDataSz = 0;
382 
383           wPldDataSize =
384               ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
385           wRecvDataSz = MAX_MFC_BUFF_SIZE;
386           if ((wPldDataSize) <= wRecvDataSz) {
387             /* Extract the data part from pBuff[2] & fill it to be sent to
388              * upper layer */
389             memcpy(&(pBuff[0]), &(pBuff[1]), wPldDataSize);
390             /* update the number of bytes received from lower layer,excluding
391              * the status byte */
392             *pBufflen = wPldDataSize;
393           } else {
394             status = NFCSTATUS_FAILED;
395           }
396         } else {
397           status = NFCSTATUS_FAILED;
398         }
399       } break;
400 
401       case eMfcAuthRsp: {
402         if (*pBufflen < 2) {
403           status = NFCSTATUS_FAILED;
404           break;
405         }
406         /* check the status byte */
407         if (NFCSTATUS_SUCCESS == pBuff[1]) {
408           status = NFCSTATUS_SUCCESS;
409           /* DataLen = TotalRecvdLen - (sizeof(RspId) + sizeof(Status)) */
410           wPldDataSize =
411               ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE));
412           /* Extract the data part from pBuff[2] & fill it to be sent to upper
413            * layer */
414           pBuff[0] = pBuff[1];
415           /* update the number of bytes received from lower layer,excluding
416            * the status byte */
417           *pBufflen = wPldDataSize + 1;
418         } else {
419           pBuff[0] = pBuff[1];
420           *pBufflen = 1;
421           status = NFCSTATUS_FAILED;
422         }
423       } break;
424       default: {
425         status = NFCSTATUS_FAILED;
426       } break;
427     }
428   }
429   return status;
430 }
431 
432 /*******************************************************************************
433 **
434 ** Function         CheckMfcResponse
435 **
436 ** Description      This function is called to check if it's a valid Mfc
437 **                  response data
438 **
439 ** Returns          NFCSTATUS_SUCCESS
440 **                  NFCSTATUS_FAILED
441 **
442 *******************************************************************************/
CheckMfcResponse(uint8_t * pTransceiveData,uint16_t transceiveDataLen)443 NFCSTATUS NxpMfcReader::CheckMfcResponse(uint8_t* pTransceiveData,
444                                          uint16_t transceiveDataLen) {
445   NFCSTATUS status = NFCSTATUS_SUCCESS;
446 
447   if (transceiveDataLen == 3) {
448     if ((pTransceiveData)[0] == 0x10 && (pTransceiveData)[1] != 0x0A) {
449       NXPLOG_NCIHAL_E("Mifare Error in payload response");
450       transceiveDataLen = 0x1;
451       pTransceiveData += 1;
452       return NFCSTATUS_FAILED;
453     }
454   }
455   if ((pTransceiveData)[0] == 0x40) {
456     pTransceiveData += 1;
457     transceiveDataLen = 0x01;
458     if ((pTransceiveData)[0] == 0x03) {
459       transceiveDataLen = 0x00;
460       status = NFCSTATUS_FAILED;
461     }
462   } else if ((pTransceiveData)[0] == 0x10) {
463     pTransceiveData += 1;
464     transceiveDataLen = 0x10;
465   }
466   return status;
467 }
468 
469 /*******************************************************************************
470 **
471 ** Function         MfcAckReceived
472 **
473 ** Description      This function is called to notify that MFC
474 **                  response data is received
475 **
476 ** Returns          NFCSTATUS_SUCCESS
477 **                  NFCSTATUS_FAILED
478 **
479 *******************************************************************************/
MfcNotifyOnAckReceived(uint8_t * buff)480 void NxpMfcReader::MfcNotifyOnAckReceived(uint8_t* buff) {
481   const uint8_t NCI_RF_CONN_ID = 0;
482   /*
483    * If Mifare Activated & received RF data packet
484    */
485   if (bEnableMfcExtns && bDisableLegacyMfcExtns &&
486       (buff[0] == NCI_RF_CONN_ID)) {
487     int sem_val;
488     isAck = (buff[3] == NFCSTATUS_SUCCESS);
489     sem_getvalue(&mNacksem, &sem_val);
490     if (sem_val == 0) {
491       if (sem_post(&mNacksem) == -1) {
492         NXPLOG_NCIHAL_E("%s : sem_post failed", __func__);
493       }
494     }
495   }
496 }
497 
498 /*******************************************************************************
499 **
500 ** Function         MfcWaitForAck
501 **
502 ** Description      This function is called to wait for MFC NACK
503 **
504 ** Returns          NFCSTATUS_SUCCESS
505 **                  NFCSTATUS_FAILED
506 **
507 *******************************************************************************/
MfcWaitForAck()508 NFCSTATUS NxpMfcReader::MfcWaitForAck() {
509   NFCSTATUS status = NFCSTATUS_FAILED;
510   int sem_timedout = 2, s;
511   struct timespec ts;
512   isAck = false;
513   clock_gettime(CLOCK_MONOTONIC, &ts);
514   ts.tv_sec += sem_timedout;
515   while ((s = sem_timedwait_monotonic_np(&mNacksem, &ts)) == -1 && errno == EINTR) {
516     continue; /* Restart if interrupted by handler */
517   }
518   if (s != -1) {
519     status = NFCSTATUS_SUCCESS;
520   }
521   return status;
522 }
523