X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/35147d51e3961db75a852368fffa31006da90199..75465377b93c9a27450a186342e9cfd2a84b4173:/armsrc/mifaredesfire.c diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index d3b04fb0..60f5ec03 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -6,42 +6,117 @@ #define NOT_YET_AUTHENTICATED 255 #define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5) +// the block number for the ISO14443-4 PCB +uint8_t pcb_blocknum = 0; +// Deselect card by sending a s-block. the crc is precalced for speed +static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; + //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 }; /* PCB CID CMD PAYLOAD */ //static uint8_t __res[MAX_FRAME_SIZE]; -void MifareDesfireGetInformation(){ +bool InitDesfireCard(){ + + // Make sure it is off. +// FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +// SpinDelay(300); + + byte_t cardbuf[USB_CMD_DATA_SIZE]; + memset(cardbuf,0,sizeof(cardbuf)); + + iso14a_set_tracing(TRUE); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf; + int len = iso14443a_select_card(NULL,card,NULL); + + if (!len) { + if (MF_DBGLEVEL >= 1) { + Dbprintf("Can't select card"); + } + OnError(); + return false; + } + return true; +} - uint8_t len = 0; +// ARG0 flag enums +enum { + NONE = 0x00, + INIT = 0x01, + DISCONNECT = 0x02, + FOO = 0x04, + BAR = 0x08, +} CmdOptions ; + +void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ + + /* ARG0 contains flags. + 0x01 = init card. + 0x02 = No Disconnect + 0x03 + */ + uint8_t flags = arg0; + size_t datalen = arg1; uint8_t resp[RECV_RES_SIZE]; - uint8_t dataout[RECV_CMD_SIZE]; - byte_t buf[RECV_RES_SIZE]; + memset(resp,0,sizeof(resp)); + + if (MF_DBGLEVEL >= 4) { + Dbprintf(" flags : %02X", flags); + Dbprintf(" len : %02X", datalen); + print_result(" RX : ", datain, datalen); + } + + if ( flags & INIT ){ + if ( !InitDesfireCard() ) + return; + } + + int len = DesfireAPDU(datain, datalen, resp); + print_result(" <--: ", resp, len); + if ( !len ) { + if (MF_DBGLEVEL >= 4) { + print_result("ERR <--: ", resp, len); + } + OnError(); + return; + } + + // reset the pcb_blocknum, + pcb_blocknum = 0; + + if ( flags & DISCONNECT ) + OnSuccess(); + + cmd_send(CMD_ACK,1,len,0,resp,len); +} + +void MifareDesfireGetInformation(){ + + int len = 0; + uint8_t resp[USB_CMD_DATA_SIZE]; + uint8_t dataout[USB_CMD_DATA_SIZE]; + byte_t cardbuf[USB_CMD_DATA_SIZE]; memset(resp,0,sizeof(resp)); memset(dataout,0, sizeof(dataout)); - memset(buf,0,sizeof(buf)); + memset(cardbuf,0,sizeof(cardbuf)); /* 1 = PCB 1 2 = cid 2 3 = desfire command 3 4-5 = crc 4 key - 5-6 crc - + 5-6 crc PCB == 0x0A because sending CID byte. - CID == 0x00 first card? - + CID == 0x00 first card? */ - uint8_t cmd1[] = {0x0a,0x00,GET_VERSION, 0x00, 0x00 }; - uint8_t cmd2[] = {0x0a,0x00,GET_KEY_VERSION, 0x00, 0x00, 0x00 }; - iso14a_clear_trace(); iso14a_set_tracing(TRUE); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); // card select - information - iso14a_card_select_t *card = (iso14a_card_select_t*)buf; + iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf; byte_t isOK = iso14443a_select_card(NULL, card, NULL); if (isOK != 1) { if (MF_DBGLEVEL >= 1) { @@ -51,45 +126,42 @@ void MifareDesfireGetInformation(){ return; } - memcpy(dataout,card->uid,7); LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - // GET INFORMATION - AppendCrc14443a(cmd1, 3); - ReaderTransmit(cmd1, sizeof(cmd1), NULL); - len = ReaderReceive(resp); - if ( resp[2] != ADDITIONAL_FRAME) { + uint8_t cmd[] = {GET_VERSION}; + size_t cmd_len = sizeof(cmd); + + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { print_result("ERROR <--: ", resp, len); OnError(); return; } - + + LED_A_OFF(); + LED_B_ON(); memcpy(dataout+7,resp+3,7); // ADDITION_FRAME 1 - ++cmd1[0]; - cmd1[2] = ADDITIONAL_FRAME; - AppendCrc14443a(cmd1, 3); - ReaderTransmit(cmd1, sizeof(cmd1), NULL); - len = ReaderReceive(resp); - - if ( resp[2] != ADDITIONAL_FRAME) { + cmd[0] = ADDITIONAL_FRAME; + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { print_result("ERROR <--: ", resp, len); OnError(); return; } + + LED_B_OFF(); + LED_C_ON(); memcpy(dataout+7+7,resp+3,7); // ADDITION_FRAME 2 - --cmd1[0]; - AppendCrc14443a(cmd1, 3); - ReaderTransmit(cmd1, sizeof(cmd1), NULL); - len = ReaderReceive(resp); - if ( resp[2] != OPERATION_OK) { + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { print_result("ERROR <--: ", resp, len); OnError(); return; @@ -97,50 +169,25 @@ void MifareDesfireGetInformation(){ memcpy(dataout+7+7+7,resp+3,14); - // GET MASTER KEYSETTINGS - cmd1[2] = GET_KEY_SETTINGS; - AppendCrc14443a(cmd1, 3); - ReaderTransmit(cmd1, sizeof(cmd1), NULL); - len = ReaderReceive(resp); - if (len){ - memcpy(dataout+7+7+7+14,resp+3,2); - } - - - // GET MASTER KEY VERSION - AppendCrc14443a(cmd2, 4); - ReaderTransmit(cmd2, sizeof(cmd2), NULL); - len = ReaderReceive(resp); - if (len){ - memcpy(dataout+7+7+7+14+2,resp+3,1); - } - - // GET FREE MEMORY - cmd1[2] = GET_FREE_MEMORY; - AppendCrc14443a(cmd1, 3); - ReaderTransmit(cmd1, sizeof(cmd1), NULL); - len = ReaderReceive(resp); - if (len){ - memcpy(dataout+7+7+7+14+2+1,resp+3,3); - } - cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); + + // reset the pcb_blocknum, + pcb_blocknum = 0; OnSuccess(); } void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){ uint8_t null_key_data[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t new_key_data[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; - int res; + //uint8_t new_key_data[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + int res = 0; - MifareDESFireKey default_key = mifare_desfire_des_key_new_with_version (null_key_data); + desfirekey_t default_key = Desfire_des_key_new_with_version (null_key_data); - res = mifare_desfire_select_application (tags[i], aid); + // res = Desfire_select_application (tags[i], aid); if (res < 0) { - freefare_perror (tags[i], "mifare_desfire_select_application"); - error = EXIT_FAILURE; - break; + print_result("default key: ", default_key->data, 24 ); + return; } return; @@ -246,7 +293,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain real_cmd[2] = AUTHENTICATE_AES; real_cmd[3] = keyno; - AppendCrc14443a(real_cmd, 2); + AppendCrc14443a(real_cmd, 4); ReaderTransmit(real_cmd, sizeof(real_cmd), NULL); int len = ReaderReceive(resp); @@ -288,7 +335,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain real_cmd_A[1] = ADDITIONAL_FRAME; memcpy(real_cmd_A+2, encBoth, sizeof(encBoth) ); - AppendCrc14443a(real_cmd_A, sizeof(real_cmd_A)); + AppendCrc14443a(real_cmd_A, 34); ReaderTransmit(real_cmd_A, sizeof(real_cmd_A), NULL); len = ReaderReceive(resp); @@ -310,51 +357,60 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnSuccess(resp); } - -// desfire_cmd = enum DESFIRE_CMD in desfire.h -// cmd = pointer to -// dataout = point to array for response data. -int SendDesfireCommand(enum DESFIRE_CMD desfire_cmd,uint8_t *dataout, uint8_t fromscratch){ - - uint8_t resp[80]; - uint8_t len; +// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) +// cmd = cmd bytes to send +// cmd_len = length of cmd +// dataout = pointer to response data array +int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ - if ( fromscratch){ - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - // power up the field - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // select the card - iso14443a_select_card(NULL, NULL, NULL); - } - - // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) - uint8_t real_cmd[4]; - real_cmd[0] = 0x02; - real_cmd[1] = desfire_cmd; - AppendCrc14443a(real_cmd, 2); - ReaderTransmit(real_cmd, sizeof(real_cmd), NULL); - len = ReaderReceive(resp); - if(!len) - return -1; //DATA LINK ERROR - - if ( fromscratch){ - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + uint32_t status = 0; + size_t wrappedLen = 0; + uint8_t wCmd[USB_CMD_DATA_SIZE]; + + wrappedLen = CreateAPDU( cmd, cmd_len, wCmd); + + if (MF_DBGLEVEL >= 4) { + print_result("WCMD <--: ", wCmd, wrappedLen); } + ReaderTransmit( wCmd, wrappedLen, NULL); - enum DESFIRE_STATUS status = resp[1]; - //1 bytes iso, 1 byte status, in the end: 2 bytes crc - if ( status == OPERATION_OK || status == ADDITIONAL_FRAME) { - memcpy(dataout, resp+2, 2); - return len; - } - else { - Dbprintf("unexpected desfire response: %X (to %X)", status, desfire_cmd); - return -status; - } + status = ReaderReceive(dataout); + + if(!status){ + return FALSE; //DATA LINK ERROR + } + // if we received an I- or R(ACK)-Block with a block number equal to the + // current block number, toggle the current block number + else if (status >= 4 // PCB+CID+CRC = 4 bytes + && ((dataout[0] & 0xC0) == 0 // I-Block + || (dataout[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 + && (dataout[0] & 0x01) == pcb_blocknum) // equal block numbers + { + pcb_blocknum ^= 1; //toggle next block + } + return status; } +// CreateAPDU +size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){ + + size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); + + uint8_t cmd[cmdlen]; + memset(cmd, 0, cmdlen); + + cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar // + cmd[0] |= pcb_blocknum; // OR the block number into the PCB + cmd[1] = 0x00; // CID: 0x00 //FIXME: allow multiple selected cards + + memcpy(cmd+2, datain, len); + AppendCrc14443a(cmd, len+2); + + memcpy(dataout, cmd, cmdlen); + + return cmdlen; +} + // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ // crc_update(&desfire_crc32, addr, addr_sz); // crc_update(&desfire_crc32, byte, 8); @@ -472,7 +528,7 @@ int mifare_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ if (len == 11){ if (MF_DBGLEVEL >= 1) { - Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + Dbprintf("Auth2 Resp: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buffer[0],buffer[1],buffer[2],buffer[3],buffer[4], buffer[5],buffer[6],buffer[7],buffer[8],buffer[9], buffer[10]); @@ -513,56 +569,17 @@ void MifareDES_Auth2(uint32_t arg0, uint8_t *datain){ LEDsoff(); } -// CreateAPDU -uint8_t* CreateAPDU( uint8_t *datain, size_t len){ - - len = MIN(len, USB_CMD_DATA_SIZE); - - uint8_t tmpcmd[len]; - uint8_t *cmd = tmpcmd; - memset(cmd, 0, len); - cmd[0] = 0x0a; - cmd[1] = 0x00; - - memcpy(cmd, datain,len); - AppendCrc14443a(cmd, len+2); - return cmd; -} - -void SelectCard(){ - - uint8_t resp[RECV_RES_SIZE]; - byte_t buf[RECV_RES_SIZE]; - - memset(resp,0,sizeof(resp)); - memset(buf,0,sizeof(buf)); - - iso14a_clear_trace(); - iso14a_set_tracing(TRUE); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - // card select - information - iso14a_card_select_t *card = (iso14a_card_select_t*)buf; - byte_t isOK = iso14443a_select_card(NULL, card, NULL); - if (isOK != 1) { - if (MF_DBGLEVEL >= 1) { - Dbprintf("Can't select card"); - } - OnError(); - return; - } -} - void OnSuccess(){ - // Deselect card by sending a s-block. the crc is precalced for speed - uint8_t cmd[] = {0xc2,0xe0,0xb4}; - ReaderTransmit(cmd, sizeof(cmd), NULL); + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } void OnError(){ - cmd_send(CMD_ACK,0,0,0,0,0); + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,0,0,0,0); LEDsoff(); }