Yerriswamy | 6e16aa1 | 2020-04-18 10:09:25 +0530 | [diff] [blame] | 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 "phNxpNciHal.h" |
| 20 | #include <phNfcCompId.h> |
| 21 | #include <phNxpLog.h> |
| 22 | #include <phNxpNciHal_Adaptation.h> |
| 23 | #include <phNxpNciHal_ext.h> |
| 24 | |
| 25 | extern bool sendRspToUpperLayer; |
| 26 | |
| 27 | NxpMfcReader &NxpMfcReader::getInstance() { |
| 28 | static NxpMfcReader msNxpMfcReader; |
| 29 | return msNxpMfcReader; |
| 30 | } |
| 31 | |
| 32 | /******************************************************************************* |
| 33 | ** |
| 34 | ** Function Write |
| 35 | ** |
| 36 | ** Description Wrapper API to handle Mifare Transceive to TAG_CMD interface |
| 37 | ** RAW read write. |
| 38 | ** |
| 39 | ** Returns It returns number of bytes successfully written to NFCC. |
| 40 | ** |
| 41 | *******************************************************************************/ |
| 42 | int NxpMfcReader::Write(uint16_t mfcDataLen, const uint8_t *pMfcData) { |
| 43 | uint16_t mfcTagCmdBuffLen = 0; |
| 44 | uint8_t mfcTagCmdBuff[MAX_MFC_BUFF_SIZE] = {0}; |
| 45 | |
| 46 | memcpy(mfcTagCmdBuff, pMfcData, mfcDataLen); |
| 47 | if (mfcDataLen >= 3) |
| 48 | mfcTagCmdBuffLen = mfcDataLen - NCI_HEADER_SIZE; |
| 49 | BuildMfcCmd(&mfcTagCmdBuff[3], &mfcTagCmdBuffLen); |
| 50 | |
| 51 | mfcTagCmdBuff[2] = mfcTagCmdBuffLen; |
Alisher Alikhodjaev | ef0a28b | 2023-01-31 18:24:18 -0800 | [diff] [blame] | 52 | int writtenDataLen = phNxpNciHal_write_internal( |
| 53 | mfcTagCmdBuffLen + NCI_HEADER_SIZE, mfcTagCmdBuff); |
Yerriswamy | 6e16aa1 | 2020-04-18 10:09:25 +0530 | [diff] [blame] | 54 | |
| 55 | /* send TAG_CMD part 2 for Mifare increment ,decrement and restore commands */ |
| 56 | if (mfcTagCmdBuff[4] == eMifareDec || mfcTagCmdBuff[4] == eMifareInc || |
| 57 | mfcTagCmdBuff[4] == eMifareRestore) { |
Alisher Alikhodjaev | ef0a28b | 2023-01-31 18:24:18 -0800 | [diff] [blame] | 58 | SendIncDecRestoreCmdPart2(mfcDataLen, pMfcData); |
Yerriswamy | 6e16aa1 | 2020-04-18 10:09:25 +0530 | [diff] [blame] | 59 | } |
| 60 | return writtenDataLen; |
| 61 | } |
| 62 | |
| 63 | /******************************************************************************* |
| 64 | ** |
| 65 | ** Function BuildMfcCmd |
| 66 | ** |
| 67 | ** Description builds the TAG CMD for Mifare Classic Tag. |
| 68 | ** |
| 69 | ** Returns None |
| 70 | ** |
| 71 | *******************************************************************************/ |
| 72 | void NxpMfcReader::BuildMfcCmd(uint8_t *pData, uint16_t *pLength) { |
| 73 | uint16_t cmdBuffLen = *pLength; |
| 74 | memcpy(mMfcTagCmdIntfData.sendBuf, pData, cmdBuffLen); |
| 75 | mMfcTagCmdIntfData.sendBufLen = cmdBuffLen; |
| 76 | |
| 77 | switch (pData[0]) { |
| 78 | case eMifareAuthentA: |
| 79 | case eMifareAuthentB: |
| 80 | BuildAuthCmd(); |
| 81 | break; |
| 82 | case eMifareRead16: |
| 83 | BuildReadCmd(); |
| 84 | break; |
| 85 | case eMifareWrite16: |
| 86 | AuthForWrite(); |
| 87 | BuildWrite16Cmd(); |
| 88 | break; |
| 89 | case eMifareInc: |
| 90 | case eMifareDec: |
| 91 | BuildIncDecCmd(); |
| 92 | break; |
| 93 | default: |
| 94 | BuildRawCmd(); |
| 95 | break; |
| 96 | } |
| 97 | |
| 98 | memcpy(pData, mMfcTagCmdIntfData.sendBuf, (mMfcTagCmdIntfData.sendBufLen)); |
| 99 | *pLength = (mMfcTagCmdIntfData.sendBufLen); |
| 100 | return; |
| 101 | } |
| 102 | |
| 103 | /******************************************************************************* |
| 104 | ** |
| 105 | ** Function BuildAuthCmd |
| 106 | ** |
| 107 | ** Description builds the TAG CMD for Mifare Auth. |
| 108 | ** |
| 109 | ** Returns None |
| 110 | ** |
| 111 | *******************************************************************************/ |
| 112 | void NxpMfcReader::BuildAuthCmd() { |
| 113 | uint8_t byKey = 0x00, noOfKeys = 0x00; |
| 114 | bool isPreloadedKey = false; |
| 115 | |
| 116 | if (mMfcTagCmdIntfData.sendBuf[0] == eMifareAuthentB) { |
| 117 | byKey |= MFC_ENABLE_KEY_B; |
| 118 | } |
| 119 | uint8_t aMfckeys[MFC_NUM_OF_KEYS][MFC_KEY_SIZE] = MFC_KEYS; |
| 120 | noOfKeys = sizeof(aMfckeys) / MFC_KEY_SIZE; |
| 121 | for (uint8_t byIndex = 0; byIndex < noOfKeys; byIndex++) { |
| 122 | if ((memcmp(aMfckeys[byIndex], &mMfcTagCmdIntfData.sendBuf[6], |
| 123 | MFC_AUTHKEYLEN) == 0x00)) { |
| 124 | byKey = byKey | byIndex; |
| 125 | isPreloadedKey = true; |
| 126 | break; |
| 127 | } |
| 128 | } |
| 129 | CalcSectorAddress(); |
| 130 | mMfcTagCmdIntfData.sendBufLen = 0x03; |
| 131 | if (!isPreloadedKey) { |
| 132 | byKey |= MFC_EMBEDDED_KEY; |
| 133 | memcpy(&mMfcTagCmdIntfData.sendBuf[3], &mMfcTagCmdIntfData.sendBuf[6], |
| 134 | MFC_AUTHKEYLEN); |
| 135 | mMfcTagCmdIntfData.sendBufLen += MFC_AUTHKEYLEN; |
| 136 | } |
| 137 | |
| 138 | mMfcTagCmdIntfData.sendBuf[0] = eMfcAuthReq; |
| 139 | mMfcTagCmdIntfData.sendBuf[1] = mMfcTagCmdIntfData.byAddr; |
| 140 | mMfcTagCmdIntfData.sendBuf[2] = byKey; |
| 141 | return; |
| 142 | } |
| 143 | |
| 144 | /******************************************************************************* |
| 145 | ** |
| 146 | ** Function CalcSectorAddress |
| 147 | ** |
| 148 | ** Description This function update the sector address for Mifare classic |
| 149 | ** |
| 150 | ** Returns None |
| 151 | ** |
| 152 | *******************************************************************************/ |
| 153 | void NxpMfcReader::CalcSectorAddress() { |
| 154 | uint8_t BlockNumber = mMfcTagCmdIntfData.sendBuf[1]; |
| 155 | if (BlockNumber >= MFC_4K_BLK128) { |
| 156 | mMfcTagCmdIntfData.byAddr = |
| 157 | (uint8_t)(MFC_SECTOR_NO32 + |
| 158 | ((BlockNumber - MFC_4K_BLK128) / MFC_BYTES_PER_BLOCK)); |
| 159 | } else { |
| 160 | mMfcTagCmdIntfData.byAddr = BlockNumber / MFC_BLKS_PER_SECTOR; |
| 161 | } |
| 162 | |
| 163 | return; |
| 164 | } |
| 165 | |
| 166 | /******************************************************************************* |
| 167 | ** |
| 168 | ** Function BuildReadCmd |
| 169 | ** |
| 170 | ** Description builds the TAG CMD for Mifare Read. |
| 171 | ** |
| 172 | ** Returns None |
| 173 | ** |
| 174 | *******************************************************************************/ |
| 175 | void NxpMfcReader::BuildReadCmd() { BuildRawCmd(); } |
| 176 | |
| 177 | /******************************************************************************* |
| 178 | ** |
| 179 | ** Function BuildWrite16Cmd |
| 180 | ** |
| 181 | ** Description builds the TAG CMD for Mifare write part 2. |
| 182 | ** |
| 183 | ** Returns None |
| 184 | ** |
| 185 | *******************************************************************************/ |
| 186 | void NxpMfcReader::BuildWrite16Cmd() { |
| 187 | mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr; |
| 188 | mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen - 1; |
| 189 | memmove(mMfcTagCmdIntfData.sendBuf + 1, mMfcTagCmdIntfData.sendBuf + 2, |
| 190 | mMfcTagCmdIntfData.sendBufLen); |
| 191 | } |
| 192 | |
| 193 | /******************************************************************************* |
| 194 | ** |
| 195 | ** Function BuildRawCmd |
| 196 | ** |
| 197 | ** Description builds the TAG CMD for Raw transceive. |
| 198 | ** |
| 199 | ** Returns None |
| 200 | ** |
| 201 | *******************************************************************************/ |
| 202 | void NxpMfcReader::BuildRawCmd() { |
| 203 | mMfcTagCmdIntfData.sendBufLen = mMfcTagCmdIntfData.sendBufLen + 1; |
| 204 | memmove(mMfcTagCmdIntfData.sendBuf + 1, mMfcTagCmdIntfData.sendBuf, |
| 205 | mMfcTagCmdIntfData.sendBufLen); |
| 206 | mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr; |
| 207 | } |
| 208 | |
| 209 | /******************************************************************************* |
| 210 | ** |
| 211 | ** Function BuildIncDecCmd |
| 212 | ** |
| 213 | ** Description builds the TAG CMD for Mifare Inc/Dec. |
| 214 | ** |
| 215 | ** Returns None |
| 216 | ** |
| 217 | *******************************************************************************/ |
| 218 | void NxpMfcReader::BuildIncDecCmd() { |
| 219 | mMfcTagCmdIntfData.sendBufLen = 0x03; // eMfRawDataXchgHdr + cmd + |
| 220 | // blockaddress |
| 221 | memmove(mMfcTagCmdIntfData.sendBuf + 1, mMfcTagCmdIntfData.sendBuf, |
| 222 | mMfcTagCmdIntfData.sendBufLen); |
| 223 | mMfcTagCmdIntfData.sendBuf[0] = eMfRawDataXchgHdr; |
| 224 | } |
| 225 | |
| 226 | /******************************************************************************* |
| 227 | ** |
| 228 | ** Function AuthForWrite |
| 229 | ** |
| 230 | ** Description send Mifare write Part 1. |
| 231 | ** |
| 232 | ** Returns None |
| 233 | ** |
| 234 | *******************************************************************************/ |
| 235 | void NxpMfcReader::AuthForWrite() { |
| 236 | sendRspToUpperLayer = false; |
| 237 | NFCSTATUS status = NFCSTATUS_FAILED; |
| 238 | uint8_t authForWriteBuff[] = {0x00, |
| 239 | 0x00, |
| 240 | 0x03, |
| 241 | (uint8_t)eMfRawDataXchgHdr, |
| 242 | (uint8_t)mMfcTagCmdIntfData.sendBuf[0], |
| 243 | (uint8_t)mMfcTagCmdIntfData.sendBuf[1]}; |
| 244 | |
| 245 | status = phNxpNciHal_send_ext_cmd( |
| 246 | sizeof(authForWriteBuff) / sizeof(authForWriteBuff[0]), authForWriteBuff); |
| 247 | if (status != NFCSTATUS_SUCCESS) { |
| 248 | NXPLOG_NCIHAL_E("Mifare Auth for Transceive failed"); |
| 249 | } |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | /******************************************************************************* |
| 254 | ** |
| 255 | ** Function SendIncDecRestoreCmdPart2 |
| 256 | ** |
| 257 | ** Description send Mifare Inc/Dec/Restore Command Part 2. |
| 258 | ** |
| 259 | ** Returns None |
| 260 | ** |
| 261 | *******************************************************************************/ |
Alisher Alikhodjaev | ef0a28b | 2023-01-31 18:24:18 -0800 | [diff] [blame] | 262 | void NxpMfcReader::SendIncDecRestoreCmdPart2(uint16_t mfcDataLen, |
| 263 | const uint8_t *mfcData) { |
Yerriswamy | 6e16aa1 | 2020-04-18 10:09:25 +0530 | [diff] [blame] | 264 | NFCSTATUS status = NFCSTATUS_SUCCESS; |
| 265 | /* Build TAG_CMD part 2 for Mifare increment ,decrement and restore commands*/ |
| 266 | uint8_t incDecRestorePart2[] = {0x00, 0x00, 0x05, (uint8_t)eMfRawDataXchgHdr, |
| 267 | 0x00, 0x00, 0x00, 0x00}; |
| 268 | uint8_t incDecRestorePart2Size = |
| 269 | (sizeof(incDecRestorePart2) / sizeof(incDecRestorePart2[0])); |
| 270 | if (mfcData[3] == eMifareInc || mfcData[3] == eMifareDec) { |
Alisher Alikhodjaev | ef0a28b | 2023-01-31 18:24:18 -0800 | [diff] [blame] | 271 | if (incDecRestorePart2Size >= mfcDataLen) { |
| 272 | incDecRestorePart2Size = mfcDataLen - 1; |
| 273 | android_errorWriteLog(0x534e4554, "238177877"); |
| 274 | } |
Yerriswamy | 6e16aa1 | 2020-04-18 10:09:25 +0530 | [diff] [blame] | 275 | for (int i = 4; i < incDecRestorePart2Size; i++) { |
| 276 | incDecRestorePart2[i] = mfcData[i + 1]; |
| 277 | } |
| 278 | } |
| 279 | sendRspToUpperLayer = false; |
| 280 | status = phNxpNciHal_send_ext_cmd(incDecRestorePart2Size, incDecRestorePart2); |
| 281 | if (status != NFCSTATUS_SUCCESS) { |
| 282 | NXPLOG_NCIHAL_E("Mifare Cmd for inc/dec/Restore part 2 failed"); |
| 283 | } |
| 284 | return; |
| 285 | } |
| 286 | |
| 287 | /******************************************************************************* |
| 288 | ** |
| 289 | ** Function AnalyzeMfcResp |
| 290 | ** |
| 291 | ** Description Analyze type of MFC response and build MFC response from |
| 292 | ** Tag cmd Intf response? |
| 293 | ** |
| 294 | ** Returns NFCSTATUS_SUCCESS - Data Reception is successful |
| 295 | ** NFCSTATUS_FAILED - Data Reception failed |
| 296 | ** |
| 297 | *******************************************************************************/ |
| 298 | NFCSTATUS NxpMfcReader::AnalyzeMfcResp(uint8_t *pBuff, uint16_t *pBufflen) { |
| 299 | NFCSTATUS status = NFCSTATUS_SUCCESS; |
| 300 | uint16_t wPldDataSize = 0; |
| 301 | MfcRespId_t RecvdExtnRspId = eInvalidRsp; |
| 302 | |
| 303 | if (0 == (*pBufflen)) { |
| 304 | status = NFCSTATUS_FAILED; |
| 305 | } else { |
| 306 | RecvdExtnRspId = (MfcRespId_t)pBuff[0]; |
| 307 | NXPLOG_NCIHAL_E("%s: RecvdExtnRspId=%d", __func__, RecvdExtnRspId); |
| 308 | switch (RecvdExtnRspId) { |
| 309 | case eMfXchgDataRsp: { |
| 310 | NFCSTATUS writeRespStatus = NFCSTATUS_SUCCESS; |
| 311 | /* check the status byte */ |
| 312 | if (*pBufflen == 3) { |
| 313 | if ((pBuff[0] == 0x10) && (pBuff[1] != 0x0A)) { |
| 314 | NXPLOG_NCIHAL_E("Mifare Error in payload response"); |
| 315 | *pBufflen = 0x1; |
| 316 | pBuff[0] = NFCSTATUS_FAILED; |
| 317 | return NFCSTATUS_FAILED; |
| 318 | } else { |
| 319 | pBuff[0] = NFCSTATUS_SUCCESS; |
| 320 | return NFCSTATUS_SUCCESS; |
| 321 | } |
| 322 | } |
| 323 | writeRespStatus = pBuff[*pBufflen - 1]; |
| 324 | |
| 325 | if (NFCSTATUS_SUCCESS == writeRespStatus) { |
| 326 | status = NFCSTATUS_SUCCESS; |
| 327 | uint16_t wRecvDataSz = 0; |
| 328 | |
| 329 | wPldDataSize = |
| 330 | ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE)); |
| 331 | wRecvDataSz = MAX_MFC_BUFF_SIZE; |
| 332 | if ((wPldDataSize) <= wRecvDataSz) { |
| 333 | /* Extract the data part from pBuff[2] & fill it to be sent to |
| 334 | * upper layer */ |
| 335 | memmove(&(pBuff[0]), &(pBuff[1]), wPldDataSize); |
| 336 | /* update the number of bytes received from lower layer,excluding |
| 337 | * the status byte */ |
| 338 | *pBufflen = wPldDataSize; |
| 339 | } else { |
| 340 | status = NFCSTATUS_FAILED; |
| 341 | } |
| 342 | } else { |
| 343 | status = NFCSTATUS_FAILED; |
| 344 | } |
| 345 | } break; |
| 346 | |
| 347 | case eMfcAuthRsp: { |
| 348 | /* check the status byte */ |
| 349 | if (NFCSTATUS_SUCCESS == pBuff[1]) { |
| 350 | status = NFCSTATUS_SUCCESS; |
| 351 | /* DataLen = TotalRecvdLen - (sizeof(RspId) + sizeof(Status)) */ |
| 352 | wPldDataSize = |
| 353 | ((*pBufflen) - (MFC_EXTN_ID_SIZE + MFC_EXTN_STATUS_SIZE)); |
| 354 | /* Extract the data part from pBuff[2] & fill it to be sent to upper |
| 355 | * layer */ |
| 356 | pBuff[0] = pBuff[1]; |
| 357 | /* update the number of bytes received from lower layer,excluding |
| 358 | * the status byte */ |
| 359 | *pBufflen = wPldDataSize + 1; |
| 360 | } else { |
| 361 | pBuff[0] = pBuff[1]; |
| 362 | *pBufflen = 1; |
| 363 | status = NFCSTATUS_FAILED; |
| 364 | } |
| 365 | } break; |
| 366 | default: { status = NFCSTATUS_FAILED; } break; |
| 367 | } |
| 368 | } |
| 369 | return status; |
| 370 | } |
| 371 | |
| 372 | /******************************************************************************* |
| 373 | ** |
| 374 | ** Function CheckMfcResponse |
| 375 | ** |
| 376 | ** Description This function is called to check if it's a valid Mfc |
| 377 | ** response data |
| 378 | ** |
| 379 | ** Returns NFCSTATUS_SUCCESS |
| 380 | ** NFCSTATUS_FAILED |
| 381 | ** |
| 382 | *******************************************************************************/ |
| 383 | NFCSTATUS NxpMfcReader::CheckMfcResponse(uint8_t *pTransceiveData, |
| 384 | uint16_t transceiveDataLen) { |
| 385 | NFCSTATUS status = NFCSTATUS_SUCCESS; |
| 386 | |
| 387 | if (transceiveDataLen == 3) { |
| 388 | if ((pTransceiveData)[0] == 0x10 && (pTransceiveData)[1] != 0x0A) { |
| 389 | NXPLOG_NCIHAL_E("Mifare Error in payload response"); |
| 390 | transceiveDataLen = 0x1; |
| 391 | pTransceiveData += 1; |
| 392 | return NFCSTATUS_FAILED; |
| 393 | } |
| 394 | } |
| 395 | if ((pTransceiveData)[0] == 0x40) { |
| 396 | pTransceiveData += 1; |
| 397 | transceiveDataLen = 0x01; |
| 398 | if ((pTransceiveData)[0] == 0x03) { |
| 399 | transceiveDataLen = 0x00; |
| 400 | status = NFCSTATUS_FAILED; |
| 401 | } |
| 402 | } else if ((pTransceiveData)[0] == 0x10) { |
| 403 | pTransceiveData += 1; |
| 404 | transceiveDataLen = 0x10; |
| 405 | } |
| 406 | return status; |
| 407 | } |