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