1 #include "mifaredesfire.h" 
   5 #define MAX_APPLICATION_COUNT 28 
   6 #define MAX_FILE_COUNT 16 
   7 #define MAX_DESFIRE_FRAME_SIZE 60 
   8 #define NOT_YET_AUTHENTICATED 255 
   9 #define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5) 
  10 #define RECEIVE_SIZE 64 
  12 // the block number for the ISO14443-4 PCB 
  13 uint8_t pcb_blocknum 
= 0; 
  14 // Deselect card by sending a s-block. the crc is precalced for speed 
  15 static  uint8_t deselect_cmd
[] = {0xc2,0xe0,0xb4}; 
  17 //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 }; 
  18 /*                                       PCB   CID   CMD    PAYLOAD    */ 
  19 //static uint8_t __res[MAX_FRAME_SIZE]; 
  21 bool InitDesfireCard(){ 
  23         byte_t cardbuf
[USB_CMD_DATA_SIZE
] = {0x00}; 
  25         iso14a_card_select_t 
*card 
= (iso14a_card_select_t
*)cardbuf
; 
  28         iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN
); 
  30         int len 
= iso14443a_select_card(NULL
,card
,NULL
); 
  33                 if (MF_DBGLEVEL 
>= MF_DBG_ERROR
) 
  34                         Dbprintf("Can't select card"); 
  50 void MifareSendCommand(uint8_t arg0
, uint8_t arg1
, uint8_t *datain
){ 
  52         /* ARG0 contains flags. 
  58         size_t datalen 
= arg1
; 
  59         uint8_t resp
[RECEIVE_SIZE
]; 
  60         memset(resp
,0,sizeof(resp
)); 
  62         if (MF_DBGLEVEL 
>= 4) { 
  63                 Dbprintf(" flags : %02X", flags
); 
  64                 Dbprintf(" len   : %02X", datalen
); 
  65                 print_result(" RX    : ", datain
, datalen
); 
  68         if ( flags 
& CLEARTRACE 
){ 
  73                 if ( !InitDesfireCard() ) 
  77         int len 
= DesfireAPDU(datain
, datalen
, resp
); 
  78         if (MF_DBGLEVEL 
>= 4) { 
  79                 print_result("ERR <--: ", resp
, len
); 
  87         // reset the pcb_blocknum, 
  90         if ( flags 
& DISCONNECT 
){ 
  94         cmd_send(CMD_ACK
,1,len
,0,resp
,len
); 
  97 void MifareDesfireGetInformation(){ 
 100         uint8_t resp
[USB_CMD_DATA_SIZE
] = {0x00}; 
 101         uint8_t dataout
[USB_CMD_DATA_SIZE
] = {0x00}; 
 102         byte_t cardbuf
[USB_CMD_DATA_SIZE
] = {0x00}; 
 107                 3 = desfire command             3  
 110                 PCB == 0x0A because sending CID byte. 
 111                 CID == 0x00 first card?          
 115         iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN
); 
 117         // card select - information 
 118         iso14a_card_select_t 
*card 
= (iso14a_card_select_t
*)cardbuf
; 
 119         byte_t isOK 
= iso14443a_select_card(NULL
, card
, NULL
); 
 121                 if (MF_DBGLEVEL 
>= MF_DBG_ERROR
) { 
 122                         Dbprintf("Can't select card"); 
 128         memcpy(dataout
,card
->uid
,7); 
 134         uint8_t cmd
[] = {GET_VERSION
};   
 135         size_t cmd_len 
= sizeof(cmd
); 
 137         len 
=  DesfireAPDU(cmd
, cmd_len
, resp
); 
 139                 print_result("ERROR <--: ", resp
, len
);  
 146         memcpy(dataout
+7,resp
+3,7); 
 149         cmd
[0] = ADDITIONAL_FRAME
; 
 150         len 
=  DesfireAPDU(cmd
, cmd_len
, resp
); 
 152                 print_result("ERROR <--: ", resp
, len
);  
 159         memcpy(dataout
+7+7,resp
+3,7); 
 162         len 
=  DesfireAPDU(cmd
, cmd_len
, resp
); 
 164                 print_result("ERROR <--: ", resp
, len
);  
 169         memcpy(dataout
+7+7+7,resp
+3,14); 
 171         cmd_send(CMD_ACK
,1,0,0,dataout
,sizeof(dataout
)); 
 173         // reset the pcb_blocknum, 
 178 void MifareDES_Auth1(uint8_t mode
, uint8_t algo
, uint8_t keyno
,  uint8_t *datain
){ 
 181         //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; 
 182         uint8_t PICC_MASTER_KEY16
[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f }; 
 183         uint8_t null_key_data8
[8] = {0x00}; 
 184         //uint8_t null_key_data16[16] = {0x00};  
 185         //uint8_t new_key_data8[8]  = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; 
 186         //uint8_t new_key_data16[16]  = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; 
 188         uint8_t resp
[256] = {0x00}; 
 189         uint8_t IV
[16] = {0x00}; 
 191         size_t datalen 
= datain
[0]; 
 193         uint8_t cmd
[40] = {0x00}; 
 194         uint8_t encRndB
[16] = {0x00}; 
 195         uint8_t decRndB
[16] = {0x00}; 
 196         uint8_t nonce
[16] = {0x00}; 
 197         uint8_t both
[32] = {0x00}; 
 198         uint8_t encBoth
[32] = {0x00}; 
 202         // 3 olika sätt att authenticera.   AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) 
 203         // 4 olika crypto algo   DES, 3DES, 3K3DES, AES 
 204         // 3 olika kommunikations sätt,   PLAIN,MAC,CRYPTO 
 211             uint8_t keybytes
[8] = {0x00}; 
 212             uint8_t RndA
[8] = {0x00}; 
 213             uint8_t RndB
[8] = {0x00}; 
 215             if (datain
[1] == 0xff){ 
 216                 memcpy(keybytes
,null_key_data8
,8); 
 218                 memcpy(keybytes
, datain
+1, datalen
); 
 221             struct desfire_key defaultkey 
= {0}; 
 222             desfirekey_t key 
= &defaultkey
; 
 223             Desfire_des_key_new(keybytes
, key
); 
 225             cmd
[0] = AUTHENTICATE
; 
 226             cmd
[1] = keyno
;  //keynumber 
 227             len 
= DesfireAPDU(cmd
, 2, resp
); 
 229                 if (MF_DBGLEVEL 
>= MF_DBG_ERROR
) { 
 230                     DbpString("Authentication failed. Card timeout."); 
 236             if ( resp
[2] == 0xaf ){ 
 238                 DbpString("Authetication failed. Invalid key number."); 
 243             memcpy( encRndB
, resp
+3, 8); 
 245             des_dec(&decRndB
, &encRndB
, key
->data
); 
 246             memcpy(RndB
, decRndB
, 8); 
 249             // This should be random 
 250             uint8_t decRndA
[8] = {0x00}; 
 251             memcpy(RndA
, decRndA
, 8); 
 252             uint8_t encRndA
[8] = {0x00}; 
 254             des_dec(&encRndA
, &decRndA
, key
->data
); 
 256             memcpy(both
, encRndA
, 8); 
 258             for (int x 
= 0; x 
< 8; x
++) { 
 259                 decRndB
[x
] = decRndB
[x
] ^ encRndA
[x
]; 
 262             des_dec(&encRndB
, &decRndB
, key
->data
); 
 264             memcpy(both 
+ 8, encRndB
, 8); 
 266             cmd
[0] = ADDITIONAL_FRAME
; 
 267             memcpy(cmd
+1, both
, 16 ); 
 269             len 
= DesfireAPDU(cmd
, 17, resp
); 
 271                 if (MF_DBGLEVEL 
>= MF_DBG_ERROR
) { 
 272                     DbpString("Authentication failed. Card timeout."); 
 278             if ( resp
[2] == 0x00 ){ 
 280                 struct desfire_key sessionKey 
= {0}; 
 281                 desfirekey_t skey 
= &sessionKey
; 
 282                 Desfire_session_key_new( RndA
, RndB 
, key
, skey 
); 
 283                 //print_result("SESSION : ", skey->data, 8); 
 285                 memcpy(encRndA
, resp
+3, 8); 
 286                 des_dec(&encRndA
, &encRndA
, key
->data
); 
 288                 for (int x 
= 0; x 
< 8; x
++) { 
 289                     if (decRndA
[x
] != encRndA
[x
]) { 
 290                         DbpString("Authetication failed. Cannot varify PICC."); 
 296                 //Change the selected key to a new value. 
 302                 uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; 
 304                 uint8_t first, second; 
 305                 uint8_t buff1[8] = {0x00}; 
 306                 uint8_t buff2[8] = {0x00}; 
 307                 uint8_t buff3[8] = {0x00}; 
 309                 memcpy(buff1,newKey, 8); 
 310                 memcpy(buff2,newKey + 8, 8); 
 312                 ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second); 
 313                 memcpy(buff3, &first, 1); 
 314                 memcpy(buff3 + 1, &second, 1); 
 316                 des_dec(&buff1, &buff1, skey->data); 
 317                 memcpy(cmd+2,buff1,8); 
 319                 for (int x = 0; x < 8; x++) { 
 320                     buff2[x] = buff2[x] ^ buff1[x]; 
 322                 des_dec(&buff2, &buff2, skey->data); 
 323                 memcpy(cmd+10,buff2,8); 
 325                 for (int x = 0; x < 8; x++) { 
 326                     buff3[x] = buff3[x] ^ buff2[x]; 
 328                 des_dec(&buff3, &buff3, skey->data); 
 329                 memcpy(cmd+18,buff3,8); 
 331                 // The command always times out on the first attempt, this will retry until a response 
 335                     len = DesfireAPDU(cmd,26,resp); 
 340                 cmd_send(CMD_ACK
,1,0,0,skey
->data
,8); 
 343                 DbpString("Authetication failed."); 
 352                         //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); 
 357                         uint8_t keybytes
[16] = {0x00}; 
 358                         if (datain
[1] == 0xff){ 
 359                                 memcpy(keybytes
,PICC_MASTER_KEY16
,16);  
 361                                 memcpy(keybytes
, datain
+1, datalen
); 
 364                         struct desfire_key defaultkey 
= {0x00}; 
 365                         desfirekey_t key 
= &defaultkey
; 
 366                         Desfire_aes_key_new( keybytes
, key
); 
 369                         if ( AesCtxIni(&ctx
, IV
, key
->data
, KEY128
, CBC
) < 0 ){ 
 370                                 if( MF_DBGLEVEL 
>= 4) { 
 371                                         Dbprintf("AES context failed to init"); 
 377                         cmd
[0] = AUTHENTICATE_AES
; 
 378                         cmd
[1] = 0x00;  //keynumber 
 379                         len 
= DesfireAPDU(cmd
, 2, resp
); 
 381                                 if (MF_DBGLEVEL 
>= MF_DBG_ERROR
) { 
 382                                         DbpString("Authentication failed. Card timeout."); 
 388                         memcpy( encRndB
, resp
+3, 16); 
 390                         // dekryptera tagnonce. 
 391                         AesDecrypt(&ctx
, encRndB
, decRndB
, 16); 
 393                         memcpy(both
, nonce
,16); 
 394                         memcpy(both
+16, decRndB 
,16 ); 
 395                         AesEncrypt(&ctx
, both
, encBoth
, 32 ); 
 397                         cmd
[0] = ADDITIONAL_FRAME
; 
 398                         memcpy(cmd
+1, encBoth
, 32 ); 
 400                         len 
= DesfireAPDU(cmd
, 33, resp
);  // 1 + 32 == 33 
 402                                 if (MF_DBGLEVEL 
>= MF_DBG_ERROR
) { 
 403                                         DbpString("Authentication failed. Card timeout."); 
 409                         if ( resp
[2] == 0x00 ){ 
 410                                 // Create AES Session key                
 411                                 struct desfire_key sessionKey 
= {0}; 
 412                                 desfirekey_t skey 
= &sessionKey
; 
 413                                 Desfire_session_key_new( nonce
, decRndB 
, key
, skey 
); 
 414                                 print_result("SESSION : ", skey
->data
, 16); 
 416                                 DbpString("Authetication failed."); 
 425         cmd_send(CMD_ACK
,1,len
,0,resp
,len
); 
 428 // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) 
 429 // cmd  =  cmd bytes to send 
 430 // cmd_len = length of cmd 
 431 // dataout = pointer to response data array 
 432 int DesfireAPDU(uint8_t *cmd
, size_t cmd_len
, uint8_t *dataout
){ 
 435         size_t wrappedLen 
= 0; 
 436         uint8_t wCmd
[USB_CMD_DATA_SIZE
] = {0}; 
 438         uint8_t resp
[MAX_FRAME_SIZE
]; 
 439     uint8_t par
[MAX_PARITY_SIZE
]; 
 441         wrappedLen 
= CreateAPDU( cmd
, cmd_len
, wCmd
); 
 443         if (MF_DBGLEVEL 
>= 4) { 
 444                 print_result("WCMD <--: ", wCmd
, wrappedLen
);    
 446         ReaderTransmit( wCmd
, wrappedLen
, NULL
); 
 448         len 
= ReaderReceive(resp
, par
); 
 451                 if (MF_DBGLEVEL 
>= 4) { 
 454                 return FALSE
; //DATA LINK ERROR 
 456         // if we received an I- or R(ACK)-Block with a block number equal to the 
 457         // current block number, toggle the current block number 
 458         else if (len 
>= 4 // PCB+CID+CRC = 4 bytes 
 459                  && ((resp
[0] & 0xC0) == 0 // I-Block 
 460                      || (resp
[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 
 461                  && (resp
[0] & 0x01) == pcb_blocknum
) // equal block numbers 
 463                 pcb_blocknum 
^= 1;  //toggle next block  
 466         memcpy(dataout
, resp
, len
); 
 471 size_t CreateAPDU( uint8_t *datain
, size_t len
, uint8_t *dataout
){ 
 473         size_t cmdlen 
= MIN(len
+4, USB_CMD_DATA_SIZE
-1); 
 476         memset(cmd
, 0, cmdlen
); 
 478         cmd
[0] = 0x0A;  //  0x0A = skicka cid,  0x02 = ingen cid. Särskilda bitar // 
 479         cmd
[0] |= pcb_blocknum
; // OR the block number into the PCB      
 480         cmd
[1] = 0x00;  //  CID: 0x00 //TODO: allow multiple selected cards 
 482         memcpy(cmd
+2, datain
, len
); 
 483         AppendCrc14443a(cmd
, len
+2); 
 485         memcpy(dataout
, cmd
, cmdlen
); 
 490         // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ 
 491         // crc_update(&desfire_crc32, addr, addr_sz); 
 492         // crc_update(&desfire_crc32, byte, 8); 
 493         // uint32_t crc = crc_finish(&desfire_crc32); 
 497         ReaderTransmit(deselect_cmd
, 3 , NULL
); 
 498         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 502 void OnError(uint8_t reason
){ 
 504         ReaderTransmit(deselect_cmd
, 3 , NULL
); 
 505         FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
); 
 506         cmd_send(CMD_ACK
,0,reason
,0,0,0);