| 1 | //-----------------------------------------------------------------------------\r |
| 2 | // Merlok - June 2011, 2012\r |
| 3 | // Gerhard de Koning Gans - May 2008\r |
| 4 | // Hagen Fritsch - June 2010\r |
| 5 | //\r |
| 6 | // This code is licensed to you under the terms of the GNU GPL, version 2 or,\r |
| 7 | // at your option, any later version. See the LICENSE.txt file for the text of\r |
| 8 | // the license.\r |
| 9 | //-----------------------------------------------------------------------------\r |
| 10 | // Routines to support ISO 14443 type A.\r |
| 11 | //-----------------------------------------------------------------------------\r |
| 12 | \r |
| 13 | #include "mifarecmd.h"\r |
| 14 | #include "apps.h"\r |
| 15 | \r |
| 16 | //-----------------------------------------------------------------------------\r |
| 17 | // Select, Authenticaate, Read an MIFARE tag. \r |
| 18 | // read block\r |
| 19 | //-----------------------------------------------------------------------------\r |
| 20 | void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r |
| 21 | {\r |
| 22 | // params\r |
| 23 | uint8_t blockNo = arg0;\r |
| 24 | uint8_t keyType = arg1;\r |
| 25 | uint64_t ui64Key = 0;\r |
| 26 | ui64Key = bytes_to_num(datain, 6);\r |
| 27 | \r |
| 28 | // variables\r |
| 29 | byte_t isOK = 0;\r |
| 30 | byte_t dataoutbuf[16];\r |
| 31 | uint8_t uid[8];\r |
| 32 | uint32_t cuid;\r |
| 33 | struct Crypto1State mpcs = {0, 0};\r |
| 34 | struct Crypto1State *pcs;\r |
| 35 | pcs = &mpcs;\r |
| 36 | \r |
| 37 | // clear trace\r |
| 38 | iso14a_clear_trace();\r |
| 39 | // iso14a_set_tracing(false);\r |
| 40 | \r |
| 41 | iso14443a_setup();\r |
| 42 | \r |
| 43 | LED_A_ON();\r |
| 44 | LED_B_OFF();\r |
| 45 | LED_C_OFF();\r |
| 46 | \r |
| 47 | while (true) {\r |
| 48 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 49 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 50 | break;\r |
| 51 | };\r |
| 52 | \r |
| 53 | if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r |
| 54 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r |
| 55 | break;\r |
| 56 | };\r |
| 57 | \r |
| 58 | if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {\r |
| 59 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r |
| 60 | break;\r |
| 61 | };\r |
| 62 | \r |
| 63 | if(mifare_classic_halt(pcs, cuid)) {\r |
| 64 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 65 | break;\r |
| 66 | };\r |
| 67 | \r |
| 68 | isOK = 1;\r |
| 69 | break;\r |
| 70 | }\r |
| 71 | \r |
| 72 | // ----------------------------- crypto1 destroy\r |
| 73 | crypto1_destroy(pcs);\r |
| 74 | \r |
| 75 | if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r |
| 76 | \r |
| 77 | // add trace trailer\r |
| 78 | memset(uid, 0x44, 4);\r |
| 79 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 80 | \r |
| 81 | // UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r |
| 82 | // memcpy(ack.d.asBytes, dataoutbuf, 16);\r |
| 83 | \r |
| 84 | LED_B_ON();\r |
| 85 | cmd_send(CMD_ACK,isOK,0,0,0,0);\r |
| 86 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 87 | LED_B_OFF();\r |
| 88 | \r |
| 89 | \r |
| 90 | // Thats it...\r |
| 91 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 92 | LEDsoff();\r |
| 93 | // iso14a_set_tracing(TRUE);\r |
| 94 | \r |
| 95 | }\r |
| 96 | \r |
| 97 | //-----------------------------------------------------------------------------\r |
| 98 | // Select, Authenticaate, Read an MIFARE tag. \r |
| 99 | // read sector (data = 4 x 16 bytes = 64 bytes)\r |
| 100 | //-----------------------------------------------------------------------------\r |
| 101 | void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r |
| 102 | {\r |
| 103 | // params\r |
| 104 | uint8_t sectorNo = arg0;\r |
| 105 | uint8_t keyType = arg1;\r |
| 106 | uint64_t ui64Key = 0;\r |
| 107 | ui64Key = bytes_to_num(datain, 6);\r |
| 108 | \r |
| 109 | // variables\r |
| 110 | byte_t isOK = 0;\r |
| 111 | byte_t dataoutbuf[16 * 4];\r |
| 112 | uint8_t uid[8];\r |
| 113 | uint32_t cuid;\r |
| 114 | struct Crypto1State mpcs = {0, 0};\r |
| 115 | struct Crypto1State *pcs;\r |
| 116 | pcs = &mpcs;\r |
| 117 | \r |
| 118 | // clear trace\r |
| 119 | iso14a_clear_trace();\r |
| 120 | // iso14a_set_tracing(false);\r |
| 121 | \r |
| 122 | iso14443a_setup();\r |
| 123 | \r |
| 124 | LED_A_ON();\r |
| 125 | LED_B_OFF();\r |
| 126 | LED_C_OFF();\r |
| 127 | \r |
| 128 | while (true) {\r |
| 129 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 130 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 131 | break;\r |
| 132 | };\r |
| 133 | \r |
| 134 | if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {\r |
| 135 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r |
| 136 | break;\r |
| 137 | };\r |
| 138 | \r |
| 139 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf + 16 * 0)) {\r |
| 140 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 0 error");\r |
| 141 | break;\r |
| 142 | };\r |
| 143 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf + 16 * 1)) {\r |
| 144 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 1 error");\r |
| 145 | break;\r |
| 146 | };\r |
| 147 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf + 16 * 2)) {\r |
| 148 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 2 error");\r |
| 149 | break;\r |
| 150 | };\r |
| 151 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf + 16 * 3)) {\r |
| 152 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 3 error");\r |
| 153 | break;\r |
| 154 | };\r |
| 155 | \r |
| 156 | if(mifare_classic_halt(pcs, cuid)) {\r |
| 157 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 158 | break;\r |
| 159 | };\r |
| 160 | \r |
| 161 | isOK = 1;\r |
| 162 | break;\r |
| 163 | }\r |
| 164 | \r |
| 165 | // ----------------------------- crypto1 destroy\r |
| 166 | crypto1_destroy(pcs);\r |
| 167 | \r |
| 168 | if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");\r |
| 169 | \r |
| 170 | // add trace trailer\r |
| 171 | memset(uid, 0x44, 4);\r |
| 172 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 173 | \r |
| 174 | // UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r |
| 175 | // memcpy(ack.d.asBytes, dataoutbuf, 16 * 2);\r |
| 176 | \r |
| 177 | LED_B_ON();\r |
| 178 | cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,32);\r |
| 179 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 180 | // SpinDelay(100);\r |
| 181 | \r |
| 182 | // memcpy(ack.d.asBytes, dataoutbuf + 16 * 2, 16 * 2);\r |
| 183 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 184 | cmd_send(CMD_ACK,isOK,0,0,dataoutbuf+32, 32);\r |
| 185 | LED_B_OFF();\r |
| 186 | \r |
| 187 | // Thats it...\r |
| 188 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 189 | LEDsoff();\r |
| 190 | // iso14a_set_tracing(TRUE);\r |
| 191 | \r |
| 192 | }\r |
| 193 | \r |
| 194 | //-----------------------------------------------------------------------------\r |
| 195 | // Select, Authenticaate, Read an MIFARE tag. \r |
| 196 | // read block\r |
| 197 | //-----------------------------------------------------------------------------\r |
| 198 | void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r |
| 199 | {\r |
| 200 | // params\r |
| 201 | uint8_t blockNo = arg0;\r |
| 202 | uint8_t keyType = arg1;\r |
| 203 | uint64_t ui64Key = 0;\r |
| 204 | byte_t blockdata[16];\r |
| 205 | \r |
| 206 | ui64Key = bytes_to_num(datain, 6);\r |
| 207 | memcpy(blockdata, datain + 10, 16);\r |
| 208 | \r |
| 209 | // variables\r |
| 210 | byte_t isOK = 0;\r |
| 211 | uint8_t uid[8];\r |
| 212 | uint32_t cuid;\r |
| 213 | struct Crypto1State mpcs = {0, 0};\r |
| 214 | struct Crypto1State *pcs;\r |
| 215 | pcs = &mpcs;\r |
| 216 | \r |
| 217 | // clear trace\r |
| 218 | iso14a_clear_trace();\r |
| 219 | // iso14a_set_tracing(false);\r |
| 220 | \r |
| 221 | iso14443a_setup();\r |
| 222 | \r |
| 223 | LED_A_ON();\r |
| 224 | LED_B_OFF();\r |
| 225 | LED_C_OFF();\r |
| 226 | \r |
| 227 | while (true) {\r |
| 228 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 229 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 230 | break;\r |
| 231 | };\r |
| 232 | \r |
| 233 | if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r |
| 234 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r |
| 235 | break;\r |
| 236 | };\r |
| 237 | \r |
| 238 | if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {\r |
| 239 | if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r |
| 240 | break;\r |
| 241 | };\r |
| 242 | \r |
| 243 | if(mifare_classic_halt(pcs, cuid)) {\r |
| 244 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 245 | break;\r |
| 246 | };\r |
| 247 | \r |
| 248 | isOK = 1;\r |
| 249 | break;\r |
| 250 | }\r |
| 251 | \r |
| 252 | // ----------------------------- crypto1 destroy\r |
| 253 | crypto1_destroy(pcs);\r |
| 254 | \r |
| 255 | if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r |
| 256 | \r |
| 257 | // add trace trailer\r |
| 258 | memset(uid, 0x44, 4);\r |
| 259 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 260 | \r |
| 261 | // UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r |
| 262 | \r |
| 263 | LED_B_ON();\r |
| 264 | cmd_send(CMD_ACK,isOK,0,0,0,0);\r |
| 265 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 266 | LED_B_OFF();\r |
| 267 | \r |
| 268 | \r |
| 269 | // Thats it...\r |
| 270 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 271 | LEDsoff();\r |
| 272 | // iso14a_set_tracing(TRUE);\r |
| 273 | \r |
| 274 | }\r |
| 275 | \r |
| 276 | // Return 1 if the nonce is invalid else return 0\r |
| 277 | int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) {\r |
| 278 | return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \\r |
| 279 | (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \\r |
| 280 | (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;\r |
| 281 | }\r |
| 282 | \r |
| 283 | //-----------------------------------------------------------------------------\r |
| 284 | // MIFARE nested authentication. \r |
| 285 | // \r |
| 286 | //-----------------------------------------------------------------------------\r |
| 287 | void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)\r |
| 288 | {\r |
| 289 | // params\r |
| 290 | uint8_t blockNo = arg0;\r |
| 291 | uint8_t keyType = arg1;\r |
| 292 | uint8_t targetBlockNo = arg2 & 0xff;\r |
| 293 | uint8_t targetKeyType = (arg2 >> 8) & 0xff;\r |
| 294 | uint64_t ui64Key = 0;\r |
| 295 | \r |
| 296 | ui64Key = bytes_to_num(datain, 6);\r |
| 297 | \r |
| 298 | // variables\r |
| 299 | int rtr, i, j, m, len;\r |
| 300 | int davg, dmin, dmax;\r |
| 301 | uint8_t uid[8];\r |
| 302 | uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1;\r |
| 303 | uint8_t par_array[4];\r |
| 304 | nestedVector nvector[NES_MAX_INFO + 1][11];\r |
| 305 | int nvectorcount[NES_MAX_INFO + 1];\r |
| 306 | int ncount = 0;\r |
| 307 | struct Crypto1State mpcs = {0, 0};\r |
| 308 | struct Crypto1State *pcs;\r |
| 309 | pcs = &mpcs;\r |
| 310 | uint8_t* receivedAnswer = mifare_get_bigbufptr();\r |
| 311 | \r |
| 312 | //init\r |
| 313 | for (i = 0; i < NES_MAX_INFO + 1; i++) nvectorcount[i] = 11; // 11 - empty block;\r |
| 314 | \r |
| 315 | // clear trace\r |
| 316 | iso14a_clear_trace();\r |
| 317 | iso14a_set_tracing(false);\r |
| 318 | \r |
| 319 | iso14443a_setup();\r |
| 320 | \r |
| 321 | LED_A_ON();\r |
| 322 | LED_B_ON();\r |
| 323 | LED_C_OFF();\r |
| 324 | \r |
| 325 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 326 | SpinDelay(200);\r |
| 327 | \r |
| 328 | davg = dmax = 0;\r |
| 329 | dmin = 2000;\r |
| 330 | \r |
| 331 | // test nonce distance\r |
| 332 | for (rtr = 0; rtr < 10; rtr++) {\r |
| 333 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 334 | SpinDelay(100);\r |
| 335 | FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r |
| 336 | \r |
| 337 | // Test if the action was cancelled\r |
| 338 | if(BUTTON_PRESS()) {\r |
| 339 | break;\r |
| 340 | }\r |
| 341 | \r |
| 342 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 343 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 344 | break;\r |
| 345 | };\r |
| 346 | \r |
| 347 | if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {\r |
| 348 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error");\r |
| 349 | break;\r |
| 350 | };\r |
| 351 | \r |
| 352 | if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2)) {\r |
| 353 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error");\r |
| 354 | break;\r |
| 355 | };\r |
| 356 | \r |
| 357 | nttmp = prng_successor(nt1, 500);\r |
| 358 | for (i = 501; i < 2000; i++) {\r |
| 359 | nttmp = prng_successor(nttmp, 1);\r |
| 360 | if (nttmp == nt2) break;\r |
| 361 | }\r |
| 362 | \r |
| 363 | if (i != 2000) {\r |
| 364 | davg += i;\r |
| 365 | if (dmin > i) dmin = i;\r |
| 366 | if (dmax < i) dmax = i;\r |
| 367 | if (MF_DBGLEVEL >= 4) Dbprintf("r=%d nt1=%08x nt2=%08x distance=%d", rtr, nt1, nt2, i);\r |
| 368 | }\r |
| 369 | }\r |
| 370 | \r |
| 371 | if (rtr == 0) return;\r |
| 372 | \r |
| 373 | davg = davg / rtr;\r |
| 374 | if (MF_DBGLEVEL >= 3) Dbprintf("distance: min=%d max=%d avg=%d", dmin, dmax, davg);\r |
| 375 | \r |
| 376 | LED_B_OFF();\r |
| 377 | \r |
| 378 | // ------------------------------------------------------------------------------------------------- \r |
| 379 | \r |
| 380 | LED_C_ON();\r |
| 381 | \r |
| 382 | // get crypted nonces for target sector\r |
| 383 | for (rtr = 0; rtr < NS_RETRIES_GETNONCE; rtr++) {\r |
| 384 | if (MF_DBGLEVEL >= 4) Dbprintf("------------------------------");\r |
| 385 | \r |
| 386 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 387 | SpinDelay(100);\r |
| 388 | FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r |
| 389 | \r |
| 390 | // Test if the action was cancelled\r |
| 391 | if(BUTTON_PRESS()) {\r |
| 392 | break;\r |
| 393 | }\r |
| 394 | \r |
| 395 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 396 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 397 | break;\r |
| 398 | };\r |
| 399 | \r |
| 400 | if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {\r |
| 401 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error");\r |
| 402 | break;\r |
| 403 | };\r |
| 404 | \r |
| 405 | // nested authentication\r |
| 406 | len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par);\r |
| 407 | if (len != 4) {\r |
| 408 | if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error len=%d", len);\r |
| 409 | break;\r |
| 410 | };\r |
| 411 | \r |
| 412 | nt2 = bytes_to_num(receivedAnswer, 4); \r |
| 413 | if (MF_DBGLEVEL >= 4) Dbprintf("r=%d nt1=%08x nt2enc=%08x nt2par=%08x", rtr, nt1, nt2, par);\r |
| 414 | \r |
| 415 | // Parity validity check\r |
| 416 | for (i = 0; i < 4; i++) {\r |
| 417 | par_array[i] = (oddparity(receivedAnswer[i]) != ((par & 0x08) >> 3));\r |
| 418 | par = par << 1;\r |
| 419 | }\r |
| 420 | \r |
| 421 | ncount = 0;\r |
| 422 | nttest = prng_successor(nt1, dmin - NS_TOLERANCE);\r |
| 423 | for (m = dmin - NS_TOLERANCE + 1; m < dmax + NS_TOLERANCE; m++) {\r |
| 424 | nttest = prng_successor(nttest, 1);\r |
| 425 | ks1 = nt2 ^ nttest;\r |
| 426 | \r |
| 427 | if (valid_nonce(nttest, nt2, ks1, par_array) && (ncount < 11)){\r |
| 428 | \r |
| 429 | nvector[NES_MAX_INFO][ncount].nt = nttest;\r |
| 430 | nvector[NES_MAX_INFO][ncount].ks1 = ks1;\r |
| 431 | ncount++;\r |
| 432 | nvectorcount[NES_MAX_INFO] = ncount;\r |
| 433 | if (MF_DBGLEVEL >= 4) Dbprintf("valid m=%d ks1=%08x nttest=%08x", m, ks1, nttest);\r |
| 434 | }\r |
| 435 | \r |
| 436 | }\r |
| 437 | \r |
| 438 | // select vector with length less than got\r |
| 439 | if (nvectorcount[NES_MAX_INFO] != 0) {\r |
| 440 | m = NES_MAX_INFO;\r |
| 441 | \r |
| 442 | for (i = 0; i < NES_MAX_INFO; i++)\r |
| 443 | if (nvectorcount[i] > 10) {\r |
| 444 | m = i;\r |
| 445 | break;\r |
| 446 | }\r |
| 447 | \r |
| 448 | if (m == NES_MAX_INFO)\r |
| 449 | for (i = 0; i < NES_MAX_INFO; i++)\r |
| 450 | if (nvectorcount[NES_MAX_INFO] < nvectorcount[i]) {\r |
| 451 | m = i;\r |
| 452 | break;\r |
| 453 | }\r |
| 454 | \r |
| 455 | if (m != NES_MAX_INFO) {\r |
| 456 | for (i = 0; i < nvectorcount[m]; i++) {\r |
| 457 | nvector[m][i] = nvector[NES_MAX_INFO][i];\r |
| 458 | }\r |
| 459 | nvectorcount[m] = nvectorcount[NES_MAX_INFO];\r |
| 460 | }\r |
| 461 | }\r |
| 462 | }\r |
| 463 | \r |
| 464 | LED_C_OFF();\r |
| 465 | \r |
| 466 | // ----------------------------- crypto1 destroy\r |
| 467 | crypto1_destroy(pcs);\r |
| 468 | \r |
| 469 | // add trace trailer\r |
| 470 | memset(uid, 0x44, 4);\r |
| 471 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 472 | \r |
| 473 | // UsbCommand ack = {CMD_ACK, {0, 0, 0}};\r |
| 474 | \r |
| 475 | for (i = 0; i < NES_MAX_INFO; i++) {\r |
| 476 | if (nvectorcount[i] > 10) continue;\r |
| 477 | \r |
| 478 | for (j = 0; j < nvectorcount[i]; j += 5) {\r |
| 479 | ncount = nvectorcount[i] - j;\r |
| 480 | if (ncount > 5) ncount = 5; \r |
| 481 | \r |
| 482 | // ack.arg[0] = 0; // isEOF = 0\r |
| 483 | // ack.arg[1] = ncount;\r |
| 484 | // ack.arg[2] = targetBlockNo + (targetKeyType * 0x100);\r |
| 485 | // memset(ack.d.asBytes, 0x00, sizeof(ack.d.asBytes));\r |
| 486 | \r |
| 487 | byte_t buf[48];\r |
| 488 | memset(buf, 0x00, sizeof(buf));\r |
| 489 | memcpy(buf, &cuid, 4);\r |
| 490 | for (m = 0; m < ncount; m++) {\r |
| 491 | memcpy(buf + 8 + m * 8 + 0, &nvector[i][m + j].nt, 4);\r |
| 492 | memcpy(buf + 8 + m * 8 + 4, &nvector[i][m + j].ks1, 4);\r |
| 493 | }\r |
| 494 | \r |
| 495 | LED_B_ON();\r |
| 496 | // SpinDelay(100);\r |
| 497 | cmd_send(CMD_ACK,0,ncount,targetBlockNo + (targetKeyType * 0x100),buf,48);\r |
| 498 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 499 | LED_B_OFF();\r |
| 500 | }\r |
| 501 | }\r |
| 502 | \r |
| 503 | // finalize list\r |
| 504 | // ack.arg[0] = 1; // isEOF = 1\r |
| 505 | // ack.arg[1] = 0;\r |
| 506 | // ack.arg[2] = 0;\r |
| 507 | // memset(ack.d.asBytes, 0x00, sizeof(ack.d.asBytes));\r |
| 508 | \r |
| 509 | LED_B_ON();\r |
| 510 | // SpinDelay(300);\r |
| 511 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 512 | cmd_send(CMD_ACK,1,0,0,0,0);\r |
| 513 | LED_B_OFF();\r |
| 514 | \r |
| 515 | if (MF_DBGLEVEL >= 4) DbpString("NESTED FINISHED");\r |
| 516 | \r |
| 517 | // Thats it...\r |
| 518 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 519 | LEDsoff();\r |
| 520 | \r |
| 521 | iso14a_set_tracing(TRUE);\r |
| 522 | }\r |
| 523 | \r |
| 524 | //-----------------------------------------------------------------------------\r |
| 525 | // MIFARE check keys. key count up to 8. \r |
| 526 | // \r |
| 527 | //-----------------------------------------------------------------------------\r |
| 528 | void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r |
| 529 | {\r |
| 530 | // params\r |
| 531 | uint8_t blockNo = arg0;\r |
| 532 | uint8_t keyType = arg1;\r |
| 533 | uint8_t keyCount = arg2;\r |
| 534 | uint64_t ui64Key = 0;\r |
| 535 | \r |
| 536 | // variables\r |
| 537 | int i;\r |
| 538 | byte_t isOK = 0;\r |
| 539 | uint8_t uid[8];\r |
| 540 | uint32_t cuid;\r |
| 541 | struct Crypto1State mpcs = {0, 0};\r |
| 542 | struct Crypto1State *pcs;\r |
| 543 | pcs = &mpcs;\r |
| 544 | \r |
| 545 | // clear debug level\r |
| 546 | int OLD_MF_DBGLEVEL = MF_DBGLEVEL; \r |
| 547 | MF_DBGLEVEL = MF_DBG_NONE;\r |
| 548 | \r |
| 549 | // clear trace\r |
| 550 | iso14a_clear_trace();\r |
| 551 | iso14a_set_tracing(TRUE);\r |
| 552 | \r |
| 553 | iso14443a_setup();\r |
| 554 | \r |
| 555 | LED_A_ON();\r |
| 556 | LED_B_OFF();\r |
| 557 | LED_C_OFF();\r |
| 558 | \r |
| 559 | SpinDelay(300);\r |
| 560 | for (i = 0; i < keyCount; i++) {\r |
| 561 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 562 | SpinDelay(100);\r |
| 563 | FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r |
| 564 | \r |
| 565 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 566 | if (OLD_MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 567 | break;\r |
| 568 | };\r |
| 569 | \r |
| 570 | ui64Key = bytes_to_num(datain + i * 6, 6);\r |
| 571 | if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r |
| 572 | continue;\r |
| 573 | };\r |
| 574 | \r |
| 575 | isOK = 1;\r |
| 576 | break;\r |
| 577 | }\r |
| 578 | \r |
| 579 | // ----------------------------- crypto1 destroy\r |
| 580 | crypto1_destroy(pcs);\r |
| 581 | \r |
| 582 | // add trace trailer\r |
| 583 | memset(uid, 0x44, 4);\r |
| 584 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 585 | \r |
| 586 | // UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r |
| 587 | // if (isOK) memcpy(ack.d.asBytes, datain + i * 6, 6);\r |
| 588 | \r |
| 589 | LED_B_ON();\r |
| 590 | cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);\r |
| 591 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 592 | LED_B_OFF();\r |
| 593 | \r |
| 594 | // Thats it...\r |
| 595 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 596 | LEDsoff();\r |
| 597 | \r |
| 598 | // restore debug level\r |
| 599 | MF_DBGLEVEL = OLD_MF_DBGLEVEL; \r |
| 600 | }\r |
| 601 | \r |
| 602 | //-----------------------------------------------------------------------------\r |
| 603 | // MIFARE commands set debug level\r |
| 604 | // \r |
| 605 | //-----------------------------------------------------------------------------\r |
| 606 | void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 607 | MF_DBGLEVEL = arg0;\r |
| 608 | Dbprintf("Debug level: %d", MF_DBGLEVEL);\r |
| 609 | }\r |
| 610 | \r |
| 611 | //-----------------------------------------------------------------------------\r |
| 612 | // Work with emulator memory\r |
| 613 | // \r |
| 614 | //-----------------------------------------------------------------------------\r |
| 615 | void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 616 | emlClearMem();\r |
| 617 | }\r |
| 618 | \r |
| 619 | void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 620 | emlSetMem(datain, arg0, arg1); // data, block num, blocks count\r |
| 621 | }\r |
| 622 | \r |
| 623 | void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 624 | // UsbCommand ack = {CMD_ACK, {arg0, arg1, 0}};\r |
| 625 | \r |
| 626 | byte_t buf[48];\r |
| 627 | emlGetMem(buf, arg0, arg1); // data, block num, blocks count\r |
| 628 | \r |
| 629 | LED_B_ON();\r |
| 630 | cmd_send(CMD_ACK,arg0,arg1,0,buf,48);\r |
| 631 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 632 | LED_B_OFF();\r |
| 633 | }\r |
| 634 | \r |
| 635 | //-----------------------------------------------------------------------------\r |
| 636 | // Load a card into the emulator memory\r |
| 637 | // \r |
| 638 | //-----------------------------------------------------------------------------\r |
| 639 | void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 640 | int i;\r |
| 641 | uint8_t sectorNo = 0;\r |
| 642 | uint8_t keyType = arg1;\r |
| 643 | uint64_t ui64Key = 0;\r |
| 644 | uint32_t cuid;\r |
| 645 | struct Crypto1State mpcs = {0, 0};\r |
| 646 | struct Crypto1State *pcs;\r |
| 647 | pcs = &mpcs;\r |
| 648 | \r |
| 649 | // variables\r |
| 650 | byte_t dataoutbuf[16];\r |
| 651 | byte_t dataoutbuf2[16];\r |
| 652 | uint8_t uid[8];\r |
| 653 | \r |
| 654 | // clear trace\r |
| 655 | iso14a_clear_trace();\r |
| 656 | iso14a_set_tracing(false);\r |
| 657 | \r |
| 658 | iso14443a_setup();\r |
| 659 | \r |
| 660 | LED_A_ON();\r |
| 661 | LED_B_OFF();\r |
| 662 | LED_C_OFF();\r |
| 663 | \r |
| 664 | while (true) {\r |
| 665 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 666 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 667 | break;\r |
| 668 | };\r |
| 669 | \r |
| 670 | for (i = 0; i < 16; i++) {\r |
| 671 | sectorNo = i;\r |
| 672 | ui64Key = emlGetKey(sectorNo, keyType);\r |
| 673 | \r |
| 674 | if (!i){\r |
| 675 | if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {\r |
| 676 | if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%d]. Auth error", i);\r |
| 677 | break;\r |
| 678 | }\r |
| 679 | } else {\r |
| 680 | if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_NESTED)) {\r |
| 681 | if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%d]. Auth nested error", i);\r |
| 682 | break;\r |
| 683 | }\r |
| 684 | }\r |
| 685 | \r |
| 686 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf)) {\r |
| 687 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 0 error");\r |
| 688 | break;\r |
| 689 | };\r |
| 690 | emlSetMem(dataoutbuf, sectorNo * 4 + 0, 1);\r |
| 691 | \r |
| 692 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf)) {\r |
| 693 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 1 error");\r |
| 694 | break;\r |
| 695 | };\r |
| 696 | emlSetMem(dataoutbuf, sectorNo * 4 + 1, 1);\r |
| 697 | \r |
| 698 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf)) {\r |
| 699 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 2 error");\r |
| 700 | break;\r |
| 701 | };\r |
| 702 | emlSetMem(dataoutbuf, sectorNo * 4 + 2, 1);\r |
| 703 | \r |
| 704 | // get block 3 bytes 6-9\r |
| 705 | if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf)) {\r |
| 706 | if (MF_DBGLEVEL >= 1) Dbprintf("Read block 3 error");\r |
| 707 | break;\r |
| 708 | };\r |
| 709 | emlGetMem(dataoutbuf2, sectorNo * 4 + 3, 1);\r |
| 710 | memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);\r |
| 711 | emlSetMem(dataoutbuf2, sectorNo * 4 + 3, 1);\r |
| 712 | }\r |
| 713 | \r |
| 714 | if(mifare_classic_halt(pcs, cuid)) {\r |
| 715 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 716 | break;\r |
| 717 | };\r |
| 718 | \r |
| 719 | break;\r |
| 720 | } \r |
| 721 | \r |
| 722 | // ----------------------------- crypto1 destroy\r |
| 723 | crypto1_destroy(pcs);\r |
| 724 | \r |
| 725 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 726 | LEDsoff();\r |
| 727 | \r |
| 728 | if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");\r |
| 729 | \r |
| 730 | // add trace trailer\r |
| 731 | memset(uid, 0x44, 4);\r |
| 732 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 733 | }\r |
| 734 | \r |
| 735 | //-----------------------------------------------------------------------------\r |
| 736 | // MIFARE 1k emulator\r |
| 737 | // \r |
| 738 | //-----------------------------------------------------------------------------\r |
| 739 | \r |
| 740 | \r |
| 741 | //-----------------------------------------------------------------------------\r |
| 742 | // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)\r |
| 743 | // \r |
| 744 | //-----------------------------------------------------------------------------\r |
| 745 | void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 746 | \r |
| 747 | // params\r |
| 748 | uint8_t needWipe = arg0;\r |
| 749 | // bit 0 - need get UID\r |
| 750 | // bit 1 - need wupC\r |
| 751 | // bit 2 - need HALT after sequence\r |
| 752 | // bit 3 - need init FPGA and field before sequence\r |
| 753 | // bit 4 - need reset FPGA and LED\r |
| 754 | uint8_t workFlags = arg1;\r |
| 755 | uint8_t blockNo = arg2;\r |
| 756 | \r |
| 757 | // card commands\r |
| 758 | uint8_t wupC1[] = { 0x40 }; \r |
| 759 | uint8_t wupC2[] = { 0x43 }; \r |
| 760 | uint8_t wipeC[] = { 0x41 }; \r |
| 761 | \r |
| 762 | // variables\r |
| 763 | byte_t isOK = 0;\r |
| 764 | uint8_t uid[8];\r |
| 765 | uint8_t d_block[18];\r |
| 766 | uint32_t cuid;\r |
| 767 | \r |
| 768 | memset(uid, 0x00, 8);\r |
| 769 | uint8_t* receivedAnswer = mifare_get_bigbufptr();\r |
| 770 | \r |
| 771 | if (workFlags & 0x08) {\r |
| 772 | // clear trace\r |
| 773 | iso14a_clear_trace();\r |
| 774 | iso14a_set_tracing(TRUE);\r |
| 775 | \r |
| 776 | iso14443a_setup();\r |
| 777 | \r |
| 778 | LED_A_ON();\r |
| 779 | LED_B_OFF();\r |
| 780 | LED_C_OFF();\r |
| 781 | \r |
| 782 | SpinDelay(300);\r |
| 783 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 784 | SpinDelay(100);\r |
| 785 | FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r |
| 786 | }\r |
| 787 | \r |
| 788 | while (true) {\r |
| 789 | // get UID from chip\r |
| 790 | if (workFlags & 0x01) {\r |
| 791 | if(!iso14443a_select_card(uid, NULL, &cuid)) {\r |
| 792 | if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r |
| 793 | break;\r |
| 794 | };\r |
| 795 | \r |
| 796 | if(mifare_classic_halt(NULL, cuid)) {\r |
| 797 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 798 | break;\r |
| 799 | };\r |
| 800 | };\r |
| 801 | \r |
| 802 | // reset chip\r |
| 803 | if (needWipe){\r |
| 804 | ReaderTransmitShort(wupC1);\r |
| 805 | if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r |
| 806 | if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r |
| 807 | break;\r |
| 808 | };\r |
| 809 | \r |
| 810 | ReaderTransmit(wipeC, sizeof(wipeC));\r |
| 811 | if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r |
| 812 | if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r |
| 813 | break;\r |
| 814 | };\r |
| 815 | \r |
| 816 | if(mifare_classic_halt(NULL, cuid)) {\r |
| 817 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 818 | break;\r |
| 819 | };\r |
| 820 | }; \r |
| 821 | \r |
| 822 | // write block\r |
| 823 | if (workFlags & 0x02) {\r |
| 824 | ReaderTransmitShort(wupC1);\r |
| 825 | if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r |
| 826 | if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r |
| 827 | break;\r |
| 828 | };\r |
| 829 | \r |
| 830 | ReaderTransmit(wupC2, sizeof(wupC2));\r |
| 831 | if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r |
| 832 | if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r |
| 833 | break;\r |
| 834 | };\r |
| 835 | }\r |
| 836 | \r |
| 837 | if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer) != 1) || (receivedAnswer[0] != 0x0a)) {\r |
| 838 | if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r |
| 839 | break;\r |
| 840 | };\r |
| 841 | \r |
| 842 | memcpy(d_block, datain, 16);\r |
| 843 | AppendCrc14443a(d_block, 16);\r |
| 844 | \r |
| 845 | ReaderTransmit(d_block, sizeof(d_block));\r |
| 846 | if ((ReaderReceive(receivedAnswer) != 1) || (receivedAnswer[0] != 0x0a)) {\r |
| 847 | if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r |
| 848 | break;\r |
| 849 | }; \r |
| 850 | \r |
| 851 | if (workFlags & 0x04) {\r |
| 852 | if (mifare_classic_halt(NULL, cuid)) {\r |
| 853 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 854 | break;\r |
| 855 | };\r |
| 856 | }\r |
| 857 | \r |
| 858 | isOK = 1;\r |
| 859 | break;\r |
| 860 | }\r |
| 861 | \r |
| 862 | // UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r |
| 863 | // if (isOK) memcpy(ack.d.asBytes, uid, 4);\r |
| 864 | \r |
| 865 | // add trace trailer\r |
| 866 | memset(uid, 0x44, 4);\r |
| 867 | LogTrace(uid, 4, 0, 0, TRUE);\r |
| 868 | \r |
| 869 | LED_B_ON();\r |
| 870 | cmd_send(CMD_ACK,isOK,0,0,uid,4);\r |
| 871 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 872 | LED_B_OFF();\r |
| 873 | \r |
| 874 | if ((workFlags & 0x10) || (!isOK)) {\r |
| 875 | // Thats it...\r |
| 876 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 877 | LEDsoff();\r |
| 878 | }\r |
| 879 | }\r |
| 880 | \r |
| 881 | void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r |
| 882 | \r |
| 883 | // params\r |
| 884 | // bit 1 - need wupC\r |
| 885 | // bit 2 - need HALT after sequence\r |
| 886 | // bit 3 - need init FPGA and field before sequence\r |
| 887 | // bit 4 - need reset FPGA and LED\r |
| 888 | uint8_t workFlags = arg0;\r |
| 889 | uint8_t blockNo = arg2;\r |
| 890 | \r |
| 891 | // card commands\r |
| 892 | uint8_t wupC1[] = { 0x40 }; \r |
| 893 | uint8_t wupC2[] = { 0x43 }; \r |
| 894 | \r |
| 895 | // variables\r |
| 896 | byte_t isOK = 0;\r |
| 897 | uint8_t data[18];\r |
| 898 | uint32_t cuid = 0;\r |
| 899 | \r |
| 900 | memset(data, 0x00, 18);\r |
| 901 | uint8_t* receivedAnswer = mifare_get_bigbufptr();\r |
| 902 | \r |
| 903 | if (workFlags & 0x08) {\r |
| 904 | // clear trace\r |
| 905 | iso14a_clear_trace();\r |
| 906 | iso14a_set_tracing(TRUE);\r |
| 907 | \r |
| 908 | iso14443a_setup();\r |
| 909 | \r |
| 910 | LED_A_ON();\r |
| 911 | LED_B_OFF();\r |
| 912 | LED_C_OFF();\r |
| 913 | \r |
| 914 | SpinDelay(300);\r |
| 915 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 916 | SpinDelay(100);\r |
| 917 | FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r |
| 918 | }\r |
| 919 | \r |
| 920 | while (true) {\r |
| 921 | if (workFlags & 0x02) {\r |
| 922 | ReaderTransmitShort(wupC1);\r |
| 923 | if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r |
| 924 | if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r |
| 925 | break;\r |
| 926 | };\r |
| 927 | \r |
| 928 | ReaderTransmit(wupC2, sizeof(wupC2));\r |
| 929 | if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r |
| 930 | if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r |
| 931 | break;\r |
| 932 | };\r |
| 933 | }\r |
| 934 | \r |
| 935 | // read block\r |
| 936 | if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer) != 18)) {\r |
| 937 | if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r |
| 938 | break;\r |
| 939 | };\r |
| 940 | memcpy(data, receivedAnswer, 18);\r |
| 941 | \r |
| 942 | if (workFlags & 0x04) {\r |
| 943 | if (mifare_classic_halt(NULL, cuid)) {\r |
| 944 | if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r |
| 945 | break;\r |
| 946 | };\r |
| 947 | }\r |
| 948 | \r |
| 949 | isOK = 1;\r |
| 950 | break;\r |
| 951 | }\r |
| 952 | \r |
| 953 | // UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r |
| 954 | // if (isOK) memcpy(ack.d.asBytes, data, 18);\r |
| 955 | \r |
| 956 | // add trace trailer\r |
| 957 | memset(data, 0x44, 4);\r |
| 958 | LogTrace(data, 4, 0, 0, TRUE);\r |
| 959 | \r |
| 960 | LED_B_ON();\r |
| 961 | cmd_send(CMD_ACK,isOK,0,0,data,18);\r |
| 962 | // UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r |
| 963 | LED_B_OFF();\r |
| 964 | \r |
| 965 | if ((workFlags & 0x10) || (!isOK)) {\r |
| 966 | // Thats it...\r |
| 967 | FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r |
| 968 | LEDsoff();\r |
| 969 | }\r |
| 970 | }\r |
| 971 | \r |