]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/mifarecmd.c
Code cleanup (#616)
[proxmark3-svn] / armsrc / mifarecmd.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------\r
2// Merlok - June 2011, 2012\r
3// Gerhard de Koning Gans - May 2008\r
4// Hagen Fritsch - June 2010\r
5// Midnitesnake - Dec 2013\r
6// Andy Davies - Apr 2014\r
7// Iceman - May 2014\r
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
17\r
18#include "apps.h"\r
19#include "util.h"\r
20#include "parity.h"\r
21#include "crc.h"\r
22\r
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
26// the block number for the ISO14443-4 PCB\r
27static uint8_t pcb_blocknum = 0;\r
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
31//-----------------------------------------------------------------------------\r
32// Select, Authenticate, Read a MIFARE tag.\r
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
42\r
43 // variables\r
44 byte_t isOK = 0;\r
45 byte_t dataoutbuf[16];\r
46 uint8_t uid[10];\r
47 uint32_t cuid;\r
48 struct Crypto1State mpcs = {0, 0};\r
49 struct Crypto1State *pcs;\r
50 pcs = &mpcs;\r
51\r
52 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
53\r
54 clear_trace();\r
55\r
56 LED_A_ON();\r
57 LED_B_OFF();\r
58 LED_C_OFF();\r
59\r
60 while (true) {\r
61 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
62 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
63 break;\r
64 };\r
65\r
66 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
67 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
68 break;\r
69 };\r
70\r
71 if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {\r
72 if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r
73 break;\r
74 };\r
75\r
76 if(mifare_classic_halt(pcs, cuid)) {\r
77 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
78 break;\r
79 };\r
80\r
81 isOK = 1;\r
82 break;\r
83 }\r
84\r
85 // ----------------------------- crypto1 destroy\r
86 crypto1_destroy(pcs);\r
87\r
88 if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
89\r
90 LED_B_ON();\r
91 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);\r
92 LED_B_OFF();\r
93\r
94 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
95 LEDsoff();\r
96}\r
97\r
98void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){\r
99\r
100 bool turnOffField = (arg0 == 1);\r
101\r
102 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
103\r
104 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
105\r
106 clear_trace();\r
107\r
108 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {\r
109 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
110 OnError(0);\r
111 return;\r
112 };\r
113\r
114 if(!mifare_ultra_auth(keybytes)){\r
115 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed");\r
116 OnError(1);\r
117 return;\r
118 }\r
119\r
120 if (turnOffField) {\r
121 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
122 LEDsoff();\r
123 }\r
124 cmd_send(CMD_ACK,1,0,0,0,0);\r
125}\r
126\r
127// Arg0 = BlockNo,\r
128// Arg1 = UsePwd bool\r
129// datain = PWD bytes,\r
130void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
131{\r
132 uint8_t blockNo = arg0;\r
133 byte_t dataout[16] = {0x00};\r
134 bool useKey = (arg1 == 1); //UL_C\r
135 bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
136\r
137 LEDsoff();\r
138 LED_A_ON();\r
139 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
140\r
141 clear_trace();\r
142\r
143 int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);\r
144 if(!len) {\r
145 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);\r
146 OnError(1);\r
147 return;\r
148 }\r
149\r
150 // UL-C authentication\r
151 if ( useKey ) {\r
152 uint8_t key[16] = {0x00};\r
153 memcpy(key, datain, sizeof(key) );\r
154\r
155 if ( !mifare_ultra_auth(key) ) {\r
156 OnError(1);\r
157 return;\r
158 }\r
159 }\r
160\r
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
166 if (!mifare_ul_ev1_auth(pwd, pack)) {\r
167 OnError(1);\r
168 return;\r
169 }\r
170 }\r
171\r
172 if( mifare_ultra_readblock(blockNo, dataout) ) {\r
173 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");\r
174 OnError(2);\r
175 return;\r
176 }\r
177\r
178 if( mifare_ultra_halt() ) {\r
179 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
180 OnError(3);\r
181 return;\r
182 }\r
183\r
184 cmd_send(CMD_ACK,1,0,0,dataout,16);\r
185 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
186 LEDsoff();\r
187}\r
188\r
189//-----------------------------------------------------------------------------\r
190// Select, Authenticate, Read a MIFARE tag.\r
191// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)\r
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
200\r
201 // variables\r
202 byte_t isOK = 0;\r
203 byte_t dataoutbuf[16 * 16];\r
204 uint8_t uid[10];\r
205 uint32_t cuid;\r
206 struct Crypto1State mpcs = {0, 0};\r
207 struct Crypto1State *pcs;\r
208 pcs = &mpcs;\r
209\r
210 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
211\r
212 clear_trace();\r
213\r
214 LED_A_ON();\r
215 LED_B_OFF();\r
216 LED_C_OFF();\r
217\r
218 isOK = 1;\r
219 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
220 isOK = 0;\r
221 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
222 }\r
223\r
224\r
225 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
226 isOK = 0;\r
227 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
228 }\r
229\r
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
234 break;\r
235 }\r
236 }\r
237\r
238 if(mifare_classic_halt(pcs, cuid)) {\r
239 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
240 }\r
241\r
242 // ----------------------------- crypto1 destroy\r
243 crypto1_destroy(pcs);\r
244\r
245 if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");\r
246\r
247 LED_B_ON();\r
248 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));\r
249 LED_B_OFF();\r
250\r
251 // Thats it...\r
252 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
253 LEDsoff();\r
254}\r
255\r
256// arg0 = blockNo (start)\r
257// arg1 = Pages (number of blocks)\r
258// arg2 = useKey\r
259// datain = KEY bytes\r
260void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
261{\r
262 LEDsoff();\r
263 LED_A_ON();\r
264 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
265\r
266 // free eventually allocated BigBuf memory\r
267 BigBuf_free();\r
268 clear_trace();\r
269\r
270 // params\r
271 uint8_t blockNo = arg0;\r
272 uint16_t blocks = arg1;\r
273 bool useKey = (arg2 == 1); //UL_C\r
274 bool usePwd = (arg2 == 2); //UL_EV1/NTAG\r
275 uint32_t countblocks = 0;\r
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
282\r
283 int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);\r
284 if (!len) {\r
285 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);\r
286 OnError(1);\r
287 return;\r
288 }\r
289\r
290 // UL-C authentication\r
291 if ( useKey ) {\r
292 uint8_t key[16] = {0x00};\r
293 memcpy(key, datain, sizeof(key) );\r
294\r
295 if ( !mifare_ultra_auth(key) ) {\r
296 OnError(1);\r
297 return;\r
298 }\r
299 }\r
300\r
301 // UL-EV1 / NTAG authentication\r
302 if (usePwd) {\r
303 uint8_t pwd[4] = {0x00};\r
304 memcpy(pwd, datain, sizeof(pwd));\r
305 uint8_t pack[4] = {0,0,0,0};\r
306\r
307 if (!mifare_ul_ev1_auth(pwd, pack)){\r
308 OnError(1);\r
309 return;\r
310 }\r
311 }\r
312\r
313 for (int i = 0; i < blocks; i++){\r
314 if ((i*4) + 4 >= CARD_MEMORY_SIZE) {\r
315 Dbprintf("Data exceeds buffer!!");\r
316 break;\r
317 }\r
318\r
319 len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
320\r
321 if (len) {\r
322 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);\r
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
331 } else {\r
332 countblocks++;\r
333 }\r
334 }\r
335\r
336 len = mifare_ultra_halt();\r
337 if (len) {\r
338 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
339 OnError(3);\r
340 return;\r
341 }\r
342\r
343 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);\r
344\r
345 countblocks *= 4;\r
346\r
347 cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);\r
348 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
349 LEDsoff();\r
350 BigBuf_free();\r
351}\r
352\r
353//-----------------------------------------------------------------------------\r
354// Select, Authenticate, Write a MIFARE tag.\r
355// read block\r
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
367\r
368 // variables\r
369 byte_t isOK = 0;\r
370 uint8_t uid[10];\r
371 uint32_t cuid;\r
372 struct Crypto1State mpcs = {0, 0};\r
373 struct Crypto1State *pcs;\r
374 pcs = &mpcs;\r
375\r
376 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
377\r
378 clear_trace();\r
379\r
380 LED_A_ON();\r
381 LED_B_OFF();\r
382 LED_C_OFF();\r
383\r
384 while (true) {\r
385 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
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
394\r
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
404\r
405 isOK = 1;\r
406 break;\r
407 }\r
408\r
409 // ----------------------------- crypto1 destroy\r
410 crypto1_destroy(pcs);\r
411\r
412 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
413\r
414 LED_B_ON();\r
415 cmd_send(CMD_ACK,isOK,0,0,0,0);\r
416 LED_B_OFF();\r
417\r
418\r
419 // Thats it...\r
420 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
421 LEDsoff();\r
422}\r
423\r
424/* // Command not needed but left for future testing\r
425void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)\r
426{\r
427 uint8_t blockNo = arg0;\r
428 byte_t blockdata[16] = {0x00};\r
429\r
430 memcpy(blockdata, datain, 16);\r
431\r
432 uint8_t uid[10] = {0x00};\r
433\r
434 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
435\r
436 clear_trace();\r
437 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
438\r
439 if(!iso14443a_select_card(uid, NULL, NULL, true, 0)) {\r
440 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
441 OnError(0);\r
442 return;\r
443 };\r
444\r
445 if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {\r
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
461}\r
462*/\r
463\r
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
470void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
471{\r
472 uint8_t blockNo = arg0;\r
473 bool useKey = (arg1 == 1); //UL_C\r
474 bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
475 byte_t blockdata[4] = {0x00};\r
476\r
477 memcpy(blockdata, datain,4);\r
478\r
479 LEDsoff();\r
480 LED_A_ON();\r
481 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
482\r
483 clear_trace();\r
484\r
485 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {\r
486 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
487 OnError(0);\r
488 return;\r
489 };\r
490\r
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
501\r
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
513 if(mifare_ultra_writeblock(blockNo, blockdata)) {\r
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
533\r
534 uint8_t pwd[16] = {0x00};\r
535 byte_t blockdata[4] = {0x00};\r
536\r
537 memcpy(pwd, datain, 16);\r
538\r
539 LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
540 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
541\r
542 clear_trace();\r
543\r
544 if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {\r
545 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
546 OnError(0);\r
547 return;\r
548 };\r
549\r
550 blockdata[0] = pwd[7];\r
551 blockdata[1] = pwd[6];\r
552 blockdata[2] = pwd[5];\r
553 blockdata[3] = pwd[4];\r
554 if(mifare_ultra_writeblock( 44, blockdata)) {\r
555 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
556 OnError(44);\r
557 return;\r
558 };\r
559\r
560 blockdata[0] = pwd[3];\r
561 blockdata[1] = pwd[2];\r
562 blockdata[2] = pwd[1];\r
563 blockdata[3] = pwd[0];\r
564 if(mifare_ultra_writeblock( 45, blockdata)) {\r
565 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
566 OnError(45);\r
567 return;\r
568 };\r
569\r
570 blockdata[0] = pwd[15];\r
571 blockdata[1] = pwd[14];\r
572 blockdata[2] = pwd[13];\r
573 blockdata[3] = pwd[12];\r
574 if(mifare_ultra_writeblock( 46, blockdata)) {\r
575 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
576 OnError(46);\r
577 return;\r
578 };\r
579\r
580 blockdata[0] = pwd[11];\r
581 blockdata[1] = pwd[10];\r
582 blockdata[2] = pwd[9];\r
583 blockdata[3] = pwd[8];\r
584 if(mifare_ultra_writeblock( 47, blockdata)) {\r
585 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
586 OnError(47);\r
587 return;\r
588 };\r
589\r
590 if(mifare_ultra_halt()) {\r
591 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
592 OnError(0);\r
593 return;\r
594 };\r
595\r
596 cmd_send(CMD_ACK,1,0,0,0,0);\r
597 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
598 LEDsoff();\r
599}\r
600\r
601// Return 1 if the nonce is invalid else return 0\r
602int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {\r
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
606}\r
607\r
608\r
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
612// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on\r
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
630\r
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
639\r
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
648\r
649 LED_C_ON();\r
650\r
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
663 iso14a_card_select_t card_info;\r
664 if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {\r
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
674 have_uid = true;\r
675 } else { // no need for anticollision. We can directly select the card\r
676 if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {\r
677 if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)");\r
678 continue;\r
679 }\r
680 }\r
681\r
682 if (slow) {\r
683 timeout = GetCountSspClk() + HARDNESTED_PRE_AUTHENTICATION_LEADTIME;\r
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
699\r
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
703\r
704 timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT;\r
705 \r
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
719\r
720 }\r
721\r
722 LED_C_OFF();\r
723\r
724 crypto1_destroy(pcs);\r
725\r
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
739//-----------------------------------------------------------------------------\r
740// MIFARE nested authentication.\r
741//\r
742//-----------------------------------------------------------------------------\r
743void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain)\r
744{\r
745 // params\r
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
750 uint64_t ui64Key = 0;\r
751\r
752 ui64Key = bytes_to_num(datain, 6);\r
753\r
754 // variables\r
755 uint16_t rtr, i, j, len;\r
756 uint16_t davg;\r
757 static uint16_t dmin, dmax;\r
758 uint8_t uid[10];\r
759 uint32_t cuid, nt1, nt2, nttmp, nttest, ks1;\r
760 uint8_t par[1];\r
761 uint32_t target_nt[2], target_ks[2];\r
762\r
763 uint8_t par_array[4];\r
764 uint16_t ncount = 0;\r
765 struct Crypto1State mpcs = {0, 0};\r
766 struct Crypto1State *pcs;\r
767 pcs = &mpcs;\r
768 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
769\r
770 uint32_t auth1_time, auth2_time;\r
771 static uint16_t delta_time;\r
772\r
773 LED_A_ON();\r
774 LED_C_OFF();\r
775 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
776\r
777 // free eventually allocated BigBuf memory\r
778 BigBuf_free();\r
779\r
780 if (calibrate) clear_trace();\r
781 set_tracing(true);\r
782\r
783 // statistics on nonce distance\r
784 int16_t isOK = 0;\r
785 #define NESTED_MAX_TRIES 12\r
786 uint16_t unsuccessfull_tries = 0;\r
787 if (calibrate) { // for first call only. Otherwise reuse previous calibration\r
788 LED_B_ON();\r
789 WDT_HIT();\r
790\r
791 davg = dmax = 0;\r
792 dmin = 2000;\r
793 delta_time = 0;\r
794\r
795 for (rtr = 0; rtr < 17; rtr++) {\r
796\r
797 // Test if the action was cancelled\r
798 if(BUTTON_PRESS()) {\r
799 isOK = -2;\r
800 break;\r
801 }\r
802\r
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
810 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
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
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
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
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
855 }\r
856 }\r
857\r
858 davg = (davg + (rtr - 1)/2) / (rtr - 1);\r
859\r
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
861\r
862 dmin = davg - 2;\r
863 dmax = davg + 2;\r
864\r
865 LED_B_OFF();\r
866\r
867 }\r
868 // -------------------------------------------------------------------------------------------------\r
869\r
870 LED_C_ON();\r
871\r
872 // get crypted nonces for target sector\r
873 for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces\r
874\r
875 target_nt[i] = 0;\r
876 while(target_nt[i] == 0) { // continue until we have an unambiguous nonce\r
877\r
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
883\r
884 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
885 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");\r
886 continue;\r
887 };\r
888\r
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
894\r
895 // nested authentication\r
896 auth2_time = auth1_time + delta_time;\r
897 len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);\r
898 if (len != 4) {\r
899 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);\r
900 continue;\r
901 };\r
902\r
903 nt2 = bytes_to_num(receivedAnswer, 4);\r
904 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]);\r
905\r
906 // Parity validity check\r
907 for (j = 0; j < 4; j++) {\r
908 par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));\r
909 }\r
910\r
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
929 break;\r
930 }\r
931 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j);\r
932 }\r
933 }\r
934 if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1);\r
935 }\r
936 }\r
937\r
938 LED_C_OFF();\r
939\r
940 // ----------------------------- crypto1 destroy\r
941 crypto1_destroy(pcs);\r
942\r
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
949\r
950 LED_B_ON();\r
951 cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));\r
952 LED_B_OFF();\r
953\r
954 if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");\r
955\r
956 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
957 LEDsoff();\r
958}\r
959\r
960//-----------------------------------------------------------------------------\r
961// MIFARE check keys. key count up to 85.\r
962//\r
963//-----------------------------------------------------------------------------\r
964void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
965{\r
966 uint8_t blockNo = arg0 & 0xff;\r
967 uint8_t keyType = (arg0 >> 8) & 0xff;\r
968 bool clearTrace = arg1 & 0x01;\r
969 bool multisectorCheck = arg1 & 0x02;\r
970 uint8_t set14aTimeout = (arg1 >> 8) & 0xff;\r
971 uint8_t keyCount = arg2;\r
972\r
973 // clear debug level\r
974 int OLD_MF_DBGLEVEL = MF_DBGLEVEL;\r
975 MF_DBGLEVEL = MF_DBG_NONE;\r
976\r
977 LED_A_ON();\r
978 LED_B_OFF();\r
979 LED_C_OFF();\r
980 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
981\r
982 if (clearTrace) clear_trace();\r
983 set_tracing(true);\r
984\r
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
993\r
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
999 }\r
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
1009 }\r
1010 LED_B_OFF();\r
1011 }\r
1012\r
1013 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1014 LEDsoff();\r
1015\r
1016 // restore debug level\r
1017 MF_DBGLEVEL = OLD_MF_DBGLEVEL;\r
1018}\r
1019\r
1020//-----------------------------------------------------------------------------\r
1021// MIFARE commands set debug level\r
1022//\r
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
1031//\r
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
1035//-----------------------------------------------------------------------------\r
1036\r
1037void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1038 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
1039 emlClearMem();\r
1040}\r
1041\r
1042void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1043 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
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
1048 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);\r
1049 byte_t buf[USB_CMD_DATA_SIZE];\r
1050 emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4)\r
1051\r
1052 LED_B_ON();\r
1053 cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE);\r
1054 LED_B_OFF();\r
1055}\r
1056\r
1057//-----------------------------------------------------------------------------\r
1058// Load a card into the emulator memory\r
1059//\r
1060//-----------------------------------------------------------------------------\r
1061void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1062 uint8_t numSectors = arg0;\r
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
1072 byte_t dataoutbuf2[16];\r
1073 uint8_t uid[10];\r
1074\r
1075 LED_A_ON();\r
1076 LED_B_OFF();\r
1077 LED_C_OFF();\r
1078 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1079\r
1080 clear_trace();\r
1081 set_tracing(false);\r
1082\r
1083 bool isOK = true;\r
1084\r
1085 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
1086 isOK = false;\r
1087 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
1088 }\r
1089\r
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
1096 break;\r
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
1102 break;\r
1103 }\r
1104 }\r
1105\r
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
1110 break;\r
1111 };\r
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
1121 }\r
1122\r
1123 }\r
1124\r
1125 if(mifare_classic_halt(pcs, cuid)) {\r
1126 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
1127 };\r
1128\r
1129 // ----------------------------- crypto1 destroy\r
1130 crypto1_destroy(pcs);\r
1131\r
1132 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1133 LEDsoff();\r
1134\r
1135 if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");\r
1136\r
1137}\r
1138\r
1139\r
1140//-----------------------------------------------------------------------------\r
1141// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)\r
1142//\r
1143//-----------------------------------------------------------------------------\r
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
1152 return false;\r
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
1281void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1282\r
1283 // params\r
1284 uint8_t needWipe = arg0;\r
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
1290 // bit 6 - gen1b backdoor type\r
1291 uint8_t workFlags = arg1;\r
1292 uint8_t blockNo = arg2;\r
1293\r
1294 // card commands\r
1295 uint8_t wupC1[] = { 0x40 };\r
1296 uint8_t wupC2[] = { 0x43 };\r
1297 uint8_t wipeC[] = { 0x41 };\r
1298\r
1299 // variables\r
1300 byte_t isOK = 0;\r
1301 uint8_t uid[10] = {0x00};\r
1302 uint8_t d_block[18] = {0x00};\r
1303 uint32_t cuid;\r
1304\r
1305 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1306 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
1307\r
1308 // reset FPGA and LED\r
1309 if (workFlags & 0x08) {\r
1310 LED_A_ON();\r
1311 LED_B_OFF();\r
1312 LED_C_OFF();\r
1313 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1314\r
1315 clear_trace();\r
1316 set_tracing(true);\r
1317 }\r
1318\r
1319 while (true) {\r
1320\r
1321 // get UID from chip\r
1322 if (workFlags & 0x01) {\r
1323 if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {\r
1324 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
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
1327 };\r
1328\r
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
1332 // break;\r
1333 };\r
1334 };\r
1335\r
1336 // reset chip\r
1337 // Wipe command don't work with gen1b\r
1338 if (needWipe && !(workFlags & 0x40)){\r
1339 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1340 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1341 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1342 break;\r
1343 };\r
1344\r
1345 ReaderTransmit(wipeC, sizeof(wipeC), NULL);\r
1346 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1347 if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
1348 break;\r
1349 };\r
1350\r
1351 if(mifare_classic_halt(NULL, 0)) {\r
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
1355 };\r
1356 };\r
1357\r
1358 // write block\r
1359 if (workFlags & 0x02) {\r
1360 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1361\r
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
1376 }\r
1377\r
1378 if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {\r
1379 if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
1380 break;\r
1381 };\r
1382\r
1383 memcpy(d_block, datain, 16);\r
1384 AppendCrc14443a(d_block, 16);\r
1385\r
1386 ReaderTransmit(d_block, sizeof(d_block), NULL);\r
1387 if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {\r
1388 if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
1389 break;\r
1390 };\r
1391\r
1392 if (workFlags & 0x04) {\r
1393 // do no issue halt command for gen1b magic tag (#db# halt error. response len: 1)\r
1394 if (!(workFlags & 0x40)) {\r
1395 if (mifare_classic_halt(NULL, 0)) {\r
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
1401 }\r
1402\r
1403 isOK = 1;\r
1404 break;\r
1405 }\r
1406\r
1407 LED_B_ON();\r
1408 cmd_send(CMD_ACK,isOK,0,0,uid,4);\r
1409 LED_B_OFF();\r
1410\r
1411 if ((workFlags & 0x10) || (!isOK)) {\r
1412 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1413 LEDsoff();\r
1414 }\r
1415}\r
1416\r
1417\r
1418void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
1419\r
1420 // params\r
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
1425 // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a)\r
1426 // bit 6 - gen1b backdoor type\r
1427 uint8_t workFlags = arg0;\r
1428 uint8_t blockNo = arg2;\r
1429\r
1430 // card commands\r
1431 uint8_t wupC1[] = { 0x40 };\r
1432 uint8_t wupC2[] = { 0x43 };\r
1433\r
1434 // variables\r
1435 byte_t isOK = 0;\r
1436 uint8_t data[18] = {0x00};\r
1437 uint32_t cuid = 0;\r
1438\r
1439 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1440 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
1441\r
1442 if (workFlags & 0x08) {\r
1443 LED_A_ON();\r
1444 LED_B_OFF();\r
1445 LED_C_OFF();\r
1446 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1447\r
1448 clear_trace();\r
1449 set_tracing(true);\r
1450 }\r
1451\r
1452 while (true) {\r
1453 if (workFlags & 0x02) {\r
1454 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1455 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1456 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
1457 break;\r
1458 };\r
1459 // do no issue for gen1b magic tag\r
1460 if (!(workFlags & 0x40)) {\r
1461 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1462 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
1463 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
1464 break;\r
1465 };\r
1466 }\r
1467 }\r
1468\r
1469 // read block\r
1470 if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {\r
1471 if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
1472 break;\r
1473 };\r
1474 memcpy(data, receivedAnswer, 18);\r
1475\r
1476 if (workFlags & 0x04) {\r
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
1485 }\r
1486\r
1487 isOK = 1;\r
1488 break;\r
1489 }\r
1490\r
1491 LED_B_ON();\r
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
1498 LED_B_OFF();\r
1499\r
1500 if ((workFlags & 0x10) || (!isOK)) {\r
1501 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1502 LEDsoff();\r
1503 }\r
1504}\r
1505\r
1506void MifareCIdent(){\r
1507\r
1508 // card commands\r
1509 uint8_t wupC1[] = { 0x40 };\r
1510 uint8_t wupC2[] = { 0x43 };\r
1511\r
1512 // variables\r
1513 byte_t isOK = 0;\r
1514\r
1515 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
1516 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
1517 \r
1518 LED_A_ON();\r
1519 LED_B_OFF();\r
1520 LED_C_OFF();\r
1521 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1522\r
1523 clear_trace();\r
1524 set_tracing(true); \r
1525\r
1526 ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
1527 if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
1528 isOK = 2;\r
1529\r
1530 ReaderTransmit(wupC2, sizeof(wupC2), NULL);\r
1531 if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) {\r
1532 isOK = 1;\r
1533 };\r
1534 };\r
1535\r
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
1538 \r
1539 LED_B_ON();\r
1540 cmd_send(CMD_ACK,isOK,0,0,0,0);\r
1541 LED_B_OFF();\r
1542\r
1543 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1544 LEDsoff(); \r
1545}\r
1546\r
1547//\r
1548// DESFIRE\r
1549//\r
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
1556\r
1557 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
1558 clear_trace();\r
1559\r
1560 int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);\r
1561 if(!len) {\r
1562 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
1563 OnError(1);\r
1564 return;\r
1565 };\r
1566\r
1567 if(mifare_desfire_des_auth1(cuid, dataout)){\r
1568 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");\r
1569 OnError(4);\r
1570 return;\r
1571 }\r
1572\r
1573 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
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
1583\r
1584 memcpy(key, datain, 16);\r
1585\r
1586 isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
1587\r
1588 if( isOK) {\r
1589 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");\r
1590 OnError(4);\r
1591 return;\r
1592 }\r
1593\r
1594 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
1595\r
1596 cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
1597 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
1598 LEDsoff();\r
1599}\r
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