1 #include "mifaredesfire.h"
4 #define MAX_APPLICATION_COUNT 28
5 #define MAX_FILE_COUNT 16
6 #define MAX_FRAME_SIZE 60
7 #define NOT_YET_AUTHENTICATED 255
8 #define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5)
10 // the block number for the ISO14443-4 PCB
11 uint8_t pcb_blocknum
= 0;
12 // Deselect card by sending a s-block. the crc is precalced for speed
13 static uint8_t deselect_cmd
[] = {0xc2,0xe0,0xb4};
15 //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
16 /* PCB CID CMD PAYLOAD */
17 //static uint8_t __res[MAX_FRAME_SIZE];
19 bool InitDesfireCard(){
21 // Make sure it is off.
22 // FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
25 byte_t cardbuf
[USB_CMD_DATA_SIZE
];
26 memset(cardbuf
,0,sizeof(cardbuf
));
28 iso14a_set_tracing(TRUE
);
29 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN
);
31 iso14a_card_select_t
*card
= (iso14a_card_select_t
*)cardbuf
;
32 int len
= iso14443a_select_card(NULL
,card
,NULL
);
35 if (MF_DBGLEVEL
>= 1) {
36 Dbprintf("Can't select card");
53 void MifareSendCommand(uint8_t arg0
, uint8_t arg1
, uint8_t *datain
){
55 /* ARG0 contains flags.
61 size_t datalen
= arg1
;
62 uint8_t resp
[RECV_RES_SIZE
];
63 memset(resp
,0,sizeof(resp
));
65 if (MF_DBGLEVEL
>= 4) {
66 Dbprintf(" flags : %02X", flags
);
67 Dbprintf(" len : %02X", datalen
);
68 print_result(" RX : ", datain
, datalen
);
71 if ( flags
& CLEARTRACE
){
76 if ( !InitDesfireCard() )
80 int len
= DesfireAPDU(datain
, datalen
, resp
);
81 if (MF_DBGLEVEL
>= 4) {
82 print_result("ERR <--: ", resp
, len
);
90 // reset the pcb_blocknum,
93 if ( flags
& DISCONNECT
){
97 cmd_send(CMD_ACK
,1,len
,0,resp
,len
);
100 void MifareDesfireGetInformation(){
103 uint8_t resp
[USB_CMD_DATA_SIZE
];
104 uint8_t dataout
[USB_CMD_DATA_SIZE
];
105 byte_t cardbuf
[USB_CMD_DATA_SIZE
];
107 memset(resp
,0,sizeof(resp
));
108 memset(dataout
,0, sizeof(dataout
));
109 memset(cardbuf
,0,sizeof(cardbuf
));
114 3 = desfire command 3
117 PCB == 0x0A because sending CID byte.
118 CID == 0x00 first card?
120 iso14a_clear_trace();
121 iso14a_set_tracing(TRUE
);
122 iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN
);
124 // card select - information
125 iso14a_card_select_t
*card
= (iso14a_card_select_t
*)cardbuf
;
126 byte_t isOK
= iso14443a_select_card(NULL
, card
, NULL
);
128 if (MF_DBGLEVEL
>= 1) {
129 Dbprintf("Can't select card");
135 memcpy(dataout
,card
->uid
,7);
141 uint8_t cmd
[] = {GET_VERSION
};
142 size_t cmd_len
= sizeof(cmd
);
144 len
= DesfireAPDU(cmd
, cmd_len
, resp
);
146 print_result("ERROR <--: ", resp
, len
);
153 memcpy(dataout
+7,resp
+3,7);
156 cmd
[0] = ADDITIONAL_FRAME
;
157 len
= DesfireAPDU(cmd
, cmd_len
, resp
);
159 print_result("ERROR <--: ", resp
, len
);
166 memcpy(dataout
+7+7,resp
+3,7);
169 len
= DesfireAPDU(cmd
, cmd_len
, resp
);
171 print_result("ERROR <--: ", resp
, len
);
176 memcpy(dataout
+7+7+7,resp
+3,14);
178 cmd_send(CMD_ACK
,1,0,0,dataout
,sizeof(dataout
));
180 // reset the pcb_blocknum,
185 void MifareDES_Auth1(uint8_t mode
, uint8_t algo
, uint8_t keyno
, uint8_t *datain
){
188 //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
189 uint8_t PICC_MASTER_KEY16
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
190 uint8_t null_key_data8
[8] = {0x00};
191 //uint8_t null_key_data16[16] = {0x00};
192 //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
193 //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
195 //uint8_t* bigbuffer = mifare_get_bigbufptr();
196 uint8_t resp
[256] = {0x00};
197 uint8_t IV
[16] = {0x00};
199 size_t datalen
= datain
[0];
201 uint8_t cmd
[40] = {0x00};
202 uint8_t encRndB
[16] = {0x00};
203 uint8_t decRndB
[16] = {0x00};
204 uint8_t nonce
[16] = {0x00};
205 uint8_t both
[32] = {0x00};
206 uint8_t encBoth
[32] = {0x00};
214 // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
215 // 4 olika crypto algo DES, 3DES, 3K3DES, AES
216 // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
222 if (datain
[1] == 0xff){
223 memcpy(keybytes
,null_key_data8
,8);
225 memcpy(keybytes
, datain
+1, datalen
);
228 cmd
[0] = AUTHENTICATE
;
229 cmd
[1] = 0x00; //keynumber
230 len
= DesfireAPDU(cmd
, 2, resp
);
232 if (MF_DBGLEVEL
>= 1) {
233 DbpString("Authentication failed. Card timeout.");
239 memcpy( encRndB
, resp
+3, 8);
241 des_dec(&decRndB
, &encRndB
, &keybytes
);
242 Dbprintf("RndB: %02x%02x%02x%02x%02x%02x%02x%02x",decRndB
[0],decRndB
[1],decRndB
[2],decRndB
[3],decRndB
[4],decRndB
[5],decRndB
[6],decRndB
[7]);
244 Dbprintf("RndB': %02x%02x%02x%02x%02x%02x%02x%02x",decRndB
[0],decRndB
[1],decRndB
[2],decRndB
[3],decRndB
[4],decRndB
[5],decRndB
[6],decRndB
[7]);
246 uint8_t decRndA
[8] = {0x00};
247 uint8_t encRndA
[8] = {0x00};
249 des_dec(&encRndA
, &decRndA
, &keybytes
);
250 Dbprintf("RndA: %02x%02x%02x%02x%02x%02x%02x%02x",decRndA
[0],decRndA
[1],decRndA
[2],decRndA
[3],decRndA
[4],decRndA
[5],decRndA
[6],decRndA
[7]);
251 Dbprintf("ek0RandA: %02x%02x%02x%02x%02x%02x%02x%02x",encRndA
[0],encRndA
[1],encRndA
[2],encRndA
[3],encRndA
[4],encRndA
[5],encRndA
[6],encRndA
[7]);
253 memcpy(both
, encRndA
, 8);
255 for (int x
= 0; x
< 8; x
++) {
256 decRndB
[x
] = decRndB
[x
] ^ encRndA
[x
];
260 des_dec(&encRndB
, &decRndB
, &keybytes
);
262 memcpy(both
+ 8, encRndB
, 8);
263 Dbprintf("both: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",both
[0],both
[1],both
[2],both
[3],both
[4],both
[5],both
[6],both
[7],both
[8],both
[9],both
[10],both
[11],both
[12],both
[13],both
[14],both
[15]);
265 cmd
[0] = ADDITIONAL_FRAME
;
266 memcpy(cmd
+1, both
, 16 );
268 len
= DesfireAPDU(cmd
, 17, resp
);
270 if (MF_DBGLEVEL
>= 1) {
271 DbpString("Authentication failed. Card timeout.");
277 // TODO: Check returned RandA'
282 //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
287 uint8_t keybytes
[16];
288 if (datain
[1] == 0xff){
289 memcpy(keybytes
,PICC_MASTER_KEY16
,16);
291 memcpy(keybytes
, datain
+1, datalen
);
294 struct desfire_key defaultkey
= {0};
295 desfirekey_t key
= &defaultkey
;
296 Desfire_aes_key_new( keybytes
, key
);
299 if ( AesCtxIni(&ctx
, IV
, key
->data
, KEY128
, CBC
) < 0 ){
300 if( MF_DBGLEVEL
>= 4) {
301 Dbprintf("AES context failed to init");
307 cmd
[0] = AUTHENTICATE_AES
;
308 cmd
[1] = 0x00; //keynumber
309 len
= DesfireAPDU(cmd
, 2, resp
);
311 if (MF_DBGLEVEL
>= 1) {
312 DbpString("Authentication failed. Card timeout.");
318 memcpy( encRndB
, resp
+3, 16);
320 // dekryptera tagnonce.
321 AesDecrypt(&ctx
, encRndB
, decRndB
, 16);
323 memcpy(both
, nonce
,16);
324 memcpy(both
+16, decRndB
,16 );
325 AesEncrypt(&ctx
, both
, encBoth
, 32 );
327 cmd
[0] = ADDITIONAL_FRAME
;
328 memcpy(cmd
+1, encBoth
, 32 );
330 len
= DesfireAPDU(cmd
, 33, resp
); // 1 + 32 == 33
332 if (MF_DBGLEVEL
>= 1) {
333 DbpString("Authentication failed. Card timeout.");
339 if ( resp
[2] == 0x00 ){
340 // Create AES Session key
341 struct desfire_key sessionKey
= {0};
342 desfirekey_t skey
= &sessionKey
;
343 Desfire_session_key_new( nonce
, decRndB
, key
, skey
);
344 print_result("SESSION : ", skey
->data
, 16);
346 DbpString("Authetication failed.");
356 cmd_send(CMD_ACK
,1,len
,0,resp
,len
);
359 // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
360 // cmd = cmd bytes to send
361 // cmd_len = length of cmd
362 // dataout = pointer to response data array
363 int DesfireAPDU(uint8_t *cmd
, size_t cmd_len
, uint8_t *dataout
){
366 size_t wrappedLen
= 0;
367 uint8_t wCmd
[USB_CMD_DATA_SIZE
] = {0};
369 wrappedLen
= CreateAPDU( cmd
, cmd_len
, wCmd
);
371 if (MF_DBGLEVEL
>= 4) {
372 print_result("WCMD <--: ", wCmd
, wrappedLen
);
374 ReaderTransmit( wCmd
, wrappedLen
, NULL
);
376 status
= ReaderReceive(dataout
);
379 if (MF_DBGLEVEL
>= 4) {
382 return FALSE
; //DATA LINK ERROR
384 // if we received an I- or R(ACK)-Block with a block number equal to the
385 // current block number, toggle the current block number
386 else if (status
>= 4 // PCB+CID+CRC = 4 bytes
387 && ((dataout
[0] & 0xC0) == 0 // I-Block
388 || (dataout
[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
389 && (dataout
[0] & 0x01) == pcb_blocknum
) // equal block numbers
391 pcb_blocknum
^= 1; //toggle next block
397 size_t CreateAPDU( uint8_t *datain
, size_t len
, uint8_t *dataout
){
399 size_t cmdlen
= MIN(len
+4, USB_CMD_DATA_SIZE
-1);
402 memset(cmd
, 0, cmdlen
);
404 cmd
[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
405 cmd
[0] |= pcb_blocknum
; // OR the block number into the PCB
406 cmd
[1] = 0x00; // CID: 0x00 //FIXME: allow multiple selected cards
408 memcpy(cmd
+2, datain
, len
);
409 AppendCrc14443a(cmd
, len
+2);
411 memcpy(dataout
, cmd
, cmdlen
);
416 // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
417 // crc_update(&desfire_crc32, addr, addr_sz);
418 // crc_update(&desfire_crc32, byte, 8);
419 // uint32_t crc = crc_finish(&desfire_crc32);
423 ReaderTransmit(deselect_cmd
, 3 , NULL
);
424 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
430 ReaderTransmit(deselect_cmd
, 3 , NULL
);
431 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
432 cmd_send(CMD_ACK
,0,0,0,0,0);