]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/mifarecmd.c
Fido U2F complete (#716)
[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
d1f9ec06 23#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)\r
24#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication \r
25\r
f168b263 26// the block number for the ISO14443-4 PCB\r
de77d4ac 27static uint8_t pcb_blocknum = 0;\r
f168b263 28// Deselect card by sending a s-block. the crc is precalced for speed\r
29static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};\r
30\r
8556b852 31//-----------------------------------------------------------------------------\r
7906cb41 32// Select, Authenticate, Read a MIFARE tag.\r
8556b852
M
33// read block\r
34//-----------------------------------------------------------------------------\r
35void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
36{\r
37 // params\r
38 uint8_t blockNo = arg0;\r
39 uint8_t keyType = arg1;\r
40 uint64_t ui64Key = 0;\r
41 ui64Key = bytes_to_num(datain, 6);\r
7906cb41 42\r
8556b852
M
43 // variables\r
44 byte_t isOK = 0;\r
45 byte_t dataoutbuf[16];\r
1c611bbd 46 uint8_t uid[10];\r
8556b852
M
47 uint32_t cuid;\r
48 struct Crypto1State mpcs = {0, 0};\r
49 struct Crypto1State *pcs;\r
50 pcs = &mpcs;\r
51\r
7bc95e2e 52 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
8556b852 53\r
09ffd16e 54 clear_trace();\r
55\r
8556b852
M
56 LED_A_ON();\r
57 LED_B_OFF();\r
58 LED_C_OFF();\r
59\r
60 while (true) {\r
c04a4b60 61 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
baeaf579 62 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
8556b852
M
63 break;\r
64 };\r
65\r
66 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
baeaf579 67 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
8556b852
M
68 break;\r
69 };\r
7906cb41 70\r
8556b852 71 if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {\r
baeaf579 72 if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r
8556b852
M
73 break;\r
74 };\r
75\r
76 if(mifare_classic_halt(pcs, cuid)) {\r
baeaf579 77 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
8556b852
M
78 break;\r
79 };\r
7906cb41 80\r
8556b852
M
81 isOK = 1;\r
82 break;\r
83 }\r
7906cb41 84\r
8556b852
M
85 // ----------------------------- crypto1 destroy\r
86 crypto1_destroy(pcs);\r
7906cb41 87\r
8556b852
M
88 if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
89\r
8556b852 90 LED_B_ON();\r
baeaf579 91 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);\r
8556b852
M
92 LED_B_OFF();\r
93\r
a631936e 94 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
95 LEDsoff();\r
96}\r
97\r
8258f409 98void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){\r
a631936e 99\r
8258f409 100 bool turnOffField = (arg0 == 1);\r
a631936e 101\r
f168b263 102 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
09ffd16e 103\r
a631936e 104 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
105\r
09ffd16e 106 clear_trace();\r
107\r
c04a4b60 108 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {\r
f168b263 109 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
110 OnError(0);\r
a631936e 111 return;\r
112 };\r
7906cb41 113\r
9d87eb66 114 if(!mifare_ultra_auth(keybytes)){\r
8258f409 115 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed");\r
f168b263 116 OnError(1);\r
a631936e 117 return;\r
118 }\r
119\r
8258f409 120 if (turnOffField) {\r
cceabb79 121 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
122 LEDsoff();\r
123 }\r
9d87eb66 124 cmd_send(CMD_ACK,1,0,0,0,0);\r
7cc204bf 125}\r
126\r
75377d29 127// Arg0 = BlockNo,\r
128// Arg1 = UsePwd bool\r
129// datain = PWD bytes,\r
f168b263 130void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
7cc204bf 131{\r
7cc204bf 132 uint8_t blockNo = arg0;\r
787b5bd8 133 byte_t dataout[16] = {0x00};\r
8258f409 134 bool useKey = (arg1 == 1); //UL_C\r
135 bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
f168b263 136\r
75377d29 137 LEDsoff();\r
138 LED_A_ON();\r
787b5bd8 139 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
f168b263 140\r
09ffd16e 141 clear_trace();\r
142\r
c04a4b60 143 int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);\r
787b5bd8 144 if(!len) {\r
f168b263 145 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);\r
146 OnError(1);\r
787b5bd8 147 return;\r
f168b263 148 }\r
149\r
8258f409 150 // UL-C authentication\r
151 if ( useKey ) {\r
152 uint8_t key[16] = {0x00};\r
153 memcpy(key, datain, sizeof(key) );\r
f168b263 154\r
9d87eb66 155 if ( !mifare_ultra_auth(key) ) {\r
f168b263 156 OnError(1);\r
157 return;\r
158 }\r
8258f409 159 }\r
f168b263 160\r
8258f409 161 // UL-EV1 / NTAG authentication\r
162 if ( usePwd ) {\r
163 uint8_t pwd[4] = {0x00};\r
164 memcpy(pwd, datain, 4);\r
165 uint8_t pack[4] = {0,0,0,0};\r
9d87eb66 166 if (!mifare_ul_ev1_auth(pwd, pack)) {\r
f168b263 167 OnError(1);\r
168 return;\r
169 }\r
7906cb41 170 }\r
f168b263 171\r
f168b263 172 if( mifare_ultra_readblock(blockNo, dataout) ) {\r
173 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");\r
174 OnError(2);\r
787b5bd8 175 return;\r
f168b263 176 }\r
8258f409 177\r
f168b263 178 if( mifare_ultra_halt() ) {\r
179 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
180 OnError(3);\r
787b5bd8 181 return;\r
f168b263 182 }\r
8258f409 183\r
184 cmd_send(CMD_ACK,1,0,0,dataout,16);\r
7cc204bf 185 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
186 LEDsoff();\r
187}\r
b3125340 188\r
7cc204bf 189//-----------------------------------------------------------------------------\r
7906cb41 190// Select, Authenticate, Read a MIFARE tag.\r
baeaf579 191// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)\r
8556b852
M
192//-----------------------------------------------------------------------------\r
193void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
194{\r
195 // params\r
196 uint8_t sectorNo = arg0;\r
197 uint8_t keyType = arg1;\r
198 uint64_t ui64Key = 0;\r
199 ui64Key = bytes_to_num(datain, 6);\r
7906cb41 200\r
8556b852 201 // variables\r
3fe4ff4f 202 byte_t isOK = 0;\r
baeaf579 203 byte_t dataoutbuf[16 * 16];\r
1c611bbd 204 uint8_t uid[10];\r
8556b852
M
205 uint32_t cuid;\r
206 struct Crypto1State mpcs = {0, 0};\r
207 struct Crypto1State *pcs;\r
208 pcs = &mpcs;\r
209\r
7bc95e2e 210 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
8556b852 211\r
09ffd16e 212 clear_trace();\r
213\r
8556b852
M
214 LED_A_ON();\r
215 LED_B_OFF();\r
216 LED_C_OFF();\r
217\r
baeaf579 218 isOK = 1;\r
c04a4b60 219 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
baeaf579 220 isOK = 0;\r
8556b852 221 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
baeaf579 222 }\r
8556b852 223\r
7906cb41 224\r
baeaf579 225 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
226 isOK = 0;\r
8556b852 227 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
baeaf579 228 }\r
7906cb41 229\r
baeaf579 230 for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
231 if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {\r
232 isOK = 0;\r
233 if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);\r
8556b852 234 break;\r
baeaf579 235 }\r
236 }\r
7906cb41 237\r
baeaf579 238 if(mifare_classic_halt(pcs, cuid)) {\r
8556b852 239 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
8556b852 240 }\r
baeaf579 241\r
8556b852
M
242 // ----------------------------- crypto1 destroy\r
243 crypto1_destroy(pcs);\r
7906cb41 244\r
8556b852
M
245 if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");\r
246\r
8556b852 247 LED_B_ON();\r
baeaf579 248 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));\r
6e82300d 249 LED_B_OFF();\r
8556b852
M
250\r
251 // Thats it...\r
252 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
253 LEDsoff();\r
7cc204bf 254}\r
255\r
79d7bcbb 256// arg0 = blockNo (start)\r
257// arg1 = Pages (number of blocks)\r
258// arg2 = useKey\r
259// datain = KEY bytes\r
75377d29 260void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
7cc204bf 261{\r
09ffd16e 262 LEDsoff();\r
263 LED_A_ON();\r
264 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
265\r
d7acc640 266 // free eventually allocated BigBuf memory\r
267 BigBuf_free();\r
d7acc640 268 clear_trace();\r
269\r
f168b263 270 // params\r
75377d29 271 uint8_t blockNo = arg0;\r
272 uint16_t blocks = arg1;\r
cceabb79 273 bool useKey = (arg2 == 1); //UL_C\r
274 bool usePwd = (arg2 == 2); //UL_EV1/NTAG\r
9d87eb66 275 uint32_t countblocks = 0;\r
d7acc640 276 uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE);\r
277 if (dataout == NULL){\r
278 Dbprintf("out of memory");\r
279 OnError(1);\r
280 return;\r
281 }\r
7cc204bf 282\r
c04a4b60 283 int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);\r
787b5bd8 284 if (!len) {\r
f168b263 285 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);\r
286 OnError(1);\r
787b5bd8 287 return;\r
288 }\r
75377d29 289\r
8258f409 290 // UL-C authentication\r
75377d29 291 if ( useKey ) {\r
292 uint8_t key[16] = {0x00};\r
8258f409 293 memcpy(key, datain, sizeof(key) );\r
75377d29 294\r
9d87eb66 295 if ( !mifare_ultra_auth(key) ) {\r
75377d29 296 OnError(1);\r
297 return;\r
298 }\r
75377d29 299 }\r
300\r
8258f409 301 // UL-EV1 / NTAG authentication\r
302 if (usePwd) {\r
303 uint8_t pwd[4] = {0x00};\r
304 memcpy(pwd, datain, sizeof(pwd));\r
cceabb79 305 uint8_t pack[4] = {0,0,0,0};\r
306\r
9d87eb66 307 if (!mifare_ul_ev1_auth(pwd, pack)){\r
cceabb79 308 OnError(1);\r
7906cb41 309 return;\r
cceabb79 310 }\r
311 }\r
312\r
75377d29 313 for (int i = 0; i < blocks; i++){\r
22342f6d 314 if ((i*4) + 4 >= CARD_MEMORY_SIZE) {\r
9d87eb66 315 Dbprintf("Data exceeds buffer!!");\r
316 break;\r
317 }\r
7906cb41 318\r
9d87eb66 319 len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
75377d29 320\r
787b5bd8 321 if (len) {\r
f168b263 322 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);\r
9d87eb66 323 // if no blocks read - error out\r
324 if (i==0){\r
325 OnError(2);\r
326 return;\r
327 } else {\r
328 //stop at last successful read block and return what we got\r
329 break;\r
330 }\r
787b5bd8 331 } else {\r
75377d29 332 countblocks++;\r
787b5bd8 333 }\r
334 }\r
75377d29 335\r
f168b263 336 len = mifare_ultra_halt();\r
787b5bd8 337 if (len) {\r
f168b263 338 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
339 OnError(3);\r
787b5bd8 340 return;\r
341 }\r
7cc204bf 342\r
75377d29 343 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);\r
344\r
9d87eb66 345 countblocks *= 4;\r
22342f6d 346\r
0ce03d9a 347 cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);\r
31d1caa5
MHS
348 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
349 LEDsoff();\r
22342f6d 350 BigBuf_free();\r
7cc204bf 351}\r
352\r
7cc204bf 353//-----------------------------------------------------------------------------\r
7906cb41 354// Select, Authenticate, Write a MIFARE tag.\r
7cc204bf 355// read block\r
8556b852
M
356//-----------------------------------------------------------------------------\r
357void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
358{\r
359 // params\r
360 uint8_t blockNo = arg0;\r
361 uint8_t keyType = arg1;\r
362 uint64_t ui64Key = 0;\r
363 byte_t blockdata[16];\r
364\r
365 ui64Key = bytes_to_num(datain, 6);\r
366 memcpy(blockdata, datain + 10, 16);\r
7906cb41 367\r
8556b852
M
368 // variables\r
369 byte_t isOK = 0;\r
1c611bbd 370 uint8_t uid[10];\r
8556b852
M
371 uint32_t cuid;\r
372 struct Crypto1State mpcs = {0, 0};\r
373 struct Crypto1State *pcs;\r
374 pcs = &mpcs;\r
375\r
7bc95e2e 376 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
8556b852 377\r
09ffd16e 378 clear_trace();\r
379\r
8556b852
M
380 LED_A_ON();\r
381 LED_B_OFF();\r
382 LED_C_OFF();\r
383\r
384 while (true) {\r
c04a4b60 385 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
8556b852
M
386 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
387 break;\r
388 };\r
389\r
390 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
391 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
392 break;\r
393 };\r
7906cb41 394\r
8556b852
M
395 if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {\r
396 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
397 break;\r
398 };\r
399\r
400 if(mifare_classic_halt(pcs, cuid)) {\r
401 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
402 break;\r
403 };\r
7906cb41 404\r
8556b852
M
405 isOK = 1;\r
406 break;\r
407 }\r
7906cb41 408\r
8556b852
M
409 // ----------------------------- crypto1 destroy\r
410 crypto1_destroy(pcs);\r
7906cb41 411\r
8556b852
M
412 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
413\r
8556b852 414 LED_B_ON();\r
9492e0b0 415 cmd_send(CMD_ACK,isOK,0,0,0,0);\r
6e82300d 416 LED_B_OFF();\r
8556b852
M
417\r
418\r
419 // Thats it...\r
420 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
421 LEDsoff();\r
7cc204bf 422}\r
423\r
7906cb41 424/* // Command not needed but left for future testing\r
4973f23d 425void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)\r
7cc204bf 426{\r
f168b263 427 uint8_t blockNo = arg0;\r
787b5bd8 428 byte_t blockdata[16] = {0x00};\r
7cc204bf 429\r
f168b263 430 memcpy(blockdata, datain, 16);\r
431\r
787b5bd8 432 uint8_t uid[10] = {0x00};\r
7cc204bf 433\r
f168b263 434 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
7cc204bf 435\r
f168b263 436 clear_trace();\r
437 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
438\r
de77d4ac 439 if(!iso14443a_select_card(uid, NULL, NULL, true, 0)) {\r
f168b263 440 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
441 OnError(0);\r
442 return;\r
443 };\r
444\r
4973f23d 445 if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {\r
f168b263 446 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
447 OnError(0);\r
448 return; };\r
449\r
450 if(mifare_ultra_halt()) {\r
451 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
452 OnError(0);\r
453 return;\r
454 };\r
455\r
456 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
457\r
458 cmd_send(CMD_ACK,1,0,0,0,0);\r
459 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
460 LEDsoff();\r
7cc204bf 461}\r
4973f23d 462*/\r
7cc204bf 463\r
79d7bcbb 464// Arg0 : Block to write to.\r
465// Arg1 : 0 = use no authentication.\r
466// 1 = use 0x1A authentication.\r
467// 2 = use 0x1B authentication.\r
468// datain : 4 first bytes is data to be written.\r
469// : 4/16 next bytes is authentication key.\r
4973f23d 470void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
7cc204bf 471{\r
baeaf579 472 uint8_t blockNo = arg0;\r
79d7bcbb 473 bool useKey = (arg1 == 1); //UL_C\r
474 bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
787b5bd8 475 byte_t blockdata[4] = {0x00};\r
7cc204bf 476\r
8258f409 477 memcpy(blockdata, datain,4);\r
7906cb41 478\r
8258f409 479 LEDsoff();\r
480 LED_A_ON();\r
f168b263 481 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
482\r
09ffd16e 483 clear_trace();\r
484\r
c04a4b60 485 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {\r
f168b263 486 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
487 OnError(0);\r
488 return;\r
489 };\r
7cc204bf 490\r
79d7bcbb 491 // UL-C authentication\r
492 if ( useKey ) {\r
493 uint8_t key[16] = {0x00};\r
494 memcpy(key, datain+4, sizeof(key) );\r
495\r
496 if ( !mifare_ultra_auth(key) ) {\r
497 OnError(1);\r
498 return;\r
499 }\r
500 }\r
7906cb41 501\r
79d7bcbb 502 // UL-EV1 / NTAG authentication\r
503 if (usePwd) {\r
504 uint8_t pwd[4] = {0x00};\r
505 memcpy(pwd, datain+4, 4);\r
506 uint8_t pack[4] = {0,0,0,0};\r
507 if (!mifare_ul_ev1_auth(pwd, pack)) {\r
508 OnError(1);\r
509 return;\r
510 }\r
511 }\r
512\r
4973f23d 513 if(mifare_ultra_writeblock(blockNo, blockdata)) {\r
f168b263 514 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
515 OnError(0);\r
516 return;\r
517 };\r
518\r
519 if(mifare_ultra_halt()) {\r
520 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
521 OnError(0);\r
522 return;\r
523 };\r
524\r
525 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
526\r
527 cmd_send(CMD_ACK,1,0,0,0,0);\r
528 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
529 LEDsoff();\r
530}\r
531\r
532void MifareUSetPwd(uint8_t arg0, uint8_t *datain){\r
7906cb41 533\r
f168b263 534 uint8_t pwd[16] = {0x00};\r
535 byte_t blockdata[4] = {0x00};\r
7906cb41 536\r
f168b263 537 memcpy(pwd, datain, 16);\r
7906cb41 538\r
f168b263 539 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
baeaf579 540 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
7cc204bf 541\r
09ffd16e 542 clear_trace();\r
543\r
c04a4b60 544 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {\r
f168b263 545 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
546 OnError(0);\r
547 return;\r
548 };\r
7cc204bf 549\r
f168b263 550 blockdata[0] = pwd[7];\r
551 blockdata[1] = pwd[6];\r
552 blockdata[2] = pwd[5];\r
553 blockdata[3] = pwd[4];\r
4973f23d 554 if(mifare_ultra_writeblock( 44, blockdata)) {\r
f168b263 555 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
556 OnError(44);\r
557 return;\r
558 };\r
7cc204bf 559\r
f168b263 560 blockdata[0] = pwd[3];\r
561 blockdata[1] = pwd[2];\r
562 blockdata[2] = pwd[1];\r
563 blockdata[3] = pwd[0];\r
4973f23d 564 if(mifare_ultra_writeblock( 45, blockdata)) {\r
f168b263 565 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
566 OnError(45);\r
567 return;\r
568 };\r
7cc204bf 569\r
f168b263 570 blockdata[0] = pwd[15];\r
571 blockdata[1] = pwd[14];\r
572 blockdata[2] = pwd[13];\r
573 blockdata[3] = pwd[12];\r
4973f23d 574 if(mifare_ultra_writeblock( 46, blockdata)) {\r
f168b263 575 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
576 OnError(46);\r
577 return;\r
578 };\r
7cc204bf 579\r
f168b263 580 blockdata[0] = pwd[11];\r
581 blockdata[1] = pwd[10];\r
582 blockdata[2] = pwd[9];\r
583 blockdata[3] = pwd[8];\r
4973f23d 584 if(mifare_ultra_writeblock( 47, blockdata)) {\r
f168b263 585 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
586 OnError(47);\r
587 return;\r
7906cb41 588 };\r
7cc204bf 589\r
f168b263 590 if(mifare_ultra_halt()) {\r
591 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
592 OnError(0);\r
593 return;\r
594 };\r
7cc204bf 595\r
f168b263 596 cmd_send(CMD_ACK,1,0,0,0,0);\r
baeaf579 597 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
598 LEDsoff();\r
7cc204bf 599}\r
600\r
601// Return 1 if the nonce is invalid else return 0\r
6a1f2d82 602int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {\r
1f065e1d 603 return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \\r
604 (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \\r
605 (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;\r
8556b852
M
606}\r
607\r
9492e0b0 608\r
de77d4ac 609//-----------------------------------------------------------------------------\r
610// acquire encrypted nonces in order to perform the attack described in\r
611// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened\r
7906cb41 612// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on\r
de77d4ac 613// Computer and Communications Security, 2015\r
614//-----------------------------------------------------------------------------\r
615void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain)\r
616{\r
617 uint64_t ui64Key = 0;\r
618 uint8_t uid[10];\r
619 uint32_t cuid;\r
620 uint8_t cascade_levels = 0;\r
621 struct Crypto1State mpcs = {0, 0};\r
622 struct Crypto1State *pcs;\r
623 pcs = &mpcs;\r
624 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
625 int16_t isOK = 0;\r
626 uint8_t par_enc[1];\r
627 uint8_t nt_par_enc = 0;\r
628 uint8_t buf[USB_CMD_DATA_SIZE];\r
629 uint32_t timeout;\r
7906cb41 630\r
de77d4ac 631 uint8_t blockNo = arg0 & 0xff;\r
632 uint8_t keyType = (arg0 >> 8) & 0xff;\r
633 uint8_t targetBlockNo = arg1 & 0xff;\r
634 uint8_t targetKeyType = (arg1 >> 8) & 0xff;\r
635 ui64Key = bytes_to_num(datain, 6);\r
636 bool initialize = flags & 0x0001;\r
637 bool slow = flags & 0x0002;\r
638 bool field_off = flags & 0x0004;\r
7906cb41 639\r
de77d4ac 640 LED_A_ON();\r
641 LED_C_OFF();\r
642\r
643 if (initialize) {\r
644 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
645 clear_trace();\r
646 set_tracing(true);\r
647 }\r
7906cb41 648\r
de77d4ac 649 LED_C_ON();\r
7906cb41 650\r
de77d4ac 651 uint16_t num_nonces = 0;\r
652 bool have_uid = false;\r
653 for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) {\r
654\r
655 // Test if the action was cancelled\r
656 if(BUTTON_PRESS()) {\r
657 isOK = 2;\r
658 field_off = true;\r
659 break;\r
660 }\r
661\r
662 if (!have_uid) { // need a full select cycle to get the uid first\r
7906cb41 663 iso14a_card_select_t card_info;\r
c04a4b60 664 if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {\r
de77d4ac 665 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)");\r
666 continue;\r
667 }\r
668 switch (card_info.uidlen) {\r
669 case 4 : cascade_levels = 1; break;\r
670 case 7 : cascade_levels = 2; break;\r
671 case 10: cascade_levels = 3; break;\r
672 default: break;\r
673 }\r
7906cb41 674 have_uid = true;\r
de77d4ac 675 } else { // no need for anticollision. We can directly select the card\r
c04a4b60 676 if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {\r
de77d4ac 677 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");\r
678 continue;\r
679 }\r
680 }\r
7906cb41 681\r
de77d4ac 682 if (slow) {\r
d1f9ec06 683 timeout = GetCountSspClk() + HARDNESTED_PRE_AUTHENTICATION_LEADTIME;\r
de77d4ac 684 while(GetCountSspClk() < timeout);\r
685 }\r
686\r
687 uint32_t nt1;\r
688 if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) {\r
689 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error");\r
690 continue;\r
691 }\r
692\r
693 // nested authentication\r
694 uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL);\r
695 if (len != 4) {\r
696 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len);\r
697 continue;\r
698 }\r
7906cb41 699\r
d1f9ec06 700 // send an incomplete dummy response in order to trigger the card's authentication failure timeout\r
701 uint8_t dummy_answer[1] = {0};\r
702 ReaderTransmit(dummy_answer, 1, NULL);\r
7906cb41 703\r
d1f9ec06 704 timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;\r
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
d1f9ec06 717 // wait for the card to become ready again\r
718 while(GetCountSspClk() < timeout);\r
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
c04a4b60 810 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\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
c04a4b60 884 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\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
275d9e61 964void MifareChkKeys(uint16_t arg0, uint16_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
275d9e61
OM
968 bool clearTrace = arg1 & 0x01;\r
969 bool multisectorCheck = arg1 & 0x02;\r
970 uint8_t set14aTimeout = (arg1 >> 8) & 0xff;\r
8556b852 971 uint8_t keyCount = arg2;\r
7906cb41 972\r
8556b852 973 // clear debug level\r
7906cb41 974 int OLD_MF_DBGLEVEL = MF_DBGLEVEL;\r
8556b852 975 MF_DBGLEVEL = MF_DBG_NONE;\r
7906cb41 976\r
8556b852
M
977 LED_A_ON();\r
978 LED_B_OFF();\r
979 LED_C_OFF();\r
09ffd16e 980 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
981\r
5330f532 982 if (clearTrace) clear_trace();\r
de77d4ac 983 set_tracing(true);\r
8556b852 984\r
275d9e61
OM
985 if (set14aTimeout){\r
986 iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe\r
987 }\r
988 \r
989 if (multisectorCheck) {\r
990 TKeyIndex keyIndex = {{0}};\r
991 uint8_t sectorCnt = blockNo;\r
992 int res = MifareMultisectorChk(datain, keyCount, sectorCnt, keyType, OLD_MF_DBGLEVEL, &keyIndex);\r
de77d4ac 993\r
275d9e61
OM
994 LED_B_ON();\r
995 if (res >= 0) {\r
996 cmd_send(CMD_ACK, 1, 0, 0, keyIndex, 80);\r
997 } else {\r
998 cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);\r
9492e0b0 999 }\r
275d9e61
OM
1000 LED_B_OFF();\r
1001 } else { \r
1002 int res = MifareChkBlockKeys(datain, keyCount, blockNo, keyType, OLD_MF_DBGLEVEL);\r
1003 \r
1004 LED_B_ON();\r
1005 if (res > 0) {\r
1006 cmd_send(CMD_ACK, 1, 0, 0, datain + (res - 1) * 6, 6);\r
1007 } else {\r
1008 cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);\r
de77d4ac 1009 }\r
275d9e61 1010 LED_B_OFF();\r
8556b852 1011 }\r
7906cb41 1012\r
8556b852
M
1013 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1014 LEDsoff();\r
1015\r
1016 // restore debug level\r
7906cb41 1017 MF_DBGLEVEL = OLD_MF_DBGLEVEL;\r
8556b852
M
1018}\r
1019\r
1020//-----------------------------------------------------------------------------\r
1021// MIFARE commands set debug level\r
7906cb41 1022//\r
8556b852
M
1023//-----------------------------------------------------------------------------\r
1024void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1025 MF_DBGLEVEL = arg0;\r
1026 Dbprintf("Debug level: %d", MF_DBGLEVEL);\r
1027}\r
1028\r
1029//-----------------------------------------------------------------------------\r
1030// Work with emulator memory\r
7906cb41 1031//\r
09ffd16e 1032// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not\r
1033// involved in dealing with emulator memory. But if it is called later, it might\r
1034// destroy the Emulator Memory.\r
8556b852 1035//-----------------------------------------------------------------------------\r
09ffd16e 1036\r
8556b852 1037void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
09ffd16e 1038 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
8556b852
M
1039 emlClearMem();\r
1040}\r
1041\r
1042void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
09ffd16e 1043 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
8556b852
M
1044 emlSetMem(datain, arg0, arg1); // data, block num, blocks count\r
1045}\r
1046\r
1047void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
09ffd16e 1048 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
3fe4ff4f 1049 byte_t buf[USB_CMD_DATA_SIZE];\r
baeaf579 1050 emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4)\r
8556b852
M
1051\r
1052 LED_B_ON();\r
3fe4ff4f 1053 cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE);\r
8556b852
M
1054 LED_B_OFF();\r
1055}\r
1056\r
1057//-----------------------------------------------------------------------------\r
1058// Load a card into the emulator memory\r
7906cb41 1059//\r
8556b852
M
1060//-----------------------------------------------------------------------------\r
1061void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
baeaf579 1062 uint8_t numSectors = arg0;\r
8556b852
M
1063 uint8_t keyType = arg1;\r
1064 uint64_t ui64Key = 0;\r
1065 uint32_t cuid;\r
1066 struct Crypto1State mpcs = {0, 0};\r
1067 struct Crypto1State *pcs;\r
1068 pcs = &mpcs;\r
1069\r
1070 // variables\r
1071 byte_t dataoutbuf[16];\r
ab8b654e 1072 byte_t dataoutbuf2[16];\r
1c611bbd 1073 uint8_t uid[10];\r
8556b852 1074\r
8556b852
M
1075 LED_A_ON();\r
1076 LED_B_OFF();\r
1077 LED_C_OFF();\r
09ffd16e 1078 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
7906cb41 1079\r
09ffd16e 1080 clear_trace();\r
1081 set_tracing(false);\r
7906cb41 1082\r
baeaf579 1083 bool isOK = true;\r
1084\r
c04a4b60 1085 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
baeaf579 1086 isOK = false;\r
1087 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
1088 }\r
7906cb41 1089\r
baeaf579 1090 for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {\r
1091 ui64Key = emlGetKey(sectorNo, keyType);\r
1092 if (sectorNo == 0){\r
1093 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
1094 isOK = false;\r
1095 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);\r
8556b852 1096 break;\r
baeaf579 1097 }\r
1098 } else {\r
1099 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {\r
1100 isOK = false;\r
1101 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);\r
8556b852 1102 break;\r
baeaf579 1103 }\r
1104 }\r
7906cb41 1105\r
baeaf579 1106 for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {\r
1107 if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {\r
1108 isOK = false;\r
1109 if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);\r
ab8b654e
M
1110 break;\r
1111 };\r
baeaf579 1112 if (isOK) {\r
1113 if (blockNo < NumBlocksPerSector(sectorNo) - 1) {\r
1114 emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
1115 } else { // sector trailer, keep the keys, set only the AC\r
1116 emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
1117 memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);\r
1118 emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);\r
1119 }\r
1120 }\r
8556b852
M
1121 }\r
1122\r
baeaf579 1123 }\r
1124\r
1125 if(mifare_classic_halt(pcs, cuid)) {\r
1126 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
1127 };\r
8556b852
M
1128\r
1129 // ----------------------------- crypto1 destroy\r
1130 crypto1_destroy(pcs);\r
ab8b654e
M
1131\r
1132 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1133 LEDsoff();\r
7906cb41 1134\r
8556b852
M
1135 if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");\r
1136\r
8556b852
M
1137}\r
1138\r
0675f200
M
1139\r
1140//-----------------------------------------------------------------------------\r
1141// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)\r
7906cb41 1142//\r
0675f200 1143//-----------------------------------------------------------------------------\r
3a05a1e7
OM
1144\r
1145static bool isBlockTrailer(int blockN) {\r
1146 if (blockN >= 0 && blockN < 128) {\r
1147 return ((blockN & 0x03) == 0x03);\r
1148 }\r
1149 if (blockN >= 128 && blockN <= 256) {\r
1150 return ((blockN & 0x0F) == 0x0F);\r
1151 }\r
44964fd1 1152 return false;\r
3a05a1e7
OM
1153}\r
1154\r
1155void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1156 // var\r
1157 byte_t isOK = 0;\r
1158 uint32_t numBlocks = arg0;\r
1159 // cmdParams:\r
1160 // bit 0 - wipe gen1a\r
1161 // bit 1 - fill card with default data\r
1162 // bit 2 - gen1a = 0, gen1b = 1\r
1163 uint8_t cmdParams = arg1;\r
1164 bool needWipe = cmdParams & 0x01;\r
1165 bool needFill = cmdParams & 0x02;\r
1166 bool gen1b = cmdParams & 0x04;\r
1167 \r
1168 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1169 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
1170 \r
1171 uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF};\r
1172 uint8_t block1[16] = {0x00};\r
1173 uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\r
1174 uint8_t d_block[18] = {0x00};\r
1175 \r
1176 // card commands\r
1177 uint8_t wupC1[] = { 0x40 };\r
1178 uint8_t wupC2[] = { 0x43 };\r
1179 uint8_t wipeC[] = { 0x41 };\r
1180 \r
1181 // iso14443 setup\r
1182 LED_A_ON();\r
1183 LED_B_OFF();\r
1184 LED_C_OFF();\r
1185 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1186\r
1187 // tracing\r
1188 clear_trace();\r
1189 set_tracing(true);\r
1190 \r
1191 while (true){\r
1192 // wipe\r
1193 if (needWipe){\r
1194 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1195 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1196 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1197 break;\r
1198 };\r
1199\r
1200 ReaderTransmit(wipeC, sizeof(wipeC), NULL);\r
1201 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1202 if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
1203 break;\r
1204 };\r
1205\r
1206 if(mifare_classic_halt(NULL, 0)) {\r
1207 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1208 };\r
1209 };\r
1210 \r
1211 // put default data\r
1212 if (needFill){\r
1213 // select commands\r
1214 ReaderTransmitBitsPar(wupC1, 7, 0, NULL);\r
1215\r
1216 // 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
1217 if (!gen1b) { \r
1218\r
1219 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1220 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1221 break;\r
1222 };\r
1223\r
1224 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1225 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1226 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
1227 break;\r
1228 };\r
1229 }\r
1230\r
1231 // send blocks command\r
1232 for (int blockNo = 0; blockNo < numBlocks; blockNo++) {\r
1233 if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {\r
1234 if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
1235 break;\r
1236 };\r
1237 \r
1238 // check type of block and add crc\r
1239 if (!isBlockTrailer(blockNo)){\r
1240 memcpy(d_block, block1, 16);\r
1241 } else {\r
1242 memcpy(d_block, blockK, 16);\r
1243 }\r
1244 if (blockNo == 0) {\r
1245 memcpy(d_block, block0, 16);\r
1246 }\r
1247 AppendCrc14443a(d_block, 16);\r
1248\r
1249 // send write command\r
1250 ReaderTransmit(d_block, sizeof(d_block), NULL);\r
1251 if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {\r
1252 if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
1253 break;\r
1254 };\r
1255 }\r
1256 \r
1257 // halt\r
1258 // do no issue halt command for gen1b \r
1259 if (!gen1b) {\r
1260 if (mifare_classic_halt(NULL, 0)) {\r
1261 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1262 break;\r
1263 }\r
1264 }\r
1265 }\r
1266 break;\r
1267 } \r
1268\r
1269 // send USB response\r
1270 LED_B_ON();\r
1271 cmd_send(CMD_ACK,isOK,0,0,NULL,0);\r
1272 LED_B_OFF();\r
1273 \r
1274 // reset fpga\r
1275 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1276 LEDsoff();\r
1277 \r
1278 return;\r
1279}\r
1280\r
0675f200 1281void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
7906cb41 1282\r
0675f200
M
1283 // params\r
1284 uint8_t needWipe = arg0;\r
208a0166
M
1285 // bit 0 - need get UID\r
1286 // bit 1 - need wupC\r
1287 // bit 2 - need HALT after sequence\r
1288 // bit 3 - need init FPGA and field before sequence\r
1289 // bit 4 - need reset FPGA and LED\r
7906cb41 1290 // bit 6 - gen1b backdoor type\r
208a0166 1291 uint8_t workFlags = arg1;\r
0675f200 1292 uint8_t blockNo = arg2;\r
7906cb41 1293\r
0675f200 1294 // card commands\r
7906cb41
F
1295 uint8_t wupC1[] = { 0x40 };\r
1296 uint8_t wupC2[] = { 0x43 };\r
1297 uint8_t wipeC[] = { 0x41 };\r
1298\r
0675f200
M
1299 // variables\r
1300 byte_t isOK = 0;\r
3fe4ff4f 1301 uint8_t uid[10] = {0x00};\r
1302 uint8_t d_block[18] = {0x00};\r
0675f200 1303 uint32_t cuid;\r
7906cb41 1304\r
f71f4deb 1305 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1306 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
6a1f2d82 1307\r
3fe4ff4f 1308 // reset FPGA and LED\r
208a0166 1309 if (workFlags & 0x08) {\r
208a0166
M
1310 LED_A_ON();\r
1311 LED_B_OFF();\r
1312 LED_C_OFF();\r
09ffd16e 1313 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
7906cb41 1314\r
3000dc4e 1315 clear_trace();\r
de77d4ac 1316 set_tracing(true);\r
208a0166 1317 }\r
0675f200
M
1318\r
1319 while (true) {\r
3fe4ff4f 1320\r
0675f200 1321 // get UID from chip\r
208a0166 1322 if (workFlags & 0x01) {\r
c04a4b60 1323 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
0675f200 1324 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
3a05a1e7
OM
1325 // Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work.\r
1326 //break;\r
7906cb41 1327 };\r
0675f200 1328\r
7906cb41
F
1329 if(mifare_classic_halt(NULL, cuid)) {\r
1330 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1331 // Continue, some magic tags misbehavies and send an answer to it.\r
3a05a1e7 1332 // break;\r
7906cb41 1333 };\r
0675f200 1334 };\r
7906cb41 1335\r
0675f200 1336 // reset chip\r
7906cb41
F
1337 // Wipe command don't work with gen1b\r
1338 if (needWipe && !(workFlags & 0x40)){\r
6a1f2d82 1339 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1340 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1341 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1342 break;\r
1343 };\r
1344\r
9492e0b0 1345 ReaderTransmit(wipeC, sizeof(wipeC), NULL);\r
6a1f2d82 1346 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1347 if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
1348 break;\r
1349 };\r
1350\r
3a05a1e7 1351 if(mifare_classic_halt(NULL, 0)) {\r
7906cb41
F
1352 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1353 // Continue, some magic tags misbehavies and send an answer to it.\r
1354 // break;\r
0675f200 1355 };\r
7906cb41 1356 };\r
0675f200 1357\r
545a1f38 1358 // write block\r
208a0166 1359 if (workFlags & 0x02) {\r
6a1f2d82 1360 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
0675f200 1361\r
7906cb41
F
1362 // 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
1363 if (!(workFlags & 0x40)) {\r
1364\r
1365 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1366 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1367 break;\r
1368 };\r
1369\r
1370 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1371 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1372 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
1373 break;\r
1374 };\r
1375 }\r
208a0166 1376 }\r
0675f200 1377\r
6a1f2d82 1378 if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1379 if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
1380 break;\r
1381 };\r
7906cb41 1382\r
0675f200
M
1383 memcpy(d_block, datain, 16);\r
1384 AppendCrc14443a(d_block, 16);\r
7906cb41 1385\r
9492e0b0 1386 ReaderTransmit(d_block, sizeof(d_block), NULL);\r
6a1f2d82 1387 if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {\r
0675f200
M
1388 if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
1389 break;\r
7906cb41
F
1390 };\r
1391\r
208a0166 1392 if (workFlags & 0x04) {\r
7906cb41
F
1393 // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
1394 if (!(workFlags & 0x40)) {\r
3a05a1e7 1395 if (mifare_classic_halt(NULL, 0)) {\r
7906cb41
F
1396 if (MF_DBGLEVEL > 2) Dbprintf("Halt error");\r
1397 // Continue, some magic tags misbehavies and send an answer to it.\r
1398 // break;\r
1399 }\r
1400 }\r
208a0166 1401 }\r
7906cb41 1402\r
0675f200
M
1403 isOK = 1;\r
1404 break;\r
1405 }\r
7906cb41 1406\r
0675f200 1407 LED_B_ON();\r
baeaf579 1408 cmd_send(CMD_ACK,isOK,0,0,uid,4);\r
0675f200
M
1409 LED_B_OFF();\r
1410\r
545a1f38 1411 if ((workFlags & 0x10) || (!isOK)) {\r
208a0166
M
1412 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1413 LEDsoff();\r
1414 }\r
0675f200 1415}\r
545a1f38 1416\r
baeaf579 1417\r
545a1f38 1418void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
7906cb41
F
1419\r
1420 // params\r
545a1f38
M
1421 // bit 1 - need wupC\r
1422 // bit 2 - need HALT after sequence\r
1423 // bit 3 - need init FPGA and field before sequence\r
1424 // bit 4 - need reset FPGA and LED\r
c89274cc 1425 // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)\r
7906cb41 1426 // bit 6 - gen1b backdoor type\r
545a1f38
M
1427 uint8_t workFlags = arg0;\r
1428 uint8_t blockNo = arg2;\r
7906cb41 1429\r
545a1f38 1430 // card commands\r
7906cb41
F
1431 uint8_t wupC1[] = { 0x40 };\r
1432 uint8_t wupC2[] = { 0x43 };\r
1433\r
545a1f38
M
1434 // variables\r
1435 byte_t isOK = 0;\r
3fe4ff4f 1436 uint8_t data[18] = {0x00};\r
545a1f38 1437 uint32_t cuid = 0;\r
7906cb41 1438\r
f71f4deb 1439 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1440 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
7906cb41 1441\r
545a1f38 1442 if (workFlags & 0x08) {\r
545a1f38
M
1443 LED_A_ON();\r
1444 LED_B_OFF();\r
1445 LED_C_OFF();\r
09ffd16e 1446 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1447\r
3000dc4e 1448 clear_trace();\r
de77d4ac 1449 set_tracing(true);\r
545a1f38
M
1450 }\r
1451\r
1452 while (true) {\r
1453 if (workFlags & 0x02) {\r
7bc95e2e 1454 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
6a1f2d82 1455 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
545a1f38
M
1456 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1457 break;\r
7906cb41
F
1458 };\r
1459 // do no issue for gen1b magic tag\r
1460 if (!(workFlags & 0x40)) {\r
9492e0b0 1461 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
6a1f2d82 1462 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
545a1f38
M
1463 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
1464 break;\r
1465 };\r
1466 }\r
7906cb41 1467 }\r
545a1f38
M
1468\r
1469 // read block\r
6a1f2d82 1470 if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {\r
545a1f38
M
1471 if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
1472 break;\r
1473 };\r
1474 memcpy(data, receivedAnswer, 18);\r
7906cb41 1475\r
545a1f38 1476 if (workFlags & 0x04) {\r
7906cb41
F
1477 // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
1478 if (!(workFlags & 0x40)) {\r
1479 if (mifare_classic_halt(NULL, cuid)) {\r
1480 if (MF_DBGLEVEL > 1) Dbprintf("Halt error");\r
1481 // Continue, some magic tags misbehavies and send an answer to it.\r
1482 // break;\r
1483 }\r
1484 }\r
545a1f38 1485 }\r
7906cb41 1486\r
545a1f38
M
1487 isOK = 1;\r
1488 break;\r
1489 }\r
7906cb41 1490\r
545a1f38 1491 LED_B_ON();\r
c89274cc
CY
1492 if (workFlags & 0x20) {\r
1493 if (isOK)\r
1494 memcpy(datain, data, 18);\r
1495 }\r
1496 else\r
1497 cmd_send(CMD_ACK,isOK,0,0,data,18);\r
545a1f38
M
1498 LED_B_OFF();\r
1499\r
1500 if ((workFlags & 0x10) || (!isOK)) {\r
545a1f38
M
1501 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1502 LEDsoff();\r
1503 }\r
1504}\r
1505\r
3fe4ff4f 1506void MifareCIdent(){\r
7906cb41 1507\r
3fe4ff4f 1508 // card commands\r
7906cb41
F
1509 uint8_t wupC1[] = { 0x40 };\r
1510 uint8_t wupC2[] = { 0x43 };\r
1511\r
3fe4ff4f 1512 // variables\r
7906cb41
F
1513 byte_t isOK = 0;\r
1514\r
f71f4deb 1515 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1516 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
8bdb6043
OM
1517 \r
1518 LED_A_ON();\r
1519 LED_B_OFF();\r
1520 LED_C_OFF();\r
8bdb6043
OM
1521 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1522\r
1523 clear_trace();\r
1524 set_tracing(true); \r
3fe4ff4f 1525\r
1526 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
7906cb41
F
1527 if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
1528 isOK = 2;\r
3fe4ff4f 1529\r
7906cb41
F
1530 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1531 if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
1532 isOK = 1;\r
1533 };\r
3fe4ff4f 1534 };\r
1535\r
7906cb41
F
1536 // From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it.\r
1537 mifare_classic_halt(NULL, 0);\r
8bdb6043
OM
1538 \r
1539 LED_B_ON();\r
3fe4ff4f 1540 cmd_send(CMD_ACK,isOK,0,0,0,0);\r
8bdb6043
OM
1541 LED_B_OFF();\r
1542\r
1543 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1544 LEDsoff(); \r
3fe4ff4f 1545}\r
1546\r
09ffd16e 1547//\r
3fe4ff4f 1548// DESFIRE\r
1549//\r
a631936e 1550\r
1551void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){\r
1552\r
1553 byte_t dataout[11] = {0x00};\r
1554 uint8_t uid[10] = {0x00};\r
1555 uint32_t cuid;\r
7906cb41 1556\r
a631936e 1557 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
09ffd16e 1558 clear_trace();\r
a631936e 1559\r
c04a4b60 1560 int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);\r
a631936e 1561 if(!len) {\r
8258f409 1562 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
1563 OnError(1);\r
a631936e 1564 return;\r
1565 };\r
1566\r
1567 if(mifare_desfire_des_auth1(cuid, dataout)){\r
8258f409 1568 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");\r
1569 OnError(4);\r
a631936e 1570 return;\r
1571 }\r
1572\r
1573 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
a631936e 1574 cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));\r
1575}\r
1576\r
1577void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){\r
1578\r
1579 uint32_t cuid = arg0;\r
1580 uint8_t key[16] = {0x00};\r
1581 byte_t isOK = 0;\r
1582 byte_t dataout[12] = {0x00};\r
7906cb41 1583\r
a631936e 1584 memcpy(key, datain, 16);\r
7906cb41 1585\r
a631936e 1586 isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
7906cb41 1587\r
a631936e 1588 if( isOK) {\r
7906cb41 1589 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");\r
4973f23d 1590 OnError(4);\r
a631936e 1591 return;\r
1592 }\r
1593\r
4973f23d 1594 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
a631936e 1595\r
1596 cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
1597 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1598 LEDsoff();\r
3000dc4e 1599}\r
f168b263 1600\r
1601void OnSuccess(){\r
1602 pcb_blocknum = 0;\r
1603 ReaderTransmit(deselect_cmd, 3 , NULL);\r
1604 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1605 LEDsoff();\r
1606}\r
1607\r
1608void OnError(uint8_t reason){\r
1609 pcb_blocknum = 0;\r
1610 ReaderTransmit(deselect_cmd, 3 , NULL);\r
1611 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1612 cmd_send(CMD_ACK,0,reason,0,0,0);\r
1613 LEDsoff();\r
1614}\r
Impressum, Datenschutz