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