]> git.zerfleddert.de Git - proxmark3-svn/blob - armsrc/mifarecmd.c
Merge branch 'master' into topaz
[proxmark3-svn] / armsrc / mifarecmd.c
1 //-----------------------------------------------------------------------------
2 // Merlok - June 2011, 2012
3 // Gerhard de Koning Gans - May 2008
4 // Hagen Fritsch - June 2010
5 // Midnitesnake - Dec 2013
6 // Andy Davies - Apr 2014
7 // Iceman - May 2014
8 //
9 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
10 // at your option, any later version. See the LICENSE.txt file for the text of
11 // the license.
12 //-----------------------------------------------------------------------------
13 // Routines to support ISO 14443 type A.
14 //-----------------------------------------------------------------------------
15
16 #include "mifarecmd.h"
17 #include "apps.h"
18 #include "util.h"
19 #include "crc.h"
20
21 // the block number for the ISO14443-4 PCB
22 uint8_t pcb_blocknum = 0;
23 // Deselect card by sending a s-block. the crc is precalced for speed
24 static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
25
26 //-----------------------------------------------------------------------------
27 // Select, Authenticate, Read a MIFARE tag.
28 // read block
29 //-----------------------------------------------------------------------------
30 void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
31 {
32 // params
33 uint8_t blockNo = arg0;
34 uint8_t keyType = arg1;
35 uint64_t ui64Key = 0;
36 ui64Key = bytes_to_num(datain, 6);
37
38 // variables
39 byte_t isOK = 0;
40 byte_t dataoutbuf[16];
41 uint8_t uid[10];
42 uint32_t cuid;
43 struct Crypto1State mpcs = {0, 0};
44 struct Crypto1State *pcs;
45 pcs = &mpcs;
46
47 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
48
49 clear_trace();
50
51 LED_A_ON();
52 LED_B_OFF();
53 LED_C_OFF();
54
55 while (true) {
56 if(!iso14443a_select_card(uid, NULL, &cuid)) {
57 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
58 break;
59 };
60
61 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
62 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
63 break;
64 };
65
66 if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {
67 if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");
68 break;
69 };
70
71 if(mifare_classic_halt(pcs, cuid)) {
72 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
73 break;
74 };
75
76 isOK = 1;
77 break;
78 }
79
80 // ----------------------------- crypto1 destroy
81 crypto1_destroy(pcs);
82
83 if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
84
85 LED_B_ON();
86 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
87 LED_B_OFF();
88
89 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
90 LEDsoff();
91 }
92
93 void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){
94
95 bool turnOffField = (arg0 == 1);
96
97 LED_A_ON(); LED_B_OFF(); LED_C_OFF();
98
99 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
100
101 clear_trace();
102
103 if(!iso14443a_select_card(NULL, NULL, NULL)) {
104 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
105 OnError(0);
106 return;
107 };
108
109 if(!mifare_ultra_auth(keybytes)){
110 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed");
111 OnError(1);
112 return;
113 }
114
115 if (turnOffField) {
116 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
117 LEDsoff();
118 }
119 cmd_send(CMD_ACK,1,0,0,0,0);
120 }
121
122 // Arg0 = BlockNo,
123 // Arg1 = UsePwd bool
124 // datain = PWD bytes,
125 void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
126 {
127 uint8_t blockNo = arg0;
128 byte_t dataout[16] = {0x00};
129 bool useKey = (arg1 == 1); //UL_C
130 bool usePwd = (arg1 == 2); //UL_EV1/NTAG
131
132 LEDsoff();
133 LED_A_ON();
134 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
135
136 clear_trace();
137
138 int len = iso14443a_select_card(NULL, NULL, NULL);
139 if(!len) {
140 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);
141 OnError(1);
142 return;
143 }
144
145 // UL-C authentication
146 if ( useKey ) {
147 uint8_t key[16] = {0x00};
148 memcpy(key, datain, sizeof(key) );
149
150 if ( !mifare_ultra_auth(key) ) {
151 OnError(1);
152 return;
153 }
154 }
155
156 // UL-EV1 / NTAG authentication
157 if ( usePwd ) {
158 uint8_t pwd[4] = {0x00};
159 memcpy(pwd, datain, 4);
160 uint8_t pack[4] = {0,0,0,0};
161 if (!mifare_ul_ev1_auth(pwd, pack)) {
162 OnError(1);
163 return;
164 }
165 }
166
167 if( mifare_ultra_readblock(blockNo, dataout) ) {
168 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");
169 OnError(2);
170 return;
171 }
172
173 if( mifare_ultra_halt() ) {
174 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");
175 OnError(3);
176 return;
177 }
178
179 cmd_send(CMD_ACK,1,0,0,dataout,16);
180 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
181 LEDsoff();
182 }
183
184 //-----------------------------------------------------------------------------
185 // Select, Authenticate, Read a MIFARE tag.
186 // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)
187 //-----------------------------------------------------------------------------
188 void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
189 {
190 // params
191 uint8_t sectorNo = arg0;
192 uint8_t keyType = arg1;
193 uint64_t ui64Key = 0;
194 ui64Key = bytes_to_num(datain, 6);
195
196 // variables
197 byte_t isOK = 0;
198 byte_t dataoutbuf[16 * 16];
199 uint8_t uid[10];
200 uint32_t cuid;
201 struct Crypto1State mpcs = {0, 0};
202 struct Crypto1State *pcs;
203 pcs = &mpcs;
204
205 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
206
207 clear_trace();
208
209 LED_A_ON();
210 LED_B_OFF();
211 LED_C_OFF();
212
213 isOK = 1;
214 if(!iso14443a_select_card(uid, NULL, &cuid)) {
215 isOK = 0;
216 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
217 }
218
219
220 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
221 isOK = 0;
222 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
223 }
224
225 for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
226 if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) {
227 isOK = 0;
228 if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo);
229 break;
230 }
231 }
232
233 if(mifare_classic_halt(pcs, cuid)) {
234 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
235 }
236
237 // ----------------------------- crypto1 destroy
238 crypto1_destroy(pcs);
239
240 if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
241
242 LED_B_ON();
243 cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));
244 LED_B_OFF();
245
246 // Thats it...
247 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
248 LEDsoff();
249 }
250
251 // arg0 = blockNo (start)
252 // arg1 = Pages (number of blocks)
253 // arg2 = useKey
254 // datain = KEY bytes
255 void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
256 {
257 LEDsoff();
258 LED_A_ON();
259 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
260
261 // free eventually allocated BigBuf memory
262 BigBuf_free();
263 clear_trace();
264
265 // params
266 uint8_t blockNo = arg0;
267 uint16_t blocks = arg1;
268 bool useKey = (arg2 == 1); //UL_C
269 bool usePwd = (arg2 == 2); //UL_EV1/NTAG
270 uint32_t countblocks = 0;
271 uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE);
272 if (dataout == NULL){
273 Dbprintf("out of memory");
274 OnError(1);
275 return;
276 }
277
278 int len = iso14443a_select_card(NULL, NULL, NULL);
279 if (!len) {
280 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);
281 OnError(1);
282 return;
283 }
284
285 // UL-C authentication
286 if ( useKey ) {
287 uint8_t key[16] = {0x00};
288 memcpy(key, datain, sizeof(key) );
289
290 if ( !mifare_ultra_auth(key) ) {
291 OnError(1);
292 return;
293 }
294 }
295
296 // UL-EV1 / NTAG authentication
297 if (usePwd) {
298 uint8_t pwd[4] = {0x00};
299 memcpy(pwd, datain, sizeof(pwd));
300 uint8_t pack[4] = {0,0,0,0};
301
302 if (!mifare_ul_ev1_auth(pwd, pack)){
303 OnError(1);
304 return;
305 }
306 }
307
308 for (int i = 0; i < blocks; i++){
309 if ((i*4) + 4 >= CARD_MEMORY_SIZE) {
310 Dbprintf("Data exceeds buffer!!");
311 break;
312 }
313
314 len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);
315
316 if (len) {
317 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);
318 // if no blocks read - error out
319 if (i==0){
320 OnError(2);
321 return;
322 } else {
323 //stop at last successful read block and return what we got
324 break;
325 }
326 } else {
327 countblocks++;
328 }
329 }
330
331 len = mifare_ultra_halt();
332 if (len) {
333 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");
334 OnError(3);
335 return;
336 }
337
338 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);
339
340 countblocks *= 4;
341
342 cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0);
343 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
344 LEDsoff();
345 BigBuf_free();
346 }
347
348 //-----------------------------------------------------------------------------
349 // Select, Authenticate, Write a MIFARE tag.
350 // read block
351 //-----------------------------------------------------------------------------
352 void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
353 {
354 // params
355 uint8_t blockNo = arg0;
356 uint8_t keyType = arg1;
357 uint64_t ui64Key = 0;
358 byte_t blockdata[16];
359
360 ui64Key = bytes_to_num(datain, 6);
361 memcpy(blockdata, datain + 10, 16);
362
363 // variables
364 byte_t isOK = 0;
365 uint8_t uid[10];
366 uint32_t cuid;
367 struct Crypto1State mpcs = {0, 0};
368 struct Crypto1State *pcs;
369 pcs = &mpcs;
370
371 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
372
373 clear_trace();
374
375 LED_A_ON();
376 LED_B_OFF();
377 LED_C_OFF();
378
379 while (true) {
380 if(!iso14443a_select_card(uid, NULL, &cuid)) {
381 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
382 break;
383 };
384
385 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
386 if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");
387 break;
388 };
389
390 if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {
391 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
392 break;
393 };
394
395 if(mifare_classic_halt(pcs, cuid)) {
396 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
397 break;
398 };
399
400 isOK = 1;
401 break;
402 }
403
404 // ----------------------------- crypto1 destroy
405 crypto1_destroy(pcs);
406
407 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
408
409 LED_B_ON();
410 cmd_send(CMD_ACK,isOK,0,0,0,0);
411 LED_B_OFF();
412
413
414 // Thats it...
415 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
416 LEDsoff();
417 }
418
419 /* // Command not needed but left for future testing
420 void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain)
421 {
422 uint8_t blockNo = arg0;
423 byte_t blockdata[16] = {0x00};
424
425 memcpy(blockdata, datain, 16);
426
427 uint8_t uid[10] = {0x00};
428
429 LED_A_ON(); LED_B_OFF(); LED_C_OFF();
430
431 clear_trace();
432 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
433
434 if(!iso14443a_select_card(uid, NULL, NULL)) {
435 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
436 OnError(0);
437 return;
438 };
439
440 if(mifare_ultra_writeblock_compat(blockNo, blockdata)) {
441 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
442 OnError(0);
443 return; };
444
445 if(mifare_ultra_halt()) {
446 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
447 OnError(0);
448 return;
449 };
450
451 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
452
453 cmd_send(CMD_ACK,1,0,0,0,0);
454 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
455 LEDsoff();
456 }
457 */
458
459 // Arg0 : Block to write to.
460 // Arg1 : 0 = use no authentication.
461 // 1 = use 0x1A authentication.
462 // 2 = use 0x1B authentication.
463 // datain : 4 first bytes is data to be written.
464 // : 4/16 next bytes is authentication key.
465 void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
466 {
467 uint8_t blockNo = arg0;
468 bool useKey = (arg1 == 1); //UL_C
469 bool usePwd = (arg1 == 2); //UL_EV1/NTAG
470 byte_t blockdata[4] = {0x00};
471
472 memcpy(blockdata, datain,4);
473
474 LEDsoff();
475 LED_A_ON();
476 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
477
478 clear_trace();
479
480 if(!iso14443a_select_card(NULL, NULL, NULL)) {
481 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
482 OnError(0);
483 return;
484 };
485
486 // UL-C authentication
487 if ( useKey ) {
488 uint8_t key[16] = {0x00};
489 memcpy(key, datain+4, sizeof(key) );
490
491 if ( !mifare_ultra_auth(key) ) {
492 OnError(1);
493 return;
494 }
495 }
496
497 // UL-EV1 / NTAG authentication
498 if (usePwd) {
499 uint8_t pwd[4] = {0x00};
500 memcpy(pwd, datain+4, 4);
501 uint8_t pack[4] = {0,0,0,0};
502 if (!mifare_ul_ev1_auth(pwd, pack)) {
503 OnError(1);
504 return;
505 }
506 }
507
508 if(mifare_ultra_writeblock(blockNo, blockdata)) {
509 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
510 OnError(0);
511 return;
512 };
513
514 if(mifare_ultra_halt()) {
515 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
516 OnError(0);
517 return;
518 };
519
520 if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");
521
522 cmd_send(CMD_ACK,1,0,0,0,0);
523 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
524 LEDsoff();
525 }
526
527 void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
528
529 uint8_t pwd[16] = {0x00};
530 byte_t blockdata[4] = {0x00};
531
532 memcpy(pwd, datain, 16);
533
534 LED_A_ON(); LED_B_OFF(); LED_C_OFF();
535 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
536
537 clear_trace();
538
539 if(!iso14443a_select_card(NULL, NULL, NULL)) {
540 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
541 OnError(0);
542 return;
543 };
544
545 blockdata[0] = pwd[7];
546 blockdata[1] = pwd[6];
547 blockdata[2] = pwd[5];
548 blockdata[3] = pwd[4];
549 if(mifare_ultra_writeblock( 44, blockdata)) {
550 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
551 OnError(44);
552 return;
553 };
554
555 blockdata[0] = pwd[3];
556 blockdata[1] = pwd[2];
557 blockdata[2] = pwd[1];
558 blockdata[3] = pwd[0];
559 if(mifare_ultra_writeblock( 45, blockdata)) {
560 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
561 OnError(45);
562 return;
563 };
564
565 blockdata[0] = pwd[15];
566 blockdata[1] = pwd[14];
567 blockdata[2] = pwd[13];
568 blockdata[3] = pwd[12];
569 if(mifare_ultra_writeblock( 46, blockdata)) {
570 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
571 OnError(46);
572 return;
573 };
574
575 blockdata[0] = pwd[11];
576 blockdata[1] = pwd[10];
577 blockdata[2] = pwd[9];
578 blockdata[3] = pwd[8];
579 if(mifare_ultra_writeblock( 47, blockdata)) {
580 if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");
581 OnError(47);
582 return;
583 };
584
585 if(mifare_ultra_halt()) {
586 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
587 OnError(0);
588 return;
589 };
590
591 cmd_send(CMD_ACK,1,0,0,0,0);
592 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
593 LEDsoff();
594 }
595
596 // Return 1 if the nonce is invalid else return 0
597 int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
598 return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
599 (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
600 (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
601 }
602
603
604 //-----------------------------------------------------------------------------
605 // MIFARE nested authentication.
606 //
607 //-----------------------------------------------------------------------------
608 void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain)
609 {
610 // params
611 uint8_t blockNo = arg0 & 0xff;
612 uint8_t keyType = (arg0 >> 8) & 0xff;
613 uint8_t targetBlockNo = arg1 & 0xff;
614 uint8_t targetKeyType = (arg1 >> 8) & 0xff;
615 uint64_t ui64Key = 0;
616
617 ui64Key = bytes_to_num(datain, 6);
618
619 // variables
620 uint16_t rtr, i, j, len;
621 uint16_t davg;
622 static uint16_t dmin, dmax;
623 uint8_t uid[10];
624 uint32_t cuid, nt1, nt2, nttmp, nttest, ks1;
625 uint8_t par[1];
626 uint32_t target_nt[2], target_ks[2];
627
628 uint8_t par_array[4];
629 uint16_t ncount = 0;
630 struct Crypto1State mpcs = {0, 0};
631 struct Crypto1State *pcs;
632 pcs = &mpcs;
633 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
634
635 uint32_t auth1_time, auth2_time;
636 static uint16_t delta_time;
637
638 LED_A_ON();
639 LED_C_OFF();
640 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
641
642 // free eventually allocated BigBuf memory
643 BigBuf_free();
644
645 clear_trace();
646 set_tracing(false);
647
648 // statistics on nonce distance
649 int16_t isOK = 0;
650 #define NESTED_MAX_TRIES 12
651 uint16_t unsuccessfull_tries = 0;
652 if (calibrate) { // for first call only. Otherwise reuse previous calibration
653 LED_B_ON();
654 WDT_HIT();
655
656 davg = dmax = 0;
657 dmin = 2000;
658 delta_time = 0;
659
660 for (rtr = 0; rtr < 17; rtr++) {
661
662 // Test if the action was cancelled
663 if(BUTTON_PRESS()) {
664 isOK = -2;
665 break;
666 }
667
668 // prepare next select. No need to power down the card.
669 if(mifare_classic_halt(pcs, cuid)) {
670 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
671 rtr--;
672 continue;
673 }
674
675 if(!iso14443a_select_card(uid, NULL, &cuid)) {
676 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
677 rtr--;
678 continue;
679 };
680
681 auth1_time = 0;
682 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {
683 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");
684 rtr--;
685 continue;
686 };
687
688 if (delta_time) {
689 auth2_time = auth1_time + delta_time;
690 } else {
691 auth2_time = 0;
692 }
693 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) {
694 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error");
695 rtr--;
696 continue;
697 };
698
699 nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
700 for (i = 101; i < 1200; i++) {
701 nttmp = prng_successor(nttmp, 1);
702 if (nttmp == nt2) break;
703 }
704
705 if (i != 1200) {
706 if (rtr != 0) {
707 davg += i;
708 dmin = MIN(dmin, i);
709 dmax = MAX(dmax, i);
710 }
711 else {
712 delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing
713 }
714 if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i);
715 } else {
716 unsuccessfull_tries++;
717 if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable)
718 isOK = -3;
719 }
720 }
721 }
722
723 davg = (davg + (rtr - 1)/2) / (rtr - 1);
724
725 if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time);
726
727 dmin = davg - 2;
728 dmax = davg + 2;
729
730 LED_B_OFF();
731
732 }
733 // -------------------------------------------------------------------------------------------------
734
735 LED_C_ON();
736
737 // get crypted nonces for target sector
738 for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces
739
740 target_nt[i] = 0;
741 while(target_nt[i] == 0) { // continue until we have an unambiguous nonce
742
743 // prepare next select. No need to power down the card.
744 if(mifare_classic_halt(pcs, cuid)) {
745 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Halt error");
746 continue;
747 }
748
749 if(!iso14443a_select_card(uid, NULL, &cuid)) {
750 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card");
751 continue;
752 };
753
754 auth1_time = 0;
755 if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) {
756 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth1 error");
757 continue;
758 };
759
760 // nested authentication
761 auth2_time = auth1_time + delta_time;
762 len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
763 if (len != 4) {
764 if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
765 continue;
766 };
767
768 nt2 = bytes_to_num(receivedAnswer, 4);
769 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]);
770
771 // Parity validity check
772 for (j = 0; j < 4; j++) {
773 par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
774 }
775
776 ncount = 0;
777 nttest = prng_successor(nt1, dmin - 1);
778 for (j = dmin; j < dmax + 1; j++) {
779 nttest = prng_successor(nttest, 1);
780 ks1 = nt2 ^ nttest;
781
782 if (valid_nonce(nttest, nt2, ks1, par_array)){
783 if (ncount > 0) { // we are only interested in disambiguous nonces, try again
784 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j);
785 target_nt[i] = 0;
786 break;
787 }
788 target_nt[i] = nttest;
789 target_ks[i] = ks1;
790 ncount++;
791 if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces
792 target_nt[i] = 0;
793 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j);
794 break;
795 }
796 if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j);
797 }
798 }
799 if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1);
800 }
801 }
802
803 LED_C_OFF();
804
805 // ----------------------------- crypto1 destroy
806 crypto1_destroy(pcs);
807
808 byte_t buf[4 + 4 * 4];
809 memcpy(buf, &cuid, 4);
810 memcpy(buf+4, &target_nt[0], 4);
811 memcpy(buf+8, &target_ks[0], 4);
812 memcpy(buf+12, &target_nt[1], 4);
813 memcpy(buf+16, &target_ks[1], 4);
814
815 LED_B_ON();
816 cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf));
817 LED_B_OFF();
818
819 if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED");
820
821 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
822 LEDsoff();
823 set_tracing(TRUE);
824 }
825
826 //-----------------------------------------------------------------------------
827 // MIFARE check keys. key count up to 85.
828 //
829 //-----------------------------------------------------------------------------
830 void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
831 {
832 // params
833 uint8_t blockNo = arg0;
834 uint8_t keyType = arg1;
835 uint8_t keyCount = arg2;
836 uint64_t ui64Key = 0;
837
838 // variables
839 int i;
840 byte_t isOK = 0;
841 uint8_t uid[10];
842 uint32_t cuid;
843 struct Crypto1State mpcs = {0, 0};
844 struct Crypto1State *pcs;
845 pcs = &mpcs;
846
847 // clear debug level
848 int OLD_MF_DBGLEVEL = MF_DBGLEVEL;
849 MF_DBGLEVEL = MF_DBG_NONE;
850
851 LED_A_ON();
852 LED_B_OFF();
853 LED_C_OFF();
854 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
855
856 clear_trace();
857 set_tracing(TRUE);
858
859 for (i = 0; i < keyCount; i++) {
860 if(mifare_classic_halt(pcs, cuid)) {
861 if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error");
862 }
863
864 if(!iso14443a_select_card(uid, NULL, &cuid)) {
865 if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card");
866 break;
867 };
868
869 ui64Key = bytes_to_num(datain + i * 6, 6);
870 if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
871 continue;
872 };
873
874 isOK = 1;
875 break;
876 }
877
878 // ----------------------------- crypto1 destroy
879 crypto1_destroy(pcs);
880
881 LED_B_ON();
882 cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);
883 LED_B_OFF();
884
885 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
886 LEDsoff();
887
888 // restore debug level
889 MF_DBGLEVEL = OLD_MF_DBGLEVEL;
890 }
891
892 //-----------------------------------------------------------------------------
893 // MIFARE commands set debug level
894 //
895 //-----------------------------------------------------------------------------
896 void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
897 MF_DBGLEVEL = arg0;
898 Dbprintf("Debug level: %d", MF_DBGLEVEL);
899 }
900
901 //-----------------------------------------------------------------------------
902 // Work with emulator memory
903 //
904 // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not
905 // involved in dealing with emulator memory. But if it is called later, it might
906 // destroy the Emulator Memory.
907 //-----------------------------------------------------------------------------
908
909 void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
910 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
911 emlClearMem();
912 }
913
914 void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
915 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
916 emlSetMem(datain, arg0, arg1); // data, block num, blocks count
917 }
918
919 void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
920 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
921 byte_t buf[USB_CMD_DATA_SIZE];
922 emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4)
923
924 LED_B_ON();
925 cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE);
926 LED_B_OFF();
927 }
928
929 //-----------------------------------------------------------------------------
930 // Load a card into the emulator memory
931 //
932 //-----------------------------------------------------------------------------
933 void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
934 uint8_t numSectors = arg0;
935 uint8_t keyType = arg1;
936 uint64_t ui64Key = 0;
937 uint32_t cuid;
938 struct Crypto1State mpcs = {0, 0};
939 struct Crypto1State *pcs;
940 pcs = &mpcs;
941
942 // variables
943 byte_t dataoutbuf[16];
944 byte_t dataoutbuf2[16];
945 uint8_t uid[10];
946
947 LED_A_ON();
948 LED_B_OFF();
949 LED_C_OFF();
950 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
951
952 clear_trace();
953 set_tracing(false);
954
955 bool isOK = true;
956
957 if(!iso14443a_select_card(uid, NULL, &cuid)) {
958 isOK = false;
959 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
960 }
961
962 for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {
963 ui64Key = emlGetKey(sectorNo, keyType);
964 if (sectorNo == 0){
965 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
966 isOK = false;
967 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);
968 break;
969 }
970 } else {
971 if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
972 isOK = false;
973 if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
974 break;
975 }
976 }
977
978 for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
979 if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
980 isOK = false;
981 if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
982 break;
983 };
984 if (isOK) {
985 if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
986 emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
987 } else { // sector trailer, keep the keys, set only the AC
988 emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
989 memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4);
990 emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1);
991 }
992 }
993 }
994
995 }
996
997 if(mifare_classic_halt(pcs, cuid)) {
998 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
999 };
1000
1001 // ----------------------------- crypto1 destroy
1002 crypto1_destroy(pcs);
1003
1004 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1005 LEDsoff();
1006
1007 if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");
1008
1009 }
1010
1011
1012 //-----------------------------------------------------------------------------
1013 // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
1014 //
1015 //-----------------------------------------------------------------------------
1016 void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
1017
1018 // params
1019 uint8_t needWipe = arg0;
1020 // bit 0 - need get UID
1021 // bit 1 - need wupC
1022 // bit 2 - need HALT after sequence
1023 // bit 3 - need init FPGA and field before sequence
1024 // bit 4 - need reset FPGA and LED
1025 uint8_t workFlags = arg1;
1026 uint8_t blockNo = arg2;
1027
1028 // card commands
1029 uint8_t wupC1[] = { 0x40 };
1030 uint8_t wupC2[] = { 0x43 };
1031 uint8_t wipeC[] = { 0x41 };
1032
1033 // variables
1034 byte_t isOK = 0;
1035 uint8_t uid[10] = {0x00};
1036 uint8_t d_block[18] = {0x00};
1037 uint32_t cuid;
1038
1039 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
1040 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
1041
1042 // reset FPGA and LED
1043 if (workFlags & 0x08) {
1044 LED_A_ON();
1045 LED_B_OFF();
1046 LED_C_OFF();
1047 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
1048
1049 clear_trace();
1050 set_tracing(TRUE);
1051 }
1052
1053 while (true) {
1054
1055 // get UID from chip
1056 if (workFlags & 0x01) {
1057 if(!iso14443a_select_card(uid, NULL, &cuid)) {
1058 if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
1059 break;
1060 };
1061
1062 if(mifare_classic_halt(NULL, cuid)) {
1063 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
1064 break;
1065 };
1066 };
1067
1068 // reset chip
1069 if (needWipe){
1070 ReaderTransmitBitsPar(wupC1,7,0, NULL);
1071 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1072 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
1073 break;
1074 };
1075
1076 ReaderTransmit(wipeC, sizeof(wipeC), NULL);
1077 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1078 if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
1079 break;
1080 };
1081
1082 if(mifare_classic_halt(NULL, cuid)) {
1083 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
1084 break;
1085 };
1086 };
1087
1088 // write block
1089 if (workFlags & 0x02) {
1090 ReaderTransmitBitsPar(wupC1,7,0, NULL);
1091 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1092 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
1093 break;
1094 };
1095
1096 ReaderTransmit(wupC2, sizeof(wupC2), NULL);
1097 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1098 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
1099 break;
1100 };
1101 }
1102
1103 if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
1104 if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
1105 break;
1106 };
1107
1108 memcpy(d_block, datain, 16);
1109 AppendCrc14443a(d_block, 16);
1110
1111 ReaderTransmit(d_block, sizeof(d_block), NULL);
1112 if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
1113 if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
1114 break;
1115 };
1116
1117 if (workFlags & 0x04) {
1118 if (mifare_classic_halt(NULL, cuid)) {
1119 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
1120 break;
1121 };
1122 }
1123
1124 isOK = 1;
1125 break;
1126 }
1127
1128 LED_B_ON();
1129 cmd_send(CMD_ACK,isOK,0,0,uid,4);
1130 LED_B_OFF();
1131
1132 if ((workFlags & 0x10) || (!isOK)) {
1133 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1134 LEDsoff();
1135 }
1136 }
1137
1138
1139 void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){
1140
1141 // params
1142 // bit 1 - need wupC
1143 // bit 2 - need HALT after sequence
1144 // bit 3 - need init FPGA and field before sequence
1145 // bit 4 - need reset FPGA and LED
1146 uint8_t workFlags = arg0;
1147 uint8_t blockNo = arg2;
1148
1149 // card commands
1150 uint8_t wupC1[] = { 0x40 };
1151 uint8_t wupC2[] = { 0x43 };
1152
1153 // variables
1154 byte_t isOK = 0;
1155 uint8_t data[18] = {0x00};
1156 uint32_t cuid = 0;
1157
1158 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
1159 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
1160
1161 if (workFlags & 0x08) {
1162 LED_A_ON();
1163 LED_B_OFF();
1164 LED_C_OFF();
1165 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
1166
1167 clear_trace();
1168 set_tracing(TRUE);
1169 }
1170
1171 while (true) {
1172 if (workFlags & 0x02) {
1173 ReaderTransmitBitsPar(wupC1,7,0, NULL);
1174 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1175 if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
1176 break;
1177 };
1178
1179 ReaderTransmit(wupC2, sizeof(wupC2), NULL);
1180 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1181 if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
1182 break;
1183 };
1184 }
1185
1186 // read block
1187 if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
1188 if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");
1189 break;
1190 };
1191 memcpy(data, receivedAnswer, 18);
1192
1193 if (workFlags & 0x04) {
1194 if (mifare_classic_halt(NULL, cuid)) {
1195 if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");
1196 break;
1197 };
1198 }
1199
1200 isOK = 1;
1201 break;
1202 }
1203
1204 LED_B_ON();
1205 cmd_send(CMD_ACK,isOK,0,0,data,18);
1206 LED_B_OFF();
1207
1208 if ((workFlags & 0x10) || (!isOK)) {
1209 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1210 LEDsoff();
1211 }
1212 }
1213
1214 void MifareCIdent(){
1215
1216 // card commands
1217 uint8_t wupC1[] = { 0x40 };
1218 uint8_t wupC2[] = { 0x43 };
1219
1220 // variables
1221 byte_t isOK = 1;
1222
1223 uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
1224 uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
1225
1226 ReaderTransmitBitsPar(wupC1,7,0, NULL);
1227 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1228 isOK = 0;
1229 };
1230
1231 ReaderTransmit(wupC2, sizeof(wupC2), NULL);
1232 if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
1233 isOK = 0;
1234 };
1235
1236 if (mifare_classic_halt(NULL, 0)) {
1237 isOK = 0;
1238 };
1239
1240 cmd_send(CMD_ACK,isOK,0,0,0,0);
1241 }
1242
1243 //
1244 // DESFIRE
1245 //
1246
1247 void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
1248
1249 byte_t dataout[11] = {0x00};
1250 uint8_t uid[10] = {0x00};
1251 uint32_t cuid;
1252
1253 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
1254 clear_trace();
1255
1256 int len = iso14443a_select_card(uid, NULL, &cuid);
1257 if(!len) {
1258 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
1259 OnError(1);
1260 return;
1261 };
1262
1263 if(mifare_desfire_des_auth1(cuid, dataout)){
1264 if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");
1265 OnError(4);
1266 return;
1267 }
1268
1269 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
1270 cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
1271 }
1272
1273 void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
1274
1275 uint32_t cuid = arg0;
1276 uint8_t key[16] = {0x00};
1277 byte_t isOK = 0;
1278 byte_t dataout[12] = {0x00};
1279
1280 memcpy(key, datain, 16);
1281
1282 isOK = mifare_desfire_des_auth2(cuid, key, dataout);
1283
1284 if( isOK) {
1285 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");
1286 OnError(4);
1287 return;
1288 }
1289
1290 if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");
1291
1292 cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
1293 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1294 LEDsoff();
1295 }
1296
1297 void OnSuccess(){
1298 pcb_blocknum = 0;
1299 ReaderTransmit(deselect_cmd, 3 , NULL);
1300 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1301 LEDsoff();
1302 }
1303
1304 void OnError(uint8_t reason){
1305 pcb_blocknum = 0;
1306 ReaderTransmit(deselect_cmd, 3 , NULL);
1307 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1308 cmd_send(CMD_ACK,0,reason,0,0,0);
1309 LEDsoff();
1310 }
Impressum, Datenschutz