From 79a73ab2d1a63fdf75d42774e160a9335d893416 Mon Sep 17 00:00:00 2001 From: "roel@libnfc.org" Date: Wed, 27 Feb 2013 13:23:38 +0000 Subject: [PATCH] fixed USB GPIO bug reported by gregy, and fixed 'hf 14a reader' command --- armsrc/apps.h | 2 +- armsrc/cmd.c | 6 +-- armsrc/cmd.h | 2 +- armsrc/iso14443a.c | 99 +++++++++++++++++++++++++++++----------------- armsrc/usb_cdc.c | 29 +++++++------- client/cmdhf14a.c | 40 +++++++++---------- client/cmdmain.c | 14 ++++--- 7 files changed, 111 insertions(+), 81 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index 94bc5b04..5543d585 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -183,7 +183,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd); // cmd.h bool cmd_receive(UsbCommand* cmd); -bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* data, size_t len); +bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len); /// util.h diff --git a/armsrc/cmd.c b/armsrc/cmd.c index c414bc39..ff5c4f81 100644 --- a/armsrc/cmd.c +++ b/armsrc/cmd.c @@ -1,7 +1,7 @@ /* * Proxmark send and receive commands * - * Copyright (c) 2010, Roel Verdult + * Copyright (c) 2012, Roel Verdult * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,7 +52,7 @@ bool cmd_receive(UsbCommand* cmd) { return true; } -bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* data, size_t len) { +bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len) { UsbCommand txcmd; // Compose the outgoing command frame @@ -63,7 +63,7 @@ bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE if (data && len) { - memcpy(txcmd.d.asBytes,data,MIN(len,USB_CMD_DATA_SIZE)); + memcpy(txcmd.d.asBytes,(byte_t*)data,MIN(len,USB_CMD_DATA_SIZE)); } // Send frame and make sure all bytes are transmitted diff --git a/armsrc/cmd.h b/armsrc/cmd.h index c10a534f..b330a219 100644 --- a/armsrc/cmd.h +++ b/armsrc/cmd.h @@ -38,7 +38,7 @@ #include "usb_cdc.h" bool cmd_receive(UsbCommand* cmd); -bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, byte_t* data, size_t len); +bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len); #endif // _PROXMARK_CMD_H_ diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d2ebb0c6..7c1db14b 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1636,31 +1636,36 @@ int ReaderReceivePar(uint8_t* receivedAnswer, uint32_t * parptr) /* performs iso14443a anticolision procedure * fills the uid pointer unless NULL * fills resp_data unless NULL */ -int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, uint32_t * cuid_ptr) { +int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) { uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP uint8_t sel_all[] = { 0x93,0x20 }; uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 - uint8_t* resp = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET); // was 3560 - tied to other size changes + byte_t uid_resp[4]; + size_t uid_resp_len; uint8_t sak = 0x04; // cascade uid int cascade_level = 0; - int len; - - // clear uid - memset(uid_ptr, 0, 12); - + // Broadcast for a card, WUPA (0x52) will force response from all cards in the field ReaderTransmitShort(wupa); // Receive the ATQA if(!ReaderReceive(resp)) return 0; // Dbprintf("atqa: %02x %02x",resp[0],resp[1]); - if(resp_data) - memcpy(resp_data->atqa, resp, 2); + if(p_hi14a_card) { + memcpy(p_hi14a_card->atqa, resp, 2); + p_hi14a_card->uidlen = 0; + memset(p_hi14a_card->uid,0,10); + } + // clear uid + if (uid_ptr) { + memset(uid_ptr,0,10); + } + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. @@ -1672,12 +1677,16 @@ int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, u // SELECT_ALL ReaderTransmit(sel_all,sizeof(sel_all)); if (!ReaderReceive(resp)) return 0; -// Dbprintf("uid: %02x %02x %02x %02x",resp[0],resp[1],resp[2],resp[3]); - - if(uid_ptr) memcpy(uid_ptr + cascade_level*4, resp, 4); - + + // First backup the current uid + memcpy(uid_resp,resp,4); + uid_resp_len = 4; + // Dbprintf("uid: %02x %02x %02x %02x",uid_resp[0],uid_resp[1],uid_resp[2],uid_resp[3]); + // calculate crypto UID - if(cuid_ptr) *cuid_ptr = bytes_to_num(resp, 4); + if(cuid_ptr) { + *cuid_ptr = bytes_to_num(uid_resp, 4); + } // Construct SELECT UID command memcpy(sel_uid+2,resp,5); @@ -1687,34 +1696,47 @@ int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, u // Receive the SAK if (!ReaderReceive(resp)) return 0; sak = resp[0]; + + // Test if more parts of the uid are comming + if ((sak & 0x04) && uid_resp[0] == 0x88) { + // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: + // http://www.nxp.com/documents/application_note/AN10927.pdf + memcpy(uid_ptr, uid_ptr + 1, 3); + uid_resp_len = 3; + } + + if(uid_ptr) { + memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); + } + + if(p_hi14a_card) { + memcpy(p_hi14a_card->uid + (cascade_level*3), uid_resp, uid_resp_len); + p_hi14a_card->uidlen += uid_resp_len; + } } - if(resp_data) { - resp_data->sak = sak; - resp_data->ats_len = 0; - } - //-- this byte not UID, it CT. http://www.nxp.com/documents/application_note/AN10927.pdf page 3 - if (uid_ptr[0] == 0x88) { - memcpy(uid_ptr, uid_ptr + 1, 7); - uid_ptr[7] = 0; + + if(p_hi14a_card) { + p_hi14a_card->sak = sak; + p_hi14a_card->ats_len = 0; } - if( (sak & 0x20) == 0) + if( (sak & 0x20) == 0) { return 2; // non iso14443a compliant tag + } // Request for answer to select - if(resp_data) { // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!! + if(p_hi14a_card) { // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!! AppendCrc14443a(rats, 2); ReaderTransmit(rats, sizeof(rats)); if (!(len = ReaderReceive(resp))) return 0; - memcpy(resp_data->ats, resp, sizeof(resp_data->ats)); - resp_data->ats_len = len; + memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats)); + p_hi14a_card->ats_len = len; } // reset the PCB block number iso14_pcb_blocknum = 0; - return 1; } @@ -1774,18 +1796,20 @@ void ReaderIso14443a(UsbCommand * c) iso14a_command_t param = c->arg[0]; uint8_t * cmd = c->d.asBytes; size_t len = c->arg[1]; - uint32_t arg0; - byte_t buf[48]; + uint32_t arg0 = 0; + byte_t buf[USB_CMD_DATA_SIZE]; iso14a_clear_trace(); iso14a_set_tracing(true); - if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(1); + if(param & ISO14A_REQUEST_TRIGGER) { + iso14a_set_trigger(1); + } if(param & ISO14A_CONNECT) { iso14443a_setup(); - arg0 = iso14443a_select_card(buf, (iso14a_card_select_t *)(buf+12), NULL); - cmd_send(CMD_ACK,arg0,0,0,buf,48); + arg0 = iso14443a_select_card(NULL,(iso14a_card_select_t*)buf,NULL); + cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(iso14a_card_select_t)); // UsbSendPacket((void *)ack, sizeof(UsbCommand)); } @@ -1799,7 +1823,7 @@ void ReaderIso14443a(UsbCommand * c) if(param & ISO14A_APDU) { arg0 = iso14_apdu(cmd, len, buf); - cmd_send(CMD_ACK,arg0,0,0,buf,48); + cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf)); // UsbSendPacket((void *)ack, sizeof(UsbCommand)); } @@ -1811,13 +1835,16 @@ void ReaderIso14443a(UsbCommand * c) ReaderTransmit(cmd,len); arg0 = ReaderReceive(buf); // UsbSendPacket((void *)ack, sizeof(UsbCommand)); - cmd_send(CMD_ACK,arg0,0,0,buf,48); + cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf)); } - if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(0); + if(param & ISO14A_REQUEST_TRIGGER) { + iso14a_set_trigger(0); + } - if(param & ISO14A_NO_DISCONNECT) + if(param & ISO14A_NO_DISCONNECT) { return; + } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/usb_cdc.c b/armsrc/usb_cdc.c index b8aee5a4..fa1f849e 100644 --- a/armsrc/usb_cdc.c +++ b/armsrc/usb_cdc.c @@ -34,6 +34,7 @@ #include "usb_cdc.h" #include "util.h" +#include "config_gpio.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -217,12 +218,12 @@ byte_t btConnection = 0; byte_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; //*---------------------------------------------------------------------------- -//* \fn AT91F_USB_Disable +//* \fn usb_disable //* \brief This function deactivates the USB device //*---------------------------------------------------------------------------- void usb_disable() { - // Disconnect and reconnect USB controller for 100ms - AT91C_BASE_PIOA->PIO_ODR = AT91C_PIO_PA24; + // Disconnect the USB device + AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; SpinDelay(100); // Clear all lingering interrupts @@ -232,7 +233,7 @@ void usb_disable() { } //*---------------------------------------------------------------------------- -//* \fn AT91F_USB_Enable +//* \fn usb_enable //* \brief This function Activates the USB device //*---------------------------------------------------------------------------- void usb_enable() { @@ -246,25 +247,25 @@ void usb_enable() { // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO // Set in PIO mode and Configure in Output - AT91C_BASE_PIOA->PIO_PER = AT91C_PIO_PA16; // Set in PIO mode - AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA16; // Configure as Output + AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode + AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output - // Clear for set the Pul up resistor - AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA16; + // Clear for set the Pullup resistor + AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU; - // Disconnect and USB device + // Disconnect and reconnect USB controller for 100ms usb_disable(); // Wait for a short while SpinDelay(100); // Reconnect USB reconnect - AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA24; - AT91C_BASE_PIOA->PIO_OER = AT91C_PIO_PA24; + AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; + AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; } //*---------------------------------------------------------------------------- -//* \fn AT91F_UDP_IsConfigured +//* \fn usb_check //* \brief Test if the device is configured and handle enumeration //*---------------------------------------------------------------------------- bool usb_check() { @@ -295,7 +296,7 @@ bool usb_poll() } //*---------------------------------------------------------------------------- -//* \fn AT91F_UDP_Read +//* \fn usb_read //* \brief Read available data from Endpoint OUT //*---------------------------------------------------------------------------- uint32_t usb_read(byte_t* data, size_t len) { @@ -328,7 +329,7 @@ uint32_t usb_read(byte_t* data, size_t len) { } //*---------------------------------------------------------------------------- -//* \fn AT91F_CDC_Write +//* \fn usb_write //* \brief Send through endpoint 2 //*---------------------------------------------------------------------------- uint32_t usb_write(const byte_t* data, const size_t len) { diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index a82c7e35..79273040 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -168,8 +168,8 @@ int CmdHF14AReader(const char *Cmd) UsbCommand resp; WaitForResponse(CMD_ACK,&resp); - uint8_t * uid = resp.d.asBytes; - iso14a_card_select_t * card = (iso14a_card_select_t *)(uid + 12); + iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes; + uint8_t * uid = card->uid; if(resp.arg[0] == 0) { PrintAndLog("iso14443a card select failed"); @@ -177,24 +177,24 @@ int CmdHF14AReader(const char *Cmd) } PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]); - PrintAndLog(" UID : %s", sprint_hex(uid, 12)); + PrintAndLog(" UID : %s", sprint_hex(card->uid, card->uidlen)); PrintAndLog(" SAK : %02x [%d]", card->sak, resp.arg[0]); switch (card->sak) { - case 0x00: PrintAndLog(" SAK : NXP MIFARE Ultralight | Ultralight C"); break; - case 0x04: PrintAndLog(" SAK : NXP MIFARE (various !DESFire !DESFire EV1)"); break; - - case 0x08: PrintAndLog(" SAK : NXP MIFARE CLASSIC 1k | Plus 2k"); break; - case 0x09: PrintAndLog(" SAK : NXP MIFARE Mini 0.3k"); break; - case 0x10: PrintAndLog(" SAK : NXP MIFARE Plus 2k"); break; - case 0x11: PrintAndLog(" SAK : NXP MIFARE Plus 4k"); break; - case 0x18: PrintAndLog(" SAK : NXP MIFARE Classic 4k | Plus 4k"); break; - case 0x20: PrintAndLog(" SAK : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break; - case 0x24: PrintAndLog(" SAK : NXP MIFARE DESFire | DESFire EV1"); break; - case 0x28: PrintAndLog(" SAK : JCOP31 or JCOP41 v2.3.1"); break; - case 0x38: PrintAndLog(" SAK : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; - case 0x88: PrintAndLog(" SAK : Infineon MIFARE CLASSIC 1K"); break; - case 0x98: PrintAndLog(" SAK : Gemplus MPCOS"); break; + case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break; + case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; + + case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k"); break; + case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break; + case 0x10: PrintAndLog("TYPE : NXP MIFARE Plus 2k"); break; + case 0x11: PrintAndLog("TYPE : NXP MIFARE Plus 4k"); break; + case 0x18: PrintAndLog("TYPE : NXP MIFARE Classic 4k | Plus 4k"); break; + case 0x20: PrintAndLog("TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break; + case 0x24: PrintAndLog("TYPE : NXP MIFARE DESFire | DESFire EV1"); break; + case 0x28: PrintAndLog("TYPE : JCOP31 or JCOP41 v2.3.1"); break; + case 0x38: PrintAndLog("TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; + case 0x88: PrintAndLog("TYPE : Infineon MIFARE CLASSIC 1K"); break; + case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break; default: ; } if(resp.arg[0] == 1) { @@ -314,9 +314,9 @@ int CmdHF14AReader(const char *Cmd) } } } - } - else - PrintAndLog("proprietary non-iso14443a card found, RATS not supported"); + } else { + PrintAndLog("proprietary non iso14443a-4 card found, RATS not supported"); + } return resp.arg[0]; } diff --git a/client/cmdmain.c b/client/cmdmain.c index 2fdaabc1..62eef122 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -100,13 +100,15 @@ void CommandReceived(char *Cmd) { //----------------------------------------------------------------------------- void UsbCommandReceived(UsbCommand *UC) { + /* // Debug - // printf("UsbCommand length[len=%d]\n",sizeof(UsbCommand)); - // printf(" cmd[len=%d]: %x\n",sizeof(UC->cmd),UC->cmd); - // printf(" arg0[len=%d]: %x\n",sizeof(UC->arg[0]),UC->arg[0]); - // printf(" arg1[len=%d]: %x\n",sizeof(UC->arg[1]),UC->arg[1]); - // printf(" arg2[len=%d]: %x\n",sizeof(UC->arg[2]),UC->arg[2]); - // printf(" data[len=%d]: %02x%02x%02x...\n",sizeof(UC->d.asBytes),UC->d.asBytes[0],UC->d.asBytes[1],UC->d.asBytes[2]); + printf("UsbCommand length[len=%zd]\n",sizeof(UsbCommand)); + printf(" cmd[len=%zd]: %llx\n",sizeof(UC->cmd),UC->cmd); + printf(" arg0[len=%zd]: %llx\n",sizeof(UC->arg[0]),UC->arg[0]); + printf(" arg1[len=%zd]: %llx\n",sizeof(UC->arg[1]),UC->arg[1]); + printf(" arg2[len=%zd]: %llx\n",sizeof(UC->arg[2]),UC->arg[2]); + printf(" data[len=%zd]: %02x%02x%02x...\n",sizeof(UC->d.asBytes),UC->d.asBytes[0],UC->d.asBytes[1],UC->d.asBytes[2]); + */ // printf("%s(%x) current cmd = %x\n", __FUNCTION__, c->cmd, current_command); // If we recognize a response, return to avoid further processing -- 2.39.2