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