]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/mifarecmd.c
In the middle of some work to get arguments into scripts. Also fixed so you don't...
[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// MIFARE nested authentication. \r
285// \r
286//-----------------------------------------------------------------------------\r
287void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)\r
288{\r
289 // params\r
290 uint8_t blockNo = arg0;\r
291 uint8_t keyType = arg1;\r
292 uint8_t targetBlockNo = arg2 & 0xff;\r
293 uint8_t targetKeyType = (arg2 >> 8) & 0xff;\r
294 uint64_t ui64Key = 0;\r
295\r
296 ui64Key = bytes_to_num(datain, 6);\r
297 \r
298 // variables\r
299 int rtr, i, j, m, len;\r
300 int davg, dmin, dmax;\r
301 uint8_t uid[10];\r
302 uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1;\r
303 uint8_t par_array[4];\r
304 nestedVector nvector[NES_MAX_INFO + 1][11];\r
305 int nvectorcount[NES_MAX_INFO + 1];\r
306 int ncount = 0;\r
307 struct Crypto1State mpcs = {0, 0};\r
308 struct Crypto1State *pcs;\r
309 pcs = &mpcs;\r
310 uint8_t* receivedAnswer = mifare_get_bigbufptr();\r
311\r
312 //init\r
313 for (i = 0; i < NES_MAX_INFO + 1; i++) nvectorcount[i] = 11; // 11 - empty block;\r
314 \r
315 // clear trace\r
316 iso14a_clear_trace();\r
317 iso14a_set_tracing(false);\r
318 \r
319 iso14443a_setup();\r
320\r
321 LED_A_ON();\r
322 LED_B_ON();\r
323 LED_C_OFF();\r
324\r
325 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
326 SpinDelay(200);\r
327 \r
328 davg = dmax = 0;\r
329 dmin = 2000;\r
330\r
331 // test nonce distance\r
332 for (rtr = 0; rtr < 10; rtr++) {\r
333 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
334 SpinDelay(100);\r
335 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
336\r
337 // Test if the action was cancelled\r
338 if(BUTTON_PRESS()) {\r
339 break;\r
340 }\r
341\r
342 if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
343 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
344 break;\r
345 };\r
346 \r
347 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {\r
348 if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error");\r
349 break;\r
350 };\r
351\r
352 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2)) {\r
353 if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error");\r
354 break;\r
355 };\r
356 \r
357 nttmp = prng_successor(nt1, 500);\r
358 for (i = 501; i < 2000; i++) {\r
359 nttmp = prng_successor(nttmp, 1);\r
360 if (nttmp == nt2) break;\r
361 }\r
362 \r
363 if (i != 2000) {\r
364 davg += i;\r
365 if (dmin > i) dmin = i;\r
366 if (dmax < i) dmax = i;\r
367 if (MF_DBGLEVEL >= 4) Dbprintf("r=%d nt1=%08x nt2=%08x distance=%d", rtr, nt1, nt2, i);\r
368 }\r
369 }\r
370 \r
371 if (rtr == 0) return;\r
372\r
373 davg = davg / rtr;\r
374 if (MF_DBGLEVEL >= 3) Dbprintf("distance: min=%d max=%d avg=%d", dmin, dmax, davg);\r
375\r
376 LED_B_OFF();\r
377\r
378// ------------------------------------------------------------------------------------------------- \r
379 \r
380 LED_C_ON();\r
381\r
382 // get crypted nonces for target sector\r
383 for (rtr = 0; rtr < NS_RETRIES_GETNONCE; rtr++) {\r
384 if (MF_DBGLEVEL >= 4) Dbprintf("------------------------------");\r
385\r
386 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
387 SpinDelay(100);\r
388 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
389\r
390 // Test if the action was cancelled\r
391 if(BUTTON_PRESS()) {\r
392 break;\r
393 }\r
394\r
395 if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
396 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
397 break;\r
398 };\r
399 \r
400 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {\r
401 if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error");\r
402 break;\r
403 };\r
404\r
405 // nested authentication\r
406 len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par);\r
407 if (len != 4) {\r
408 if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error len=%d", len);\r
409 break;\r
410 };\r
411 \r
412 nt2 = bytes_to_num(receivedAnswer, 4); \r
413 if (MF_DBGLEVEL >= 4) Dbprintf("r=%d nt1=%08x nt2enc=%08x nt2par=%08x", rtr, nt1, nt2, par);\r
414 \r
415 // Parity validity check\r
416 for (i = 0; i < 4; i++) {\r
417 par_array[i] = (oddparity(receivedAnswer[i]) != ((par & 0x08) >> 3));\r
418 par = par << 1;\r
419 }\r
420 \r
421 ncount = 0;\r
422 nttest = prng_successor(nt1, dmin - NS_TOLERANCE);\r
423 for (m = dmin - NS_TOLERANCE + 1; m < dmax + NS_TOLERANCE; m++) {\r
424 nttest = prng_successor(nttest, 1);\r
425 ks1 = nt2 ^ nttest;\r
426\r
427 if (valid_nonce(nttest, nt2, ks1, par_array) && (ncount < 11)){\r
428 \r
429 nvector[NES_MAX_INFO][ncount].nt = nttest;\r
430 nvector[NES_MAX_INFO][ncount].ks1 = ks1;\r
431 ncount++;\r
432 nvectorcount[NES_MAX_INFO] = ncount;\r
433 if (MF_DBGLEVEL >= 4) Dbprintf("valid m=%d ks1=%08x nttest=%08x", m, ks1, nttest);\r
434 }\r
435\r
436 }\r
437 \r
438 // select vector with length less than got\r
439 if (nvectorcount[NES_MAX_INFO] != 0) {\r
440 m = NES_MAX_INFO;\r
441 \r
442 for (i = 0; i < NES_MAX_INFO; i++)\r
443 if (nvectorcount[i] > 10) {\r
444 m = i;\r
445 break;\r
446 }\r
447 \r
448 if (m == NES_MAX_INFO)\r
449 for (i = 0; i < NES_MAX_INFO; i++)\r
450 if (nvectorcount[NES_MAX_INFO] < nvectorcount[i]) {\r
451 m = i;\r
452 break;\r
453 }\r
454 \r
455 if (m != NES_MAX_INFO) {\r
456 for (i = 0; i < nvectorcount[m]; i++) {\r
457 nvector[m][i] = nvector[NES_MAX_INFO][i];\r
458 }\r
459 nvectorcount[m] = nvectorcount[NES_MAX_INFO];\r
460 }\r
461 }\r
462 }\r
463\r
464 LED_C_OFF();\r
465 \r
466 // ----------------------------- crypto1 destroy\r
467 crypto1_destroy(pcs);\r
468 \r
469 // add trace trailer\r
470 memset(uid, 0x44, 4);\r
471 LogTrace(uid, 4, 0, 0, TRUE);\r
472\r
473// UsbCommand ack = {CMD_ACK, {0, 0, 0}};\r
474\r
475 for (i = 0; i < NES_MAX_INFO; i++) {\r
476 if (nvectorcount[i] > 10) continue;\r
477 \r
478 for (j = 0; j < nvectorcount[i]; j += 5) {\r
479 ncount = nvectorcount[i] - j;\r
480 if (ncount > 5) ncount = 5; \r
481\r
482// ack.arg[0] = 0; // isEOF = 0\r
483// ack.arg[1] = ncount;\r
484// ack.arg[2] = targetBlockNo + (targetKeyType * 0x100);\r
485// memset(ack.d.asBytes, 0x00, sizeof(ack.d.asBytes));\r
486 \r
487 byte_t buf[48];\r
488 memset(buf, 0x00, sizeof(buf));\r
489 memcpy(buf, &cuid, 4);\r
490 for (m = 0; m < ncount; m++) {\r
491 memcpy(buf + 8 + m * 8 + 0, &nvector[i][m + j].nt, 4);\r
492 memcpy(buf + 8 + m * 8 + 4, &nvector[i][m + j].ks1, 4);\r
493 }\r
494 \r
495 LED_B_ON();\r
496 cmd_send(CMD_ACK,0,ncount,targetBlockNo + (targetKeyType * 0x100),buf,48);\r
497// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
498 LED_B_OFF();\r
499 }\r
500 }\r
501\r
502 // finalize list\r
503// ack.arg[0] = 1; // isEOF = 1\r
504// ack.arg[1] = 0;\r
505// ack.arg[2] = 0;\r
506// memset(ack.d.asBytes, 0x00, sizeof(ack.d.asBytes));\r
507 \r
508 LED_B_ON();\r
509// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
510 cmd_send(CMD_ACK,1,0,0,0,0);\r
511 LED_B_OFF();\r
512\r
513 if (MF_DBGLEVEL >= 4) DbpString("NESTED FINISHED");\r
514\r
515 // Thats it...\r
516 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
517 LEDsoff();\r
518 \r
519 iso14a_set_tracing(TRUE);\r
520}\r
521\r
522//-----------------------------------------------------------------------------\r
523// MIFARE check keys. key count up to 8. \r
524// \r
525//-----------------------------------------------------------------------------\r
526void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
527{\r
528 // params\r
529 uint8_t blockNo = arg0;\r
530 uint8_t keyType = arg1;\r
531 uint8_t keyCount = arg2;\r
532 uint64_t ui64Key = 0;\r
533 \r
534 // variables\r
535 int i;\r
536 byte_t isOK = 0;\r
537 uint8_t uid[10];\r
538 uint32_t cuid;\r
539 struct Crypto1State mpcs = {0, 0};\r
540 struct Crypto1State *pcs;\r
541 pcs = &mpcs;\r
542 \r
543 // clear debug level\r
544 int OLD_MF_DBGLEVEL = MF_DBGLEVEL; \r
545 MF_DBGLEVEL = MF_DBG_NONE;\r
546 \r
547 // clear trace\r
548 iso14a_clear_trace();\r
549 iso14a_set_tracing(TRUE);\r
550\r
551 iso14443a_setup();\r
552\r
553 LED_A_ON();\r
554 LED_B_OFF();\r
555 LED_C_OFF();\r
556\r
557 SpinDelay(300);\r
558 for (i = 0; i < keyCount; i++) {\r
559 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
560 SpinDelay(100);\r
561 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
562\r
563 if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
564 if (OLD_MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
565 break;\r
566 };\r
567\r
568 ui64Key = bytes_to_num(datain + i * 6, 6);\r
569 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
570 continue;\r
571 };\r
572 \r
573 isOK = 1;\r
574 break;\r
575 }\r
576 \r
577 // ----------------------------- crypto1 destroy\r
578 crypto1_destroy(pcs);\r
579 \r
580 // add trace trailer\r
581 memset(uid, 0x44, 4);\r
582 LogTrace(uid, 4, 0, 0, TRUE);\r
583\r
584// UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
585// if (isOK) memcpy(ack.d.asBytes, datain + i * 6, 6);\r
586 \r
587 LED_B_ON();\r
588 cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);\r
589// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
590 LED_B_OFF();\r
591\r
592 // Thats it...\r
593 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
594 LEDsoff();\r
595\r
596 // restore debug level\r
597 MF_DBGLEVEL = OLD_MF_DBGLEVEL; \r
598}\r
599\r
600//-----------------------------------------------------------------------------\r
601// MIFARE commands set debug level\r
602// \r
603//-----------------------------------------------------------------------------\r
604void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
605 MF_DBGLEVEL = arg0;\r
606 Dbprintf("Debug level: %d", MF_DBGLEVEL);\r
607}\r
608\r
609//-----------------------------------------------------------------------------\r
610// Work with emulator memory\r
611// \r
612//-----------------------------------------------------------------------------\r
613void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
614 emlClearMem();\r
615}\r
616\r
617void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
618 emlSetMem(datain, arg0, arg1); // data, block num, blocks count\r
619}\r
620\r
621void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
622// UsbCommand ack = {CMD_ACK, {arg0, arg1, 0}};\r
623\r
624 byte_t buf[48];\r
625 emlGetMem(buf, arg0, arg1); // data, block num, blocks count\r
626\r
627 LED_B_ON();\r
628 cmd_send(CMD_ACK,arg0,arg1,0,buf,48);\r
629// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
630 LED_B_OFF();\r
631}\r
632\r
633//-----------------------------------------------------------------------------\r
634// Load a card into the emulator memory\r
635// \r
636//-----------------------------------------------------------------------------\r
637void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
638 int i;\r
639 uint8_t sectorNo = 0;\r
640 uint8_t keyType = arg1;\r
641 uint64_t ui64Key = 0;\r
642 uint32_t cuid;\r
643 struct Crypto1State mpcs = {0, 0};\r
644 struct Crypto1State *pcs;\r
645 pcs = &mpcs;\r
646\r
647 // variables\r
648 byte_t dataoutbuf[16];\r
649 byte_t dataoutbuf2[16];\r
650 uint8_t uid[10];\r
651\r
652 // clear trace\r
653 iso14a_clear_trace();\r
654 iso14a_set_tracing(false);\r
655 \r
656 iso14443a_setup();\r
657\r
658 LED_A_ON();\r
659 LED_B_OFF();\r
660 LED_C_OFF();\r
661 \r
662 while (true) {\r
663 if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
664 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
665 break;\r
666 };\r
667 \r
668 for (i = 0; i < 16; i++) {\r
669 sectorNo = i;\r
670 ui64Key = emlGetKey(sectorNo, keyType);\r
671 \r
672 if (!i){\r
673 if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {\r
674 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%d]. Auth error", i);\r
675 break;\r
676 }\r
677 } else {\r
678 if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_NESTED)) {\r
679 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%d]. Auth nested error", i);\r
680 break;\r
681 }\r
682 }\r
683 \r
684 if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf)) {\r
685 if (MF_DBGLEVEL >= 1) Dbprintf("Read block 0 error");\r
686 break;\r
687 };\r
688 emlSetMem(dataoutbuf, sectorNo * 4 + 0, 1);\r
689 \r
690 if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf)) {\r
691 if (MF_DBGLEVEL >= 1) Dbprintf("Read block 1 error");\r
692 break;\r
693 };\r
694 emlSetMem(dataoutbuf, sectorNo * 4 + 1, 1);\r
695\r
696 if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf)) {\r
697 if (MF_DBGLEVEL >= 1) Dbprintf("Read block 2 error");\r
698 break;\r
699 };\r
700 emlSetMem(dataoutbuf, sectorNo * 4 + 2, 1);\r
701\r
702 // get block 3 bytes 6-9\r
703 if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf)) {\r
704 if (MF_DBGLEVEL >= 1) Dbprintf("Read block 3 error");\r
705 break;\r
706 };\r
707 emlGetMem(dataoutbuf2, sectorNo * 4 + 3, 1);\r
708 memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);\r
709 emlSetMem(dataoutbuf2, sectorNo * 4 + 3, 1);\r
710 }\r
711\r
712 if(mifare_classic_halt(pcs, cuid)) {\r
713 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
714 break;\r
715 };\r
716 \r
717 break;\r
718 } \r
719\r
720 // ----------------------------- crypto1 destroy\r
721 crypto1_destroy(pcs);\r
722\r
723 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
724 LEDsoff();\r
725 \r
726 if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");\r
727\r
728 // add trace trailer\r
729 memset(uid, 0x44, 4);\r
730 LogTrace(uid, 4, 0, 0, TRUE);\r
731}\r
732\r
733//-----------------------------------------------------------------------------\r
734// MIFARE 1k emulator\r
735// \r
736//-----------------------------------------------------------------------------\r
737\r
738\r
739//-----------------------------------------------------------------------------\r
740// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)\r
741// \r
742//-----------------------------------------------------------------------------\r
743void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
744 \r
745 // params\r
746 uint8_t needWipe = arg0;\r
747 // bit 0 - need get UID\r
748 // bit 1 - need wupC\r
749 // bit 2 - need HALT after sequence\r
750 // bit 3 - need init FPGA and field before sequence\r
751 // bit 4 - need reset FPGA and LED\r
752 uint8_t workFlags = arg1;\r
753 uint8_t blockNo = arg2;\r
754 \r
755 // card commands\r
756 uint8_t wupC1[] = { 0x40 }; \r
757 uint8_t wupC2[] = { 0x43 }; \r
758 uint8_t wipeC[] = { 0x41 }; \r
759 \r
760 // variables\r
761 byte_t isOK = 0;\r
762 uint8_t uid[10];\r
763 uint8_t d_block[18];\r
764 uint32_t cuid;\r
765 \r
766 memset(uid, 0x00, 10);\r
767 uint8_t* receivedAnswer = mifare_get_bigbufptr();\r
768 \r
769 if (workFlags & 0x08) {\r
770 // clear trace\r
771 iso14a_clear_trace();\r
772 iso14a_set_tracing(TRUE);\r
773\r
774 iso14443a_setup();\r
775\r
776 LED_A_ON();\r
777 LED_B_OFF();\r
778 LED_C_OFF();\r
779 \r
780 SpinDelay(300);\r
781 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
782 SpinDelay(100);\r
783 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
784 }\r
785\r
786 while (true) {\r
787 // get UID from chip\r
788 if (workFlags & 0x01) {\r
789 if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
790 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
791 break;\r
792 };\r
793\r
794 if(mifare_classic_halt(NULL, cuid)) {\r
795 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
796 break;\r
797 };\r
798 };\r
799 \r
800 // reset chip\r
801 if (needWipe){\r
802 ReaderTransmitBitsPar(wupC1,7,0);\r
803 if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
804 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
805 break;\r
806 };\r
807\r
808 ReaderTransmit(wipeC, sizeof(wipeC));\r
809 if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
810 if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");\r
811 break;\r
812 };\r
813\r
814 if(mifare_classic_halt(NULL, cuid)) {\r
815 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
816 break;\r
817 };\r
818 }; \r
819\r
820 // write block\r
821 if (workFlags & 0x02) {\r
822 ReaderTransmitBitsPar(wupC1,7,0);\r
823 if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
824 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
825 break;\r
826 };\r
827\r
828 ReaderTransmit(wupC2, sizeof(wupC2));\r
829 if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
830 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
831 break;\r
832 };\r
833 }\r
834\r
835 if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer) != 1) || (receivedAnswer[0] != 0x0a)) {\r
836 if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");\r
837 break;\r
838 };\r
839 \r
840 memcpy(d_block, datain, 16);\r
841 AppendCrc14443a(d_block, 16);\r
842 \r
843 ReaderTransmit(d_block, sizeof(d_block));\r
844 if ((ReaderReceive(receivedAnswer) != 1) || (receivedAnswer[0] != 0x0a)) {\r
845 if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");\r
846 break;\r
847 }; \r
848 \r
849 if (workFlags & 0x04) {\r
850 if (mifare_classic_halt(NULL, cuid)) {\r
851 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
852 break;\r
853 };\r
854 }\r
855 \r
856 isOK = 1;\r
857 break;\r
858 }\r
859 \r
860// UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
861// if (isOK) memcpy(ack.d.asBytes, uid, 4);\r
862 \r
863 // add trace trailer\r
864 /**\r
865 * Removed by Martin, the uid is overwritten with 0x44, \r
866 * which can 't be intended. \r
867 *\r
868 * memset(uid, 0x44, 4);\r
869 * LogTrace(uid, 4, 0, 0, TRUE);\r
870 **/\r
871 \r
872\r
873 LED_B_ON();\r
874 cmd_send(CMD_ACK,isOK,0,0,uid,4);\r
875// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
876 LED_B_OFF();\r
877\r
878 if ((workFlags & 0x10) || (!isOK)) {\r
879 // Thats it...\r
880 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
881 LEDsoff();\r
882 }\r
883}\r
884\r
885void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
886 \r
887 // params\r
888 // bit 1 - need wupC\r
889 // bit 2 - need HALT after sequence\r
890 // bit 3 - need init FPGA and field before sequence\r
891 // bit 4 - need reset FPGA and LED\r
892 uint8_t workFlags = arg0;\r
893 uint8_t blockNo = arg2;\r
894 \r
895 // card commands\r
896 uint8_t wupC1[] = { 0x40 }; \r
897 uint8_t wupC2[] = { 0x43 }; \r
898 \r
899 // variables\r
900 byte_t isOK = 0;\r
901 uint8_t data[18];\r
902 uint32_t cuid = 0;\r
903 \r
904 memset(data, 0x00, 18);\r
905 uint8_t* receivedAnswer = mifare_get_bigbufptr();\r
906 \r
907 if (workFlags & 0x08) {\r
908 // clear trace\r
909 iso14a_clear_trace();\r
910 iso14a_set_tracing(TRUE);\r
911\r
912 iso14443a_setup();\r
913\r
914 LED_A_ON();\r
915 LED_B_OFF();\r
916 LED_C_OFF();\r
917 \r
918 SpinDelay(300);\r
919 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
920 SpinDelay(100);\r
921 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
922 }\r
923\r
924 while (true) {\r
925 if (workFlags & 0x02) {\r
926 ReaderTransmitBitsPar(wupC1,7,0);\r
927 if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
928 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");\r
929 break;\r
930 };\r
931\r
932 ReaderTransmit(wupC2, sizeof(wupC2));\r
933 if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {\r
934 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");\r
935 break;\r
936 };\r
937 }\r
938\r
939 // read block\r
940 if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer) != 18)) {\r
941 if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");\r
942 break;\r
943 };\r
944 memcpy(data, receivedAnswer, 18);\r
945 \r
946 if (workFlags & 0x04) {\r
947 if (mifare_classic_halt(NULL, cuid)) {\r
948 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
949 break;\r
950 };\r
951 }\r
952 \r
953 isOK = 1;\r
954 break;\r
955 }\r
956 \r
957// UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
958// if (isOK) memcpy(ack.d.asBytes, data, 18);\r
959 \r
960 // add trace trailer\r
961 /*\r
962 * Removed by Martin, this piece of overwrites the 'data' variable \r
963 * which is sent two lines down, and is obviously not correct. \r
964 * \r
965 * memset(data, 0x44, 4);\r
966 * LogTrace(data, 4, 0, 0, TRUE);\r
967 */\r
968 LED_B_ON();\r
969 cmd_send(CMD_ACK,isOK,0,0,data,18);\r
970// UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
971 LED_B_OFF();\r
972\r
973 if ((workFlags & 0x10) || (!isOK)) {\r
974 // Thats it...\r
975 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
976 LEDsoff();\r
977 }\r
978}\r
979\r
Impressum, Datenschutz