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