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