]> cvs.zerfleddert.de Git - proxmark3-svn/blame - armsrc/mifarecmd.c
Merge pull request #356 from pwpiwi/low_frequencies
[proxmark3-svn] / armsrc / mifarecmd.c
CommitLineData
8556b852 1//-----------------------------------------------------------------------------\r
b62a5a84 2// Merlok - June 2011, 2012\r
8556b852
M
3// Gerhard de Koning Gans - May 2008\r
4// Hagen Fritsch - June 2010\r
3fe4ff4f 5// Midnitesnake - Dec 2013\r
6// Andy Davies - Apr 2014\r
7// Iceman - May 2014\r
8556b852
M
8//\r
9// This code is licensed to you under the terms of the GNU GPL, version 2 or,\r
10// at your option, any later version. See the LICENSE.txt file for the text of\r
11// the license.\r
12//-----------------------------------------------------------------------------\r
13// Routines to support ISO 14443 type A.\r
14//-----------------------------------------------------------------------------\r
15\r
16#include "mifarecmd.h"\r
de77d4ac 17\r
8556b852 18#include "apps.h"\r
787b5bd8 19#include "util.h"\r
1f065e1d 20#include "parity.h"\r
a631936e 21#include "crc.h"\r
22\r
de77d4ac 23#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)\r
7906cb41
F
24#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication\r
25\r
de77d4ac 26\r
f168b263 27// the block number for the ISO14443-4 PCB\r
de77d4ac 28static uint8_t pcb_blocknum = 0;\r
f168b263 29// Deselect card by sending a s-block. the crc is precalced for speed\r
30static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};\r
31\r
8556b852 32//-----------------------------------------------------------------------------\r
7906cb41 33// Select, Authenticate, Read a MIFARE tag.\r
8556b852
M
34// read block\r
35//-----------------------------------------------------------------------------\r
36void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
37{\r
38 // params\r
39 uint8_t blockNo = arg0;\r
40 uint8_t keyType = arg1;\r
41 uint64_t ui64Key = 0;\r
42 ui64Key = bytes_to_num(datain, 6);\r
7906cb41 43\r
8556b852
M
44 // variables\r
45 byte_t isOK = 0;\r
46 byte_t dataoutbuf[16];\r
1c611bbd 47 uint8_t uid[10];\r
8556b852
M
48 uint32_t cuid;\r
49 struct Crypto1State mpcs = {0, 0};\r
50 struct Crypto1State *pcs;\r
51 pcs = &mpcs;\r
52\r
7bc95e2e 53 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
8556b852 54\r
09ffd16e 55 clear_trace();\r
56\r
8556b852
M
57 LED_A_ON();\r
58 LED_B_OFF();\r
59 LED_C_OFF();\r
60\r
61 while (true) {\r
de77d4ac 62 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
baeaf579 63 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
8556b852
M
64 break;\r
65 };\r
66\r
67 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
baeaf579 68 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
8556b852
M
69 break;\r
70 };\r
7906cb41 71\r
8556b852 72 if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {\r
baeaf579 73 if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r
8556b852
M
74 break;\r
75 };\r
76\r
77 if(mifare_classic_halt(pcs, cuid)) {\r
baeaf579 78 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
8556b852
M
79 break;\r
80 };\r
7906cb41 81\r
8556b852
M
82 isOK = 1;\r
83 break;\r
84 }\r
7906cb41 85\r
8556b852
M
86 // ----------------------------- crypto1 destroy\r
87 crypto1_destroy(pcs);\r
7906cb41 88\r
8556b852
M
89 if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
90\r
8556b852 91 LED_B_ON();\r
baeaf579 92 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);\r
8556b852
M
93 LED_B_OFF();\r
94\r
a631936e 95 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
96 LEDsoff();\r
97}\r
98\r
8258f409 99void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){\r
a631936e 100\r
8258f409 101 bool turnOffField = (arg0 == 1);\r
a631936e 102\r
f168b263 103 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
09ffd16e 104\r
a631936e 105 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
106\r
09ffd16e 107 clear_trace();\r
108\r
de77d4ac 109 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {\r
f168b263 110 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
111 OnError(0);\r
a631936e 112 return;\r
113 };\r
7906cb41 114\r
9d87eb66 115 if(!mifare_ultra_auth(keybytes)){\r
8258f409 116 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed");\r
f168b263 117 OnError(1);\r
a631936e 118 return;\r
119 }\r
120\r
8258f409 121 if (turnOffField) {\r
cceabb79 122 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
123 LEDsoff();\r
124 }\r
9d87eb66 125 cmd_send(CMD_ACK,1,0,0,0,0);\r
7cc204bf 126}\r
127\r
75377d29 128// Arg0 = BlockNo,\r
129// Arg1 = UsePwd bool\r
130// datain = PWD bytes,\r
f168b263 131void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
7cc204bf 132{\r
7cc204bf 133 uint8_t blockNo = arg0;\r
787b5bd8 134 byte_t dataout[16] = {0x00};\r
8258f409 135 bool useKey = (arg1 == 1); //UL_C\r
136 bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
f168b263 137\r
75377d29 138 LEDsoff();\r
139 LED_A_ON();\r
787b5bd8 140 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
f168b263 141\r
09ffd16e 142 clear_trace();\r
143\r
de77d4ac 144 int len = iso14443a_select_card(NULL, NULL, NULL, true, 0);\r
787b5bd8 145 if(!len) {\r
f168b263 146 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);\r
147 OnError(1);\r
787b5bd8 148 return;\r
f168b263 149 }\r
150\r
8258f409 151 // UL-C authentication\r
152 if ( useKey ) {\r
153 uint8_t key[16] = {0x00};\r
154 memcpy(key, datain, sizeof(key) );\r
f168b263 155\r
9d87eb66 156 if ( !mifare_ultra_auth(key) ) {\r
f168b263 157 OnError(1);\r
158 return;\r
159 }\r
8258f409 160 }\r
f168b263 161\r
8258f409 162 // UL-EV1 / NTAG authentication\r
163 if ( usePwd ) {\r
164 uint8_t pwd[4] = {0x00};\r
165 memcpy(pwd, datain, 4);\r
166 uint8_t pack[4] = {0,0,0,0};\r
9d87eb66 167 if (!mifare_ul_ev1_auth(pwd, pack)) {\r
f168b263 168 OnError(1);\r
169 return;\r
170 }\r
7906cb41 171 }\r
f168b263 172\r
f168b263 173 if( mifare_ultra_readblock(blockNo, dataout) ) {\r
174 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");\r
175 OnError(2);\r
787b5bd8 176 return;\r
f168b263 177 }\r
8258f409 178\r
f168b263 179 if( mifare_ultra_halt() ) {\r
180 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
181 OnError(3);\r
787b5bd8 182 return;\r
f168b263 183 }\r
8258f409 184\r
185 cmd_send(CMD_ACK,1,0,0,dataout,16);\r
7cc204bf 186 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
187 LEDsoff();\r
188}\r
b3125340 189\r
7cc204bf 190//-----------------------------------------------------------------------------\r
7906cb41 191// Select, Authenticate, Read a MIFARE tag.\r
baeaf579 192// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)\r
8556b852
M
193//-----------------------------------------------------------------------------\r
194void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
195{\r
196 // params\r
197 uint8_t sectorNo = arg0;\r
198 uint8_t keyType = arg1;\r
199 uint64_t ui64Key = 0;\r
200 ui64Key = bytes_to_num(datain, 6);\r
7906cb41 201\r
8556b852 202 // variables\r
3fe4ff4f 203 byte_t isOK = 0;\r
baeaf579 204 byte_t dataoutbuf[16 * 16];\r
1c611bbd 205 uint8_t uid[10];\r
8556b852
M
206 uint32_t cuid;\r
207 struct Crypto1State mpcs = {0, 0};\r
208 struct Crypto1State *pcs;\r
209 pcs = &mpcs;\r
210\r
7bc95e2e 211 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
8556b852 212\r
09ffd16e 213 clear_trace();\r
214\r
8556b852
M
215 LED_A_ON();\r
216 LED_B_OFF();\r
217 LED_C_OFF();\r
218\r
baeaf579 219 isOK = 1;\r
de77d4ac 220 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
baeaf579 221 isOK = 0;\r
8556b852 222 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
baeaf579 223 }\r
8556b852 224\r
7906cb41 225\r
baeaf579 226 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
227 isOK = 0;\r
8556b852 228 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
baeaf579 229 }\r
7906cb41 230\r
baeaf579 231 for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
232 if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {\r
233 isOK = 0;\r
234 if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);\r
8556b852 235 break;\r
baeaf579 236 }\r
237 }\r
7906cb41 238\r
baeaf579 239 if(mifare_classic_halt(pcs, cuid)) {\r
8556b852 240 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
8556b852 241 }\r
baeaf579 242\r
8556b852
M
243 // ----------------------------- crypto1 destroy\r
244 crypto1_destroy(pcs);\r
7906cb41 245\r
8556b852
M
246 if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");\r
247\r
8556b852 248 LED_B_ON();\r
baeaf579 249 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));\r
6e82300d 250 LED_B_OFF();\r
8556b852
M
251\r
252 // Thats it...\r
253 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
254 LEDsoff();\r
7cc204bf 255}\r
256\r
79d7bcbb 257// arg0 = blockNo (start)\r
258// arg1 = Pages (number of blocks)\r
259// arg2 = useKey\r
260// datain = KEY bytes\r
75377d29 261void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
7cc204bf 262{\r
09ffd16e 263 LEDsoff();\r
264 LED_A_ON();\r
265 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
266\r
d7acc640 267 // free eventually allocated BigBuf memory\r
268 BigBuf_free();\r
d7acc640 269 clear_trace();\r
270\r
f168b263 271 // params\r
75377d29 272 uint8_t blockNo = arg0;\r
273 uint16_t blocks = arg1;\r
cceabb79 274 bool useKey = (arg2 == 1); //UL_C\r
275 bool usePwd = (arg2 == 2); //UL_EV1/NTAG\r
9d87eb66 276 uint32_t countblocks = 0;\r
d7acc640 277 uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE);\r
278 if (dataout == NULL){\r
279 Dbprintf("out of memory");\r
280 OnError(1);\r
281 return;\r
282 }\r
7cc204bf 283\r
de77d4ac 284 int len = iso14443a_select_card(NULL, NULL, NULL, true, 0);\r
787b5bd8 285 if (!len) {\r
f168b263 286 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);\r
287 OnError(1);\r
787b5bd8 288 return;\r
289 }\r
75377d29 290\r
8258f409 291 // UL-C authentication\r
75377d29 292 if ( useKey ) {\r
293 uint8_t key[16] = {0x00};\r
8258f409 294 memcpy(key, datain, sizeof(key) );\r
75377d29 295\r
9d87eb66 296 if ( !mifare_ultra_auth(key) ) {\r
75377d29 297 OnError(1);\r
298 return;\r
299 }\r
75377d29 300 }\r
301\r
8258f409 302 // UL-EV1 / NTAG authentication\r
303 if (usePwd) {\r
304 uint8_t pwd[4] = {0x00};\r
305 memcpy(pwd, datain, sizeof(pwd));\r
cceabb79 306 uint8_t pack[4] = {0,0,0,0};\r
307\r
9d87eb66 308 if (!mifare_ul_ev1_auth(pwd, pack)){\r
cceabb79 309 OnError(1);\r
7906cb41 310 return;\r
cceabb79 311 }\r
312 }\r
313\r
75377d29 314 for (int i = 0; i < blocks; i++){\r
22342f6d 315 if ((i*4) + 4 >= CARD_MEMORY_SIZE) {\r
9d87eb66 316 Dbprintf("Data exceeds buffer!!");\r
317 break;\r
318 }\r
7906cb41 319\r
9d87eb66 320 len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
75377d29 321\r
787b5bd8 322 if (len) {\r
f168b263 323 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);\r
9d87eb66 324 // if no blocks read - error out\r
325 if (i==0){\r
326 OnError(2);\r
327 return;\r
328 } else {\r
329 //stop at last successful read block and return what we got\r
330 break;\r
331 }\r
787b5bd8 332 } else {\r
75377d29 333 countblocks++;\r
787b5bd8 334 }\r
335 }\r
75377d29 336\r
f168b263 337 len = mifare_ultra_halt();\r
787b5bd8 338 if (len) {\r
f168b263 339 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
340 OnError(3);\r
787b5bd8 341 return;\r
342 }\r
7cc204bf 343\r
75377d29 344 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);\r
345\r
9d87eb66 346 countblocks *= 4;\r
22342f6d 347\r
0ce03d9a 348 cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);\r
31d1caa5
MHS
349 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
350 LEDsoff();\r
22342f6d 351 BigBuf_free();\r
7cc204bf 352}\r
353\r
7cc204bf 354//-----------------------------------------------------------------------------\r
7906cb41 355// Select, Authenticate, Write a MIFARE tag.\r
7cc204bf 356// read block\r
8556b852
M
357//-----------------------------------------------------------------------------\r
358void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
359{\r
360 // params\r
361 uint8_t blockNo = arg0;\r
362 uint8_t keyType = arg1;\r
363 uint64_t ui64Key = 0;\r
364 byte_t blockdata[16];\r
365\r
366 ui64Key = bytes_to_num(datain, 6);\r
367 memcpy(blockdata, datain + 10, 16);\r
7906cb41 368\r
8556b852
M
369 // variables\r
370 byte_t isOK = 0;\r
1c611bbd 371 uint8_t uid[10];\r
8556b852
M
372 uint32_t cuid;\r
373 struct Crypto1State mpcs = {0, 0};\r
374 struct Crypto1State *pcs;\r
375 pcs = &mpcs;\r
376\r
7bc95e2e 377 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
8556b852 378\r
09ffd16e 379 clear_trace();\r
380\r
8556b852
M
381 LED_A_ON();\r
382 LED_B_OFF();\r
383 LED_C_OFF();\r
384\r
385 while (true) {\r
de77d4ac 386 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
8556b852
M
387 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
388 break;\r
389 };\r
390\r
391 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
392 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
393 break;\r
394 };\r
7906cb41 395\r
8556b852
M
396 if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {\r
397 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
398 break;\r
399 };\r
400\r
401 if(mifare_classic_halt(pcs, cuid)) {\r
402 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
403 break;\r
404 };\r
7906cb41 405\r
8556b852
M
406 isOK = 1;\r
407 break;\r
408 }\r
7906cb41 409\r
8556b852
M
410 // ----------------------------- crypto1 destroy\r
411 crypto1_destroy(pcs);\r
7906cb41 412\r
8556b852
M
413 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
414\r
8556b852 415 LED_B_ON();\r
9492e0b0 416 cmd_send(CMD_ACK,isOK,0,0,0,0);\r
6e82300d 417 LED_B_OFF();\r
8556b852
M
418\r
419\r
420 // Thats it...\r
421 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
422 LEDsoff();\r
7cc204bf 423}\r
424\r
7906cb41 425/* // Command not needed but left for future testing\r
4973f23d 426void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)\r
7cc204bf 427{\r
f168b263 428 uint8_t blockNo = arg0;\r
787b5bd8 429 byte_t blockdata[16] = {0x00};\r
7cc204bf 430\r
f168b263 431 memcpy(blockdata, datain, 16);\r
432\r
787b5bd8 433 uint8_t uid[10] = {0x00};\r
7cc204bf 434\r
f168b263 435 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
7cc204bf 436\r
f168b263 437 clear_trace();\r
438 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
439\r
de77d4ac 440 if(!iso14443a_select_card(uid, NULL, NULL, true, 0)) {\r
f168b263 441 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
442 OnError(0);\r
443 return;\r
444 };\r
445\r
4973f23d 446 if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {\r
f168b263 447 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
448 OnError(0);\r
449 return; };\r
450\r
451 if(mifare_ultra_halt()) {\r
452 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
453 OnError(0);\r
454 return;\r
455 };\r
456\r
457 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
458\r
459 cmd_send(CMD_ACK,1,0,0,0,0);\r
460 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
461 LEDsoff();\r
7cc204bf 462}\r
4973f23d 463*/\r
7cc204bf 464\r
79d7bcbb 465// Arg0 : Block to write to.\r
466// Arg1 : 0 = use no authentication.\r
467// 1 = use 0x1A authentication.\r
468// 2 = use 0x1B authentication.\r
469// datain : 4 first bytes is data to be written.\r
470// : 4/16 next bytes is authentication key.\r
4973f23d 471void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
7cc204bf 472{\r
baeaf579 473 uint8_t blockNo = arg0;\r
79d7bcbb 474 bool useKey = (arg1 == 1); //UL_C\r
475 bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
787b5bd8 476 byte_t blockdata[4] = {0x00};\r
7cc204bf 477\r
8258f409 478 memcpy(blockdata, datain,4);\r
7906cb41 479\r
8258f409 480 LEDsoff();\r
481 LED_A_ON();\r
f168b263 482 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
483\r
09ffd16e 484 clear_trace();\r
485\r
de77d4ac 486 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {\r
f168b263 487 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
488 OnError(0);\r
489 return;\r
490 };\r
7cc204bf 491\r
79d7bcbb 492 // UL-C authentication\r
493 if ( useKey ) {\r
494 uint8_t key[16] = {0x00};\r
495 memcpy(key, datain+4, sizeof(key) );\r
496\r
497 if ( !mifare_ultra_auth(key) ) {\r
498 OnError(1);\r
499 return;\r
500 }\r
501 }\r
7906cb41 502\r
79d7bcbb 503 // UL-EV1 / NTAG authentication\r
504 if (usePwd) {\r
505 uint8_t pwd[4] = {0x00};\r
506 memcpy(pwd, datain+4, 4);\r
507 uint8_t pack[4] = {0,0,0,0};\r
508 if (!mifare_ul_ev1_auth(pwd, pack)) {\r
509 OnError(1);\r
510 return;\r
511 }\r
512 }\r
513\r
4973f23d 514 if(mifare_ultra_writeblock(blockNo, blockdata)) {\r
f168b263 515 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
516 OnError(0);\r
517 return;\r
518 };\r
519\r
520 if(mifare_ultra_halt()) {\r
521 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
522 OnError(0);\r
523 return;\r
524 };\r
525\r
526 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
527\r
528 cmd_send(CMD_ACK,1,0,0,0,0);\r
529 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
530 LEDsoff();\r
531}\r
532\r
533void MifareUSetPwd(uint8_t arg0, uint8_t *datain){\r
7906cb41 534\r
f168b263 535 uint8_t pwd[16] = {0x00};\r
536 byte_t blockdata[4] = {0x00};\r
7906cb41 537\r
f168b263 538 memcpy(pwd, datain, 16);\r
7906cb41 539\r
f168b263 540 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
baeaf579 541 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
7cc204bf 542\r
09ffd16e 543 clear_trace();\r
544\r
de77d4ac 545 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {\r
f168b263 546 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
547 OnError(0);\r
548 return;\r
549 };\r
7cc204bf 550\r
f168b263 551 blockdata[0] = pwd[7];\r
552 blockdata[1] = pwd[6];\r
553 blockdata[2] = pwd[5];\r
554 blockdata[3] = pwd[4];\r
4973f23d 555 if(mifare_ultra_writeblock( 44, blockdata)) {\r
f168b263 556 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
557 OnError(44);\r
558 return;\r
559 };\r
7cc204bf 560\r
f168b263 561 blockdata[0] = pwd[3];\r
562 blockdata[1] = pwd[2];\r
563 blockdata[2] = pwd[1];\r
564 blockdata[3] = pwd[0];\r
4973f23d 565 if(mifare_ultra_writeblock( 45, blockdata)) {\r
f168b263 566 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
567 OnError(45);\r
568 return;\r
569 };\r
7cc204bf 570\r
f168b263 571 blockdata[0] = pwd[15];\r
572 blockdata[1] = pwd[14];\r
573 blockdata[2] = pwd[13];\r
574 blockdata[3] = pwd[12];\r
4973f23d 575 if(mifare_ultra_writeblock( 46, blockdata)) {\r
f168b263 576 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
577 OnError(46);\r
578 return;\r
579 };\r
7cc204bf 580\r
f168b263 581 blockdata[0] = pwd[11];\r
582 blockdata[1] = pwd[10];\r
583 blockdata[2] = pwd[9];\r
584 blockdata[3] = pwd[8];\r
4973f23d 585 if(mifare_ultra_writeblock( 47, blockdata)) {\r
f168b263 586 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
587 OnError(47);\r
588 return;\r
7906cb41 589 };\r
7cc204bf 590\r
f168b263 591 if(mifare_ultra_halt()) {\r
592 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
593 OnError(0);\r
594 return;\r
595 };\r
7cc204bf 596\r
f168b263 597 cmd_send(CMD_ACK,1,0,0,0,0);\r
baeaf579 598 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
599 LEDsoff();\r
7cc204bf 600}\r
601\r
602// Return 1 if the nonce is invalid else return 0\r
6a1f2d82 603int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {\r
1f065e1d 604 return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \\r
605 (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \\r
606 (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;\r
8556b852
M
607}\r
608\r
9492e0b0 609\r
de77d4ac 610//-----------------------------------------------------------------------------\r
611// acquire encrypted nonces in order to perform the attack described in\r
612// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened\r
7906cb41 613// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on\r
de77d4ac 614// Computer and Communications Security, 2015\r
615//-----------------------------------------------------------------------------\r
616void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain)\r
617{\r
618 uint64_t ui64Key = 0;\r
619 uint8_t uid[10];\r
620 uint32_t cuid;\r
621 uint8_t cascade_levels = 0;\r
622 struct Crypto1State mpcs = {0, 0};\r
623 struct Crypto1State *pcs;\r
624 pcs = &mpcs;\r
625 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
626 int16_t isOK = 0;\r
627 uint8_t par_enc[1];\r
628 uint8_t nt_par_enc = 0;\r
629 uint8_t buf[USB_CMD_DATA_SIZE];\r
630 uint32_t timeout;\r
7906cb41 631\r
de77d4ac 632 uint8_t blockNo = arg0 & 0xff;\r
633 uint8_t keyType = (arg0 >> 8) & 0xff;\r
634 uint8_t targetBlockNo = arg1 & 0xff;\r
635 uint8_t targetKeyType = (arg1 >> 8) & 0xff;\r
636 ui64Key = bytes_to_num(datain, 6);\r
637 bool initialize = flags & 0x0001;\r
638 bool slow = flags & 0x0002;\r
639 bool field_off = flags & 0x0004;\r
7906cb41 640\r
de77d4ac 641 LED_A_ON();\r
642 LED_C_OFF();\r
643\r
644 if (initialize) {\r
645 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
646 clear_trace();\r
647 set_tracing(true);\r
648 }\r
7906cb41 649\r
de77d4ac 650 LED_C_ON();\r
7906cb41 651\r
de77d4ac 652 uint16_t num_nonces = 0;\r
653 bool have_uid = false;\r
654 for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) {\r
655\r
656 // Test if the action was cancelled\r
657 if(BUTTON_PRESS()) {\r
658 isOK = 2;\r
659 field_off = true;\r
660 break;\r
661 }\r
662\r
663 if (!have_uid) { // need a full select cycle to get the uid first\r
7906cb41 664 iso14a_card_select_t card_info;\r
de77d4ac 665 if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) {\r
666 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");\r
667 continue;\r
668 }\r
669 switch (card_info.uidlen) {\r
670 case 4 : cascade_levels = 1; break;\r
671 case 7 : cascade_levels = 2; break;\r
672 case 10: cascade_levels = 3; break;\r
673 default: break;\r
674 }\r
7906cb41 675 have_uid = true;\r
de77d4ac 676 } else { // no need for anticollision. We can directly select the card\r
677 if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) {\r
678 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");\r
679 continue;\r
680 }\r
681 }\r
7906cb41 682\r
de77d4ac 683 if (slow) {\r
684 timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME;\r
685 while(GetCountSspClk() < timeout);\r
686 }\r
687\r
688 uint32_t nt1;\r
689 if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {\r
690 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");\r
691 continue;\r
692 }\r
693\r
694 // nested authentication\r
695 uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);\r
696 if (len != 4) {\r
697 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);\r
698 continue;\r
699 }\r
7906cb41 700\r
de77d4ac 701 // send a dummy byte as reader response in order to trigger the cards authentication timeout\r
702 uint8_t dummy_answer = 0;\r
703 ReaderTransmit(&dummy_answer, 1, NULL);\r
704 timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;\r
7906cb41 705\r
de77d4ac 706 num_nonces++;\r
707 if (num_nonces % 2) {\r
708 memcpy(buf+i, receivedAnswer, 4);\r
709 nt_par_enc = par_enc[0] & 0xf0;\r
710 } else {\r
711 nt_par_enc |= par_enc[0] >> 4;\r
712 memcpy(buf+i+4, receivedAnswer, 4);\r
713 memcpy(buf+i+8, &nt_par_enc, 1);\r
714 i += 9;\r
715 }\r
716\r
717 // wait for the card to become ready again\r
718 while(GetCountSspClk() < timeout);\r
7906cb41 719\r
de77d4ac 720 }\r
721\r
722 LED_C_OFF();\r
7906cb41 723\r
de77d4ac 724 crypto1_destroy(pcs);\r
7906cb41 725\r
de77d4ac 726 LED_B_ON();\r
727 cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));\r
728 LED_B_OFF();\r
729\r
730 if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished");\r
731\r
732 if (field_off) {\r
733 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
734 LEDsoff();\r
735 }\r
736}\r
737\r
738\r
8556b852 739//-----------------------------------------------------------------------------\r
7906cb41
F
740// MIFARE nested authentication.\r
741//\r
8556b852 742//-----------------------------------------------------------------------------\r
9492e0b0 743void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain)\r
8556b852
M
744{\r
745 // params\r
9492e0b0 746 uint8_t blockNo = arg0 & 0xff;\r
747 uint8_t keyType = (arg0 >> 8) & 0xff;\r
748 uint8_t targetBlockNo = arg1 & 0xff;\r
749 uint8_t targetKeyType = (arg1 >> 8) & 0xff;\r
8556b852
M
750 uint64_t ui64Key = 0;\r
751\r
752 ui64Key = bytes_to_num(datain, 6);\r
7906cb41 753\r
8556b852 754 // variables\r
9492e0b0 755 uint16_t rtr, i, j, len;\r
756 uint16_t davg;\r
757 static uint16_t dmin, dmax;\r
1c611bbd 758 uint8_t uid[10];\r
6a1f2d82 759 uint32_t cuid, nt1, nt2, nttmp, nttest, ks1;\r
760 uint8_t par[1];\r
9492e0b0 761 uint32_t target_nt[2], target_ks[2];\r
7906cb41 762\r
8556b852 763 uint8_t par_array[4];\r
9492e0b0 764 uint16_t ncount = 0;\r
8556b852
M
765 struct Crypto1State mpcs = {0, 0};\r
766 struct Crypto1State *pcs;\r
767 pcs = &mpcs;\r
f71f4deb 768 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
8556b852 769\r
9492e0b0 770 uint32_t auth1_time, auth2_time;\r
771 static uint16_t delta_time;\r
772\r
09ffd16e 773 LED_A_ON();\r
774 LED_C_OFF();\r
775 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
776\r
f71f4deb 777 // free eventually allocated BigBuf memory\r
778 BigBuf_free();\r
09ffd16e 779\r
5330f532 780 if (calibrate) clear_trace();\r
781 set_tracing(true);\r
7906cb41 782\r
9492e0b0 783 // statistics on nonce distance\r
dc8ba239 784 int16_t isOK = 0;\r
785 #define NESTED_MAX_TRIES 12\r
786 uint16_t unsuccessfull_tries = 0;\r
9492e0b0 787 if (calibrate) { // for first call only. Otherwise reuse previous calibration\r
788 LED_B_ON();\r
3fe4ff4f 789 WDT_HIT();\r
8556b852 790\r
9492e0b0 791 davg = dmax = 0;\r
792 dmin = 2000;\r
793 delta_time = 0;\r
7906cb41 794\r
9492e0b0 795 for (rtr = 0; rtr < 17; rtr++) {\r
8556b852 796\r
dc8ba239 797 // Test if the action was cancelled\r
798 if(BUTTON_PRESS()) {\r
799 isOK = -2;\r
800 break;\r
801 }\r
802\r
9492e0b0 803 // prepare next select. No need to power down the card.\r
804 if(mifare_classic_halt(pcs, cuid)) {\r
805 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");\r
806 rtr--;\r
807 continue;\r
808 }\r
809\r
de77d4ac 810 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
9492e0b0 811 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
812 rtr--;\r
813 continue;\r
814 };\r
815\r
816 auth1_time = 0;\r
817 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {\r
818 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");\r
819 rtr--;\r
820 continue;\r
821 };\r
822\r
823 if (delta_time) {\r
824 auth2_time = auth1_time + delta_time;\r
825 } else {\r
826 auth2_time = 0;\r
827 }\r
828 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) {\r
829 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error");\r
830 rtr--;\r
831 continue;\r
832 };\r
833\r
b19bd5d6 834 nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160\r
835 for (i = 101; i < 1200; i++) {\r
9492e0b0 836 nttmp = prng_successor(nttmp, 1);\r
837 if (nttmp == nt2) break;\r
838 }\r
839\r
840 if (i != 1200) {\r
841 if (rtr != 0) {\r
842 davg += i;\r
843 dmin = MIN(dmin, i);\r
844 dmax = MAX(dmax, i);\r
845 }\r
846 else {\r
847 delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing\r
848 }\r
849 if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i);\r
dc8ba239 850 } else {\r
851 unsuccessfull_tries++;\r
852 if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)\r
853 isOK = -3;\r
854 }\r
9492e0b0 855 }\r
8556b852 856 }\r
8556b852 857\r
9492e0b0 858 davg = (davg + (rtr - 1)/2) / (rtr - 1);\r
7906cb41 859\r
dc8ba239 860 if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);\r
8556b852 861\r
9492e0b0 862 dmin = davg - 2;\r
863 dmax = davg + 2;\r
7906cb41 864\r
9492e0b0 865 LED_B_OFF();\r
7906cb41 866\r
9492e0b0 867 }\r
7906cb41
F
868 // -------------------------------------------------------------------------------------------------\r
869\r
8556b852
M
870 LED_C_ON();\r
871\r
872 // get crypted nonces for target sector\r
dc8ba239 873 for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces\r
8556b852 874\r
9492e0b0 875 target_nt[i] = 0;\r
876 while(target_nt[i] == 0) { // continue until we have an unambiguous nonce\r
7906cb41 877\r
9492e0b0 878 // prepare next select. No need to power down the card.\r
879 if(mifare_classic_halt(pcs, cuid)) {\r
880 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");\r
881 continue;\r
882 }\r
8556b852 883\r
de77d4ac 884 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
9492e0b0 885 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
886 continue;\r
887 };\r
7906cb41 888\r
9492e0b0 889 auth1_time = 0;\r
890 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {\r
891 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");\r
892 continue;\r
893 };\r
8556b852 894\r
9492e0b0 895 // nested authentication\r
896 auth2_time = auth1_time + delta_time;\r
e35031d2 897 len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);\r
9492e0b0 898 if (len != 4) {\r
899 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);\r
900 continue;\r
901 };\r
7906cb41
F
902\r
903 nt2 = bytes_to_num(receivedAnswer, 4);\r
6a1f2d82 904 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]);\r
7906cb41 905\r
9492e0b0 906 // Parity validity check\r
907 for (j = 0; j < 4; j++) {\r
1f065e1d 908 par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));\r
9492e0b0 909 }\r
7906cb41 910\r
9492e0b0 911 ncount = 0;\r
912 nttest = prng_successor(nt1, dmin - 1);\r
913 for (j = dmin; j < dmax + 1; j++) {\r
914 nttest = prng_successor(nttest, 1);\r
915 ks1 = nt2 ^ nttest;\r
916\r
917 if (valid_nonce(nttest, nt2, ks1, par_array)){\r
918 if (ncount > 0) { // we are only interested in disambiguous nonces, try again\r
919 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j);\r
920 target_nt[i] = 0;\r
921 break;\r
922 }\r
923 target_nt[i] = nttest;\r
924 target_ks[i] = ks1;\r
925 ncount++;\r
926 if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces\r
927 target_nt[i] = 0;\r
928 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j);\r
8556b852
M
929 break;\r
930 }\r
9492e0b0 931 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j);\r
8556b852 932 }\r
8556b852 933 }\r
9492e0b0 934 if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1);\r
8556b852
M
935 }\r
936 }\r
937\r
938 LED_C_OFF();\r
7906cb41 939\r
8556b852
M
940 // ----------------------------- crypto1 destroy\r
941 crypto1_destroy(pcs);\r
7906cb41 942\r
9492e0b0 943 byte_t buf[4 + 4 * 4];\r
944 memcpy(buf, &cuid, 4);\r
945 memcpy(buf+4, &target_nt[0], 4);\r
946 memcpy(buf+8, &target_ks[0], 4);\r
947 memcpy(buf+12, &target_nt[1], 4);\r
948 memcpy(buf+16, &target_ks[1], 4);\r
7906cb41 949\r
8556b852 950 LED_B_ON();\r
dc8ba239 951 cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));\r
6e82300d 952 LED_B_OFF();\r
8556b852 953\r
9492e0b0 954 if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");\r
8556b852 955\r
8556b852
M
956 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
957 LEDsoff();\r
8556b852
M
958}\r
959\r
960//-----------------------------------------------------------------------------\r
7906cb41
F
961// MIFARE check keys. key count up to 85.\r
962//\r
8556b852 963//-----------------------------------------------------------------------------\r
5330f532 964void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
8556b852 965{\r
5330f532 966 uint8_t blockNo = arg0 & 0xff;\r
967 uint8_t keyType = (arg0 >> 8) & 0xff;\r
968 bool clearTrace = arg1;\r
8556b852
M
969 uint8_t keyCount = arg2;\r
970 uint64_t ui64Key = 0;\r
7906cb41 971\r
de77d4ac 972 bool have_uid = false;\r
973 uint8_t cascade_levels = 0;\r
974 uint32_t timeout = 0;\r
8556b852
M
975 int i;\r
976 byte_t isOK = 0;\r
1c611bbd 977 uint8_t uid[10];\r
8556b852
M
978 uint32_t cuid;\r
979 struct Crypto1State mpcs = {0, 0};\r
980 struct Crypto1State *pcs;\r
981 pcs = &mpcs;\r
7906cb41 982\r
8556b852 983 // clear debug level\r
7906cb41 984 int OLD_MF_DBGLEVEL = MF_DBGLEVEL;\r
8556b852 985 MF_DBGLEVEL = MF_DBG_NONE;\r
7906cb41 986\r
8556b852
M
987 LED_A_ON();\r
988 LED_B_OFF();\r
989 LED_C_OFF();\r
09ffd16e 990 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
991\r
5330f532 992 if (clearTrace) clear_trace();\r
de77d4ac 993 set_tracing(true);\r
8556b852 994\r
8556b852 995 for (i = 0; i < keyCount; i++) {\r
de77d4ac 996// if(mifare_classic_halt(pcs, cuid)) {\r
997// if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error");\r
998// }\r
999\r
1000 // Iceman: use piwi's faster nonce collecting part in hardnested.\r
1001 if (!have_uid) { // need a full select cycle to get the uid first\r
7906cb41 1002 iso14a_card_select_t card_info;\r
de77d4ac 1003 if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) {\r
1004 if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card");\r
1005 --i; // try same key once again\r
1006 continue;\r
1007 }\r
1008 switch (card_info.uidlen) {\r
1009 case 4 : cascade_levels = 1; break;\r
1010 case 7 : cascade_levels = 2; break;\r
1011 case 10: cascade_levels = 3; break;\r
1012 default: break;\r
1013 }\r
7906cb41 1014 have_uid = true;\r
de77d4ac 1015 } else { // no need for anticollision. We can directly select the card\r
1016 if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) {\r
1017 if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)");\r
1018 --i; // try same key once again\r
1019 continue;\r
1020 }\r
9492e0b0 1021 }\r
8556b852 1022\r
8556b852
M
1023 ui64Key = bytes_to_num(datain + i * 6, 6);\r
1024 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
de77d4ac 1025 uint8_t dummy_answer = 0;\r
1026 ReaderTransmit(&dummy_answer, 1, NULL);\r
1027 timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;\r
7906cb41 1028\r
de77d4ac 1029 // wait for the card to become ready again\r
1030 while(GetCountSspClk() < timeout);\r
8556b852 1031 continue;\r
de77d4ac 1032 }\r
7906cb41 1033\r
8556b852
M
1034 isOK = 1;\r
1035 break;\r
1036 }\r
7906cb41 1037\r
8556b852 1038 LED_B_ON();\r
6e82300d 1039 cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);\r
8556b852
M
1040 LED_B_OFF();\r
1041\r
8556b852
M
1042 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1043 LEDsoff();\r
1044\r
1045 // restore debug level\r
7906cb41 1046 MF_DBGLEVEL = OLD_MF_DBGLEVEL;\r
8556b852
M
1047}\r
1048\r
1049//-----------------------------------------------------------------------------\r
1050// MIFARE commands set debug level\r
7906cb41 1051//\r
8556b852
M
1052//-----------------------------------------------------------------------------\r
1053void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1054 MF_DBGLEVEL = arg0;\r
1055 Dbprintf("Debug level: %d", MF_DBGLEVEL);\r
1056}\r
1057\r
1058//-----------------------------------------------------------------------------\r
1059// Work with emulator memory\r
7906cb41 1060//\r
09ffd16e 1061// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not\r
1062// involved in dealing with emulator memory. But if it is called later, it might\r
1063// destroy the Emulator Memory.\r
8556b852 1064//-----------------------------------------------------------------------------\r
09ffd16e 1065\r
8556b852 1066void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
09ffd16e 1067 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
8556b852
M
1068 emlClearMem();\r
1069}\r
1070\r
1071void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
09ffd16e 1072 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
8556b852
M
1073 emlSetMem(datain, arg0, arg1); // data, block num, blocks count\r
1074}\r
1075\r
1076void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
09ffd16e 1077 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
3fe4ff4f 1078 byte_t buf[USB_CMD_DATA_SIZE];\r
baeaf579 1079 emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4)\r
8556b852
M
1080\r
1081 LED_B_ON();\r
3fe4ff4f 1082 cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE);\r
8556b852
M
1083 LED_B_OFF();\r
1084}\r
1085\r
1086//-----------------------------------------------------------------------------\r
1087// Load a card into the emulator memory\r
7906cb41 1088//\r
8556b852
M
1089//-----------------------------------------------------------------------------\r
1090void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
baeaf579 1091 uint8_t numSectors = arg0;\r
8556b852
M
1092 uint8_t keyType = arg1;\r
1093 uint64_t ui64Key = 0;\r
1094 uint32_t cuid;\r
1095 struct Crypto1State mpcs = {0, 0};\r
1096 struct Crypto1State *pcs;\r
1097 pcs = &mpcs;\r
1098\r
1099 // variables\r
1100 byte_t dataoutbuf[16];\r
ab8b654e 1101 byte_t dataoutbuf2[16];\r
1c611bbd 1102 uint8_t uid[10];\r
8556b852 1103\r
8556b852
M
1104 LED_A_ON();\r
1105 LED_B_OFF();\r
1106 LED_C_OFF();\r
09ffd16e 1107 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
7906cb41 1108\r
09ffd16e 1109 clear_trace();\r
1110 set_tracing(false);\r
7906cb41 1111\r
baeaf579 1112 bool isOK = true;\r
1113\r
de77d4ac 1114 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
baeaf579 1115 isOK = false;\r
1116 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
1117 }\r
7906cb41 1118\r
baeaf579 1119 for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {\r
1120 ui64Key = emlGetKey(sectorNo, keyType);\r
1121 if (sectorNo == 0){\r
1122 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
1123 isOK = false;\r
1124 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);\r
8556b852 1125 break;\r
baeaf579 1126 }\r
1127 } else {\r
1128 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {\r
1129 isOK = false;\r
1130 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);\r
8556b852 1131 break;\r
baeaf579 1132 }\r
1133 }\r
7906cb41 1134\r
baeaf579 1135 for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
1136 if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {\r
1137 isOK = false;\r
1138 if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);\r
ab8b654e
M
1139 break;\r
1140 };\r
baeaf579 1141 if (isOK) {\r
1142 if (blockNo < NumBlocksPerSector(sectorNo) - 1) {\r
1143 emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
1144 } else { // sector trailer, keep the keys, set only the AC\r
1145 emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
1146 memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);\r
1147 emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
1148 }\r
1149 }\r
8556b852
M
1150 }\r
1151\r
baeaf579 1152 }\r
1153\r
1154 if(mifare_classic_halt(pcs, cuid)) {\r
1155 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
1156 };\r
8556b852
M
1157\r
1158 // ----------------------------- crypto1 destroy\r
1159 crypto1_destroy(pcs);\r
ab8b654e
M
1160\r
1161 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1162 LEDsoff();\r
7906cb41 1163\r
8556b852
M
1164 if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");\r
1165\r
8556b852
M
1166}\r
1167\r
0675f200
M
1168\r
1169//-----------------------------------------------------------------------------\r
1170// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)\r
7906cb41 1171//\r
0675f200
M
1172//-----------------------------------------------------------------------------\r
1173void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
7906cb41 1174\r
0675f200
M
1175 // params\r
1176 uint8_t needWipe = arg0;\r
208a0166
M
1177 // bit 0 - need get UID\r
1178 // bit 1 - need wupC\r
1179 // bit 2 - need HALT after sequence\r
1180 // bit 3 - need init FPGA and field before sequence\r
1181 // bit 4 - need reset FPGA and LED\r
7906cb41 1182 // bit 6 - gen1b backdoor type\r
208a0166 1183 uint8_t workFlags = arg1;\r
0675f200 1184 uint8_t blockNo = arg2;\r
7906cb41 1185\r
0675f200 1186 // card commands\r
7906cb41
F
1187 uint8_t wupC1[] = { 0x40 };\r
1188 uint8_t wupC2[] = { 0x43 };\r
1189 uint8_t wipeC[] = { 0x41 };\r
1190\r
0675f200
M
1191 // variables\r
1192 byte_t isOK = 0;\r
3fe4ff4f 1193 uint8_t uid[10] = {0x00};\r
1194 uint8_t d_block[18] = {0x00};\r
0675f200 1195 uint32_t cuid;\r
7906cb41 1196\r
f71f4deb 1197 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1198 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
6a1f2d82 1199\r
3fe4ff4f 1200 // reset FPGA and LED\r
208a0166 1201 if (workFlags & 0x08) {\r
208a0166
M
1202 LED_A_ON();\r
1203 LED_B_OFF();\r
1204 LED_C_OFF();\r
09ffd16e 1205 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
7906cb41 1206\r
3000dc4e 1207 clear_trace();\r
de77d4ac 1208 set_tracing(true);\r
208a0166 1209 }\r
0675f200
M
1210\r
1211 while (true) {\r
3fe4ff4f 1212\r
0675f200 1213 // get UID from chip\r
208a0166 1214 if (workFlags & 0x01) {\r
de77d4ac 1215 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {\r
0675f200
M
1216 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
1217 break;\r
7906cb41 1218 };\r
0675f200 1219\r
7906cb41
F
1220 if(mifare_classic_halt(NULL, cuid)) {\r
1221 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1222 // Continue, some magic tags misbehavies and send an answer to it.\r
1223 // break;\r
1224 };\r
0675f200 1225 };\r
7906cb41 1226\r
0675f200 1227 // reset chip\r
7906cb41
F
1228 // Wipe command don't work with gen1b\r
1229 if (needWipe && !(workFlags & 0x40)){\r
6a1f2d82 1230 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1231 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1232 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1233 break;\r
1234 };\r
1235\r
9492e0b0 1236 ReaderTransmit(wipeC, sizeof(wipeC), NULL);\r
6a1f2d82 1237 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1238 if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
1239 break;\r
1240 };\r
1241\r
1242 if(mifare_classic_halt(NULL, cuid)) {\r
7906cb41
F
1243 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1244 // Continue, some magic tags misbehavies and send an answer to it.\r
1245 // break;\r
0675f200 1246 };\r
7906cb41 1247 };\r
0675f200 1248\r
545a1f38 1249 // write block\r
208a0166 1250 if (workFlags & 0x02) {\r
6a1f2d82 1251 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
0675f200 1252\r
7906cb41
F
1253 // gen1b magic tag : do no issue wupC2 and don't expect 0x0a response after SELECT_UID (after getting UID from chip in 'hf mf csetuid' command)\r
1254 if (!(workFlags & 0x40)) {\r
1255\r
1256 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1257 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1258 break;\r
1259 };\r
1260\r
1261 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1262 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1263 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
1264 break;\r
1265 };\r
1266 }\r
208a0166 1267 }\r
0675f200 1268\r
6a1f2d82 1269 if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1270 if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
1271 break;\r
1272 };\r
7906cb41 1273\r
0675f200
M
1274 memcpy(d_block, datain, 16);\r
1275 AppendCrc14443a(d_block, 16);\r
7906cb41 1276\r
9492e0b0 1277 ReaderTransmit(d_block, sizeof(d_block), NULL);\r
6a1f2d82 1278 if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1279 if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
1280 break;\r
7906cb41
F
1281 };\r
1282\r
208a0166 1283 if (workFlags & 0x04) {\r
7906cb41
F
1284 // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
1285 if (!(workFlags & 0x40)) {\r
1286 if (mifare_classic_halt(NULL, cuid)) {\r
1287 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1288 // Continue, some magic tags misbehavies and send an answer to it.\r
1289 // break;\r
1290 }\r
1291 }\r
208a0166 1292 }\r
7906cb41 1293\r
0675f200
M
1294 isOK = 1;\r
1295 break;\r
1296 }\r
7906cb41 1297\r
0675f200 1298 LED_B_ON();\r
baeaf579 1299 cmd_send(CMD_ACK,isOK,0,0,uid,4);\r
0675f200
M
1300 LED_B_OFF();\r
1301\r
545a1f38 1302 if ((workFlags & 0x10) || (!isOK)) {\r
208a0166
M
1303 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1304 LEDsoff();\r
1305 }\r
0675f200 1306}\r
545a1f38 1307\r
baeaf579 1308\r
545a1f38 1309void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
7906cb41
F
1310\r
1311 // params\r
545a1f38
M
1312 // bit 1 - need wupC\r
1313 // bit 2 - need HALT after sequence\r
1314 // bit 3 - need init FPGA and field before sequence\r
1315 // bit 4 - need reset FPGA and LED\r
c89274cc 1316 // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)\r
7906cb41 1317 // bit 6 - gen1b backdoor type\r
545a1f38
M
1318 uint8_t workFlags = arg0;\r
1319 uint8_t blockNo = arg2;\r
7906cb41 1320\r
545a1f38 1321 // card commands\r
7906cb41
F
1322 uint8_t wupC1[] = { 0x40 };\r
1323 uint8_t wupC2[] = { 0x43 };\r
1324\r
545a1f38
M
1325 // variables\r
1326 byte_t isOK = 0;\r
3fe4ff4f 1327 uint8_t data[18] = {0x00};\r
545a1f38 1328 uint32_t cuid = 0;\r
7906cb41 1329\r
f71f4deb 1330 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1331 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
7906cb41 1332\r
545a1f38 1333 if (workFlags & 0x08) {\r
545a1f38
M
1334 LED_A_ON();\r
1335 LED_B_OFF();\r
1336 LED_C_OFF();\r
09ffd16e 1337 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1338\r
3000dc4e 1339 clear_trace();\r
de77d4ac 1340 set_tracing(true);\r
545a1f38
M
1341 }\r
1342\r
1343 while (true) {\r
1344 if (workFlags & 0x02) {\r
7bc95e2e 1345 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
6a1f2d82 1346 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
545a1f38
M
1347 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1348 break;\r
7906cb41
F
1349 };\r
1350 // do no issue for gen1b magic tag\r
1351 if (!(workFlags & 0x40)) {\r
9492e0b0 1352 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
6a1f2d82 1353 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
545a1f38
M
1354 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
1355 break;\r
1356 };\r
1357 }\r
7906cb41 1358 }\r
545a1f38
M
1359\r
1360 // read block\r
6a1f2d82 1361 if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {\r
545a1f38
M
1362 if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
1363 break;\r
1364 };\r
1365 memcpy(data, receivedAnswer, 18);\r
7906cb41 1366\r
545a1f38 1367 if (workFlags & 0x04) {\r
7906cb41
F
1368 // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
1369 if (!(workFlags & 0x40)) {\r
1370 if (mifare_classic_halt(NULL, cuid)) {\r
1371 if (MF_DBGLEVEL > 1) Dbprintf("Halt error");\r
1372 // Continue, some magic tags misbehavies and send an answer to it.\r
1373 // break;\r
1374 }\r
1375 }\r
545a1f38 1376 }\r
7906cb41 1377\r
545a1f38
M
1378 isOK = 1;\r
1379 break;\r
1380 }\r
7906cb41 1381\r
545a1f38 1382 LED_B_ON();\r
c89274cc
CY
1383 if (workFlags & 0x20) {\r
1384 if (isOK)\r
1385 memcpy(datain, data, 18);\r
1386 }\r
1387 else\r
1388 cmd_send(CMD_ACK,isOK,0,0,data,18);\r
545a1f38
M
1389 LED_B_OFF();\r
1390\r
1391 if ((workFlags & 0x10) || (!isOK)) {\r
545a1f38
M
1392 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1393 LEDsoff();\r
1394 }\r
1395}\r
1396\r
3fe4ff4f 1397void MifareCIdent(){\r
7906cb41 1398\r
3fe4ff4f 1399 // card commands\r
7906cb41
F
1400 uint8_t wupC1[] = { 0x40 };\r
1401 uint8_t wupC2[] = { 0x43 };\r
1402\r
3fe4ff4f 1403 // variables\r
7906cb41
F
1404 byte_t isOK = 0;\r
1405\r
f71f4deb 1406 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1407 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
3fe4ff4f 1408\r
1409 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
7906cb41
F
1410 if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
1411 isOK = 2;\r
3fe4ff4f 1412\r
7906cb41
F
1413 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1414 if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
1415 isOK = 1;\r
1416 };\r
3fe4ff4f 1417 };\r
1418\r
7906cb41
F
1419 // From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.\r
1420 mifare_classic_halt(NULL, 0);\r
3fe4ff4f 1421\r
1422 cmd_send(CMD_ACK,isOK,0,0,0,0);\r
1423}\r
1424\r
09ffd16e 1425//\r
3fe4ff4f 1426// DESFIRE\r
1427//\r
a631936e 1428\r
1429void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){\r
1430\r
1431 byte_t dataout[11] = {0x00};\r
1432 uint8_t uid[10] = {0x00};\r
1433 uint32_t cuid;\r
7906cb41 1434\r
a631936e 1435 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
09ffd16e 1436 clear_trace();\r
a631936e 1437\r
de77d4ac 1438 int len = iso14443a_select_card(uid, NULL, &cuid, true, 0);\r
a631936e 1439 if(!len) {\r
8258f409 1440 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
1441 OnError(1);\r
a631936e 1442 return;\r
1443 };\r
1444\r
1445 if(mifare_desfire_des_auth1(cuid, dataout)){\r
8258f409 1446 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");\r
1447 OnError(4);\r
a631936e 1448 return;\r
1449 }\r
1450\r
1451 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
a631936e 1452 cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));\r
1453}\r
1454\r
1455void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){\r
1456\r
1457 uint32_t cuid = arg0;\r
1458 uint8_t key[16] = {0x00};\r
1459 byte_t isOK = 0;\r
1460 byte_t dataout[12] = {0x00};\r
7906cb41 1461\r
a631936e 1462 memcpy(key, datain, 16);\r
7906cb41 1463\r
a631936e 1464 isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
7906cb41 1465\r
a631936e 1466 if( isOK) {\r
7906cb41 1467 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");\r
4973f23d 1468 OnError(4);\r
a631936e 1469 return;\r
1470 }\r
1471\r
4973f23d 1472 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
a631936e 1473\r
1474 cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
1475 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1476 LEDsoff();\r
3000dc4e 1477}\r
f168b263 1478\r
1479void OnSuccess(){\r
1480 pcb_blocknum = 0;\r
1481 ReaderTransmit(deselect_cmd, 3 , NULL);\r
1482 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1483 LEDsoff();\r
1484}\r
1485\r
1486void OnError(uint8_t reason){\r
1487 pcb_blocknum = 0;\r
1488 ReaderTransmit(deselect_cmd, 3 , NULL);\r
1489 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1490 cmd_send(CMD_ACK,0,reason,0,0,0);\r
1491 LEDsoff();\r
1492}\r
Impressum, Datenschutz