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