1 //-----------------------------------------------------------------------------
3 // Gerhard de Koning Gans - May 2008
4 // Hagen Fritsch - June 2010
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
9 //-----------------------------------------------------------------------------
10 // Routines to support ISO 14443 type A.
11 //-----------------------------------------------------------------------------
13 #include "mifarecmd.h"
16 //-----------------------------------------------------------------------------
17 // Select, Authenticaate, Read an MIFARE tag.
19 //-----------------------------------------------------------------------------
20 void MifareReadBlock(uint8_t arg0
, uint8_t arg1
, uint8_t arg2
, uint8_t *datain
)
23 uint8_t blockNo
= arg0
;
24 uint8_t keyType
= arg1
;
26 ui64Key
= bytes_to_num(datain
, 6);
30 byte_t dataoutbuf
[16];
33 struct Crypto1State mpcs
= {0, 0};
34 struct Crypto1State
*pcs
;
38 iso14a_clear_tracelen();
39 // iso14a_set_tracing(false);
48 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
49 if (MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
53 if(mifare_classic_auth(pcs
, cuid
, blockNo
, keyType
, ui64Key
, AUTH_FIRST
)) {
54 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth error");
58 if(mifare_classic_readblock(pcs
, cuid
, blockNo
, dataoutbuf
)) {
59 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block error");
63 if(mifare_classic_halt(pcs
, cuid
)) {
64 if (MF_DBGLEVEL
>= 1) Dbprintf("Halt error");
72 // ----------------------------- crypto1 destroy
75 if (MF_DBGLEVEL
>= 2) DbpString("READ BLOCK FINISHED");
79 LogTrace(uid
, 4, 0, 0, TRUE
);
81 UsbCommand ack
= {CMD_ACK
, {isOK
, 0, 0}};
82 memcpy(ack
.d
.asBytes
, dataoutbuf
, 16);
85 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
90 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
92 // iso14a_set_tracing(TRUE);
96 //-----------------------------------------------------------------------------
97 // Select, Authenticaate, Read an MIFARE tag.
98 // read sector (data = 4 x 16 bytes = 64 bytes)
99 //-----------------------------------------------------------------------------
100 void MifareReadSector(uint8_t arg0
, uint8_t arg1
, uint8_t arg2
, uint8_t *datain
)
103 uint8_t sectorNo
= arg0
;
104 uint8_t keyType
= arg1
;
105 uint64_t ui64Key
= 0;
106 ui64Key
= bytes_to_num(datain
, 6);
110 byte_t dataoutbuf
[16 * 4];
113 struct Crypto1State mpcs
= {0, 0};
114 struct Crypto1State
*pcs
;
118 iso14a_clear_tracelen();
119 // iso14a_set_tracing(false);
128 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
129 if (MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
133 if(mifare_classic_auth(pcs
, cuid
, sectorNo
* 4, keyType
, ui64Key
, AUTH_FIRST
)) {
134 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth error");
138 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 0, dataoutbuf
+ 16 * 0)) {
139 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 0 error");
142 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 1, dataoutbuf
+ 16 * 1)) {
143 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 1 error");
146 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 2, dataoutbuf
+ 16 * 2)) {
147 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 2 error");
150 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 3, dataoutbuf
+ 16 * 3)) {
151 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 3 error");
155 if(mifare_classic_halt(pcs
, cuid
)) {
156 if (MF_DBGLEVEL
>= 1) Dbprintf("Halt error");
164 // ----------------------------- crypto1 destroy
165 crypto1_destroy(pcs
);
167 if (MF_DBGLEVEL
>= 2) DbpString("READ SECTOR FINISHED");
170 memset(uid
, 0x44, 4);
171 LogTrace(uid
, 4, 0, 0, TRUE
);
173 UsbCommand ack
= {CMD_ACK
, {isOK
, 0, 0}};
174 memcpy(ack
.d
.asBytes
, dataoutbuf
, 16 * 2);
177 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
181 memcpy(ack
.d
.asBytes
, dataoutbuf
+ 16 * 2, 16 * 2);
182 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
186 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
188 // iso14a_set_tracing(TRUE);
192 //-----------------------------------------------------------------------------
193 // Select, Authenticaate, Read an MIFARE tag.
195 //-----------------------------------------------------------------------------
196 void MifareWriteBlock(uint8_t arg0
, uint8_t arg1
, uint8_t arg2
, uint8_t *datain
)
199 uint8_t blockNo
= arg0
;
200 uint8_t keyType
= arg1
;
201 uint64_t ui64Key
= 0;
202 byte_t blockdata
[16];
204 ui64Key
= bytes_to_num(datain
, 6);
205 memcpy(blockdata
, datain
+ 10, 16);
211 struct Crypto1State mpcs
= {0, 0};
212 struct Crypto1State
*pcs
;
216 iso14a_clear_tracelen();
217 // iso14a_set_tracing(false);
226 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
227 if (MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
231 if(mifare_classic_auth(pcs
, cuid
, blockNo
, keyType
, ui64Key
, AUTH_FIRST
)) {
232 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth error");
236 if(mifare_classic_writeblock(pcs
, cuid
, blockNo
, blockdata
)) {
237 if (MF_DBGLEVEL
>= 1) Dbprintf("Write block error");
241 if(mifare_classic_halt(pcs
, cuid
)) {
242 if (MF_DBGLEVEL
>= 1) Dbprintf("Halt error");
250 // ----------------------------- crypto1 destroy
251 crypto1_destroy(pcs
);
253 if (MF_DBGLEVEL
>= 2) DbpString("WRITE BLOCK FINISHED");
256 memset(uid
, 0x44, 4);
257 LogTrace(uid
, 4, 0, 0, TRUE
);
259 UsbCommand ack
= {CMD_ACK
, {isOK
, 0, 0}};
262 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
267 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
269 // iso14a_set_tracing(TRUE);
273 // Return 1 if the nonce is invalid else return 0
274 int valid_nonce(uint32_t Nt
, uint32_t NtEnc
, uint32_t Ks1
, byte_t
* parity
) {
275 return ((oddparity((Nt
>> 24) & 0xFF) == ((parity
[0]) ^ oddparity((NtEnc
>> 24) & 0xFF) ^ BIT(Ks1
,16))) & \
276 (oddparity((Nt
>> 16) & 0xFF) == ((parity
[1]) ^ oddparity((NtEnc
>> 16) & 0xFF) ^ BIT(Ks1
,8))) & \
277 (oddparity((Nt
>> 8) & 0xFF) == ((parity
[2]) ^ oddparity((NtEnc
>> 8) & 0xFF) ^ BIT(Ks1
,0)))) ? 1 : 0;
280 //-----------------------------------------------------------------------------
281 // MIFARE nested authentication.
283 //-----------------------------------------------------------------------------
284 void MifareNested(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
)
287 uint8_t blockNo
= arg0
;
288 uint8_t keyType
= arg1
;
289 uint8_t targetBlockNo
= arg2
& 0xff;
290 uint8_t targetKeyType
= (arg2
>> 8) & 0xff;
291 uint64_t ui64Key
= 0;
293 ui64Key
= bytes_to_num(datain
, 6);
296 int rtr
, i
, j
, m
, len
;
297 int davg
, dmin
, dmax
;
299 uint32_t cuid
, nt1
, nt2
, nttmp
, nttest
, par
, ks1
;
300 uint8_t par_array
[4];
301 nestedVector nvector
[NES_MAX_INFO
+ 1][11];
302 int nvectorcount
[NES_MAX_INFO
+ 1];
304 UsbCommand ack
= {CMD_ACK
, {0, 0, 0}};
305 struct Crypto1State mpcs
= {0, 0};
306 struct Crypto1State
*pcs
;
308 uint8_t* receivedAnswer
= mifare_get_bigbufptr();
311 for (i
= 0; i
< NES_MAX_INFO
+ 1; i
++) nvectorcount
[i
] = 11; // 11 - empty block;
314 iso14a_clear_tracelen();
315 iso14a_set_tracing(false);
323 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
329 // test nonce distance
330 for (rtr
= 0; rtr
< 10; rtr
++) {
331 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
333 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A
| FPGA_HF_ISO14443A_READER_MOD
);
335 // Test if the action was cancelled
340 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
341 if (MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
345 if(mifare_classic_authex(pcs
, cuid
, blockNo
, keyType
, ui64Key
, AUTH_FIRST
, &nt1
)) {
346 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth1 error");
350 if(mifare_classic_authex(pcs
, cuid
, blockNo
, keyType
, ui64Key
, AUTH_NESTED
, &nt2
)) {
351 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth2 error");
355 nttmp
= prng_successor(nt1
, 500);
356 for (i
= 501; i
< 2000; i
++) {
357 nttmp
= prng_successor(nttmp
, 1);
358 if (nttmp
== nt2
) break;
363 if (dmin
> i
) dmin
= i
;
364 if (dmax
< i
) dmax
= i
;
365 if (MF_DBGLEVEL
>= 4) Dbprintf("r=%d nt1=%08x nt2=%08x distance=%d", rtr
, nt1
, nt2
, i
);
369 if (rtr
== 0) return;
372 if (MF_DBGLEVEL
>= 3) Dbprintf("distance: min=%d max=%d avg=%d", dmin
, dmax
, davg
);
376 // -------------------------------------------------------------------------------------------------
380 // get crypted nonces for target sector
381 for (rtr
= 0; rtr
< NS_RETRIES_GETNONCE
; rtr
++) {
382 if (MF_DBGLEVEL
>= 4) Dbprintf("------------------------------");
384 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
386 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A
| FPGA_HF_ISO14443A_READER_MOD
);
388 // Test if the action was cancelled
393 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
394 if (MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
398 if(mifare_classic_authex(pcs
, cuid
, blockNo
, keyType
, ui64Key
, AUTH_FIRST
, &nt1
)) {
399 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth1 error");
403 // nested authentication
404 len
= mifare_sendcmd_shortex(pcs
, AUTH_NESTED
, 0x60 + (targetKeyType
& 0x01), targetBlockNo
, receivedAnswer
, &par
);
406 if (MF_DBGLEVEL
>= 1) Dbprintf("Auth2 error len=%d", len
);
410 nt2
= bytes_to_num(receivedAnswer
, 4);
411 if (MF_DBGLEVEL
>= 4) Dbprintf("r=%d nt1=%08x nt2enc=%08x nt2par=%08x", rtr
, nt1
, nt2
, par
);
413 // Parity validity check
414 for (i
= 0; i
< 4; i
++) {
415 par_array
[i
] = (oddparity(receivedAnswer
[i
]) != ((par
& 0x08) >> 3));
420 nttest
= prng_successor(nt1
, dmin
- NS_TOLERANCE
);
421 for (m
= dmin
- NS_TOLERANCE
+ 1; m
< dmax
+ NS_TOLERANCE
; m
++) {
422 nttest
= prng_successor(nttest
, 1);
425 if (valid_nonce(nttest
, nt2
, ks1
, par_array
) && (ncount
< 11)){
427 nvector
[NES_MAX_INFO
][ncount
].nt
= nttest
;
428 nvector
[NES_MAX_INFO
][ncount
].ks1
= ks1
;
430 nvectorcount
[NES_MAX_INFO
] = ncount
;
431 if (MF_DBGLEVEL
>= 4) Dbprintf("valid m=%d ks1=%08x nttest=%08x", m
, ks1
, nttest
);
436 // select vector with length less than got
437 if (nvectorcount
[NES_MAX_INFO
] != 0) {
440 for (i
= 0; i
< NES_MAX_INFO
; i
++)
441 if (nvectorcount
[i
] > 10) {
446 if (m
== NES_MAX_INFO
)
447 for (i
= 0; i
< NES_MAX_INFO
; i
++)
448 if (nvectorcount
[NES_MAX_INFO
] < nvectorcount
[i
]) {
453 if (m
!= NES_MAX_INFO
) {
454 for (i
= 0; i
< nvectorcount
[m
]; i
++) {
455 nvector
[m
][i
] = nvector
[NES_MAX_INFO
][i
];
457 nvectorcount
[m
] = nvectorcount
[NES_MAX_INFO
];
464 // ----------------------------- crypto1 destroy
465 crypto1_destroy(pcs
);
468 memset(uid
, 0x44, 4);
469 LogTrace(uid
, 4, 0, 0, TRUE
);
471 for (i
= 0; i
< NES_MAX_INFO
; i
++) {
472 if (nvectorcount
[i
] > 10) continue;
474 for (j
= 0; j
< nvectorcount
[i
]; j
+= 5) {
475 ncount
= nvectorcount
[i
] - j
;
476 if (ncount
> 5) ncount
= 5;
478 ack
.arg
[0] = 0; // isEOF = 0
480 ack
.arg
[2] = targetBlockNo
+ (targetKeyType
* 0x100);
481 memset(ack
.d
.asBytes
, 0x00, sizeof(ack
.d
.asBytes
));
483 memcpy(ack
.d
.asBytes
, &cuid
, 4);
484 for (m
= 0; m
< ncount
; m
++) {
485 memcpy(ack
.d
.asBytes
+ 8 + m
* 8 + 0, &nvector
[i
][m
+ j
].nt
, 4);
486 memcpy(ack
.d
.asBytes
+ 8 + m
* 8 + 4, &nvector
[i
][m
+ j
].ks1
, 4);
491 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
497 ack
.arg
[0] = 1; // isEOF = 1
500 memset(ack
.d
.asBytes
, 0x00, sizeof(ack
.d
.asBytes
));
504 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
507 if (MF_DBGLEVEL
>= 4) DbpString("NESTED FINISHED");
510 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
513 iso14a_set_tracing(TRUE
);
516 //-----------------------------------------------------------------------------
517 // MIFARE check keys. key count up to 8.
519 //-----------------------------------------------------------------------------
520 void MifareChkKeys(uint8_t arg0
, uint8_t arg1
, uint8_t arg2
, uint8_t *datain
)
523 uint8_t blockNo
= arg0
;
524 uint8_t keyType
= arg1
;
525 uint8_t keyCount
= arg2
;
526 uint64_t ui64Key
= 0;
533 struct Crypto1State mpcs
= {0, 0};
534 struct Crypto1State
*pcs
;
538 int OLD_MF_DBGLEVEL
= MF_DBGLEVEL
;
539 MF_DBGLEVEL
= MF_DBG_NONE
;
542 iso14a_clear_tracelen();
543 iso14a_set_tracing(TRUE
);
552 for (i
= 0; i
< keyCount
; i
++) {
553 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
555 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A
| FPGA_HF_ISO14443A_READER_MOD
);
557 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
558 if (OLD_MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
562 ui64Key
= bytes_to_num(datain
+ i
* 6, 6);
563 if(mifare_classic_auth(pcs
, cuid
, blockNo
, keyType
, ui64Key
, AUTH_FIRST
)) {
571 // ----------------------------- crypto1 destroy
572 crypto1_destroy(pcs
);
575 memset(uid
, 0x44, 4);
576 LogTrace(uid
, 4, 0, 0, TRUE
);
578 UsbCommand ack
= {CMD_ACK
, {isOK
, 0, 0}};
579 if (isOK
) memcpy(ack
.d
.asBytes
, datain
+ i
* 6, 6);
582 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
586 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
589 // restore debug level
590 MF_DBGLEVEL
= OLD_MF_DBGLEVEL
;
593 //-----------------------------------------------------------------------------
594 // MIFARE commands set debug level
596 //-----------------------------------------------------------------------------
597 void MifareSetDbgLvl(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
){
599 Dbprintf("Debug level: %d", MF_DBGLEVEL
);
602 //-----------------------------------------------------------------------------
603 // Work with emulator memory
605 //-----------------------------------------------------------------------------
606 void MifareEMemClr(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
){
610 void MifareEMemSet(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
){
611 emlSetMem(datain
, arg0
, arg1
); // data, block num, blocks count
614 void MifareEMemGet(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
){
615 UsbCommand ack
= {CMD_ACK
, {arg0
, arg1
, 0}};
617 emlGetMem(ack
.d
.asBytes
, arg0
, arg1
); // data, block num, blocks count
620 UsbSendPacket((uint8_t *)&ack
, sizeof(UsbCommand
));
624 //-----------------------------------------------------------------------------
625 // Load a card into the emulator memory
627 //-----------------------------------------------------------------------------
628 void MifareECardLoad(uint32_t arg0
, uint32_t arg1
, uint32_t arg2
, uint8_t *datain
){
630 uint8_t sectorNo
= 0;
631 uint8_t keyType
= arg1
;
632 uint64_t ui64Key
= 0;
634 struct Crypto1State mpcs
= {0, 0};
635 struct Crypto1State
*pcs
;
639 byte_t dataoutbuf
[16];
640 byte_t dataoutbuf2
[16];
644 iso14a_clear_tracelen();
645 iso14a_set_tracing(false);
654 if(!iso14443a_select_card(uid
, NULL
, &cuid
)) {
655 if (MF_DBGLEVEL
>= 1) Dbprintf("Can't select card");
659 for (i
= 0; i
< 16; i
++) {
661 ui64Key
= emlGetKey(sectorNo
, keyType
);
664 if(mifare_classic_auth(pcs
, cuid
, sectorNo
* 4, keyType
, ui64Key
, AUTH_FIRST
)) {
665 if (MF_DBGLEVEL
>= 1) Dbprintf("Sector[%d]. Auth error", i
);
669 if(mifare_classic_auth(pcs
, cuid
, sectorNo
* 4, keyType
, ui64Key
, AUTH_NESTED
)) {
670 if (MF_DBGLEVEL
>= 1) Dbprintf("Sector[%d]. Auth nested error", i
);
675 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 0, dataoutbuf
)) {
676 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 0 error");
679 emlSetMem(dataoutbuf
, sectorNo
* 4 + 0, 1);
681 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 1, dataoutbuf
)) {
682 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 1 error");
685 emlSetMem(dataoutbuf
, sectorNo
* 4 + 1, 1);
687 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 2, dataoutbuf
)) {
688 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 2 error");
691 emlSetMem(dataoutbuf
, sectorNo
* 4 + 2, 1);
693 // get block 3 bytes 6-9
694 if(mifare_classic_readblock(pcs
, cuid
, sectorNo
* 4 + 3, dataoutbuf
)) {
695 if (MF_DBGLEVEL
>= 1) Dbprintf("Read block 3 error");
698 emlGetMem(dataoutbuf2
, sectorNo
* 4 + 3, 1);
699 memcpy(&dataoutbuf2
[6], &dataoutbuf
[6], 4);
700 emlSetMem(dataoutbuf2
, sectorNo
* 4 + 3, 1);
703 if(mifare_classic_halt(pcs
, cuid
)) {
704 if (MF_DBGLEVEL
>= 1) Dbprintf("Halt error");
711 // ----------------------------- crypto1 destroy
712 crypto1_destroy(pcs
);
714 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
717 if (MF_DBGLEVEL
>= 2) DbpString("EMUL FILL SECTORS FINISHED");
720 memset(uid
, 0x44, 4);
721 LogTrace(uid
, 4, 0, 0, TRUE
);
724 //-----------------------------------------------------------------------------
725 // MIFARE 1k emulator
727 //-----------------------------------------------------------------------------