From e2012d1bd33ae33703da1c1648f35964472823be Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 21 Jul 2015 23:18:51 +0200 Subject: [PATCH 01/14] Implemented 'hw status' and 'hw ping', put back client-side cacheing of 'hw version' --- armsrc/BigBuf.c | 10 ++++++ armsrc/BigBuf.h | 2 +- armsrc/appmain.c | 21 ++++++++++++- armsrc/fpgaloader.c | 8 +++++ armsrc/fpgaloader.h | 1 + armsrc/lfsampling.c | 2 +- armsrc/lfsampling.h | 4 +++ armsrc/mifareutil.h | 1 + client/cmdhw.c | 61 ++++++++++++++++++++++++++++--------- client/lualibs/commands.lua | 3 +- include/usb_cmd.h | 2 ++ 11 files changed, 96 insertions(+), 19 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 510f7bef..a938d5c6 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -88,6 +88,16 @@ void BigBuf_free_keep_EM(void) } } +void BigBuf_print_status(void) +{ + Dbprintf("Memory"); + Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); + Dbprintf(" BigBuf_hi .............%d", BigBuf_hi); + Dbprintf("Tracing"); + Dbprintf(" tracing ................%d", tracing); + Dbprintf(" traceLen ...............%d", traceLen); +} + // return the maximum trace length (i.e. the unallocated size of BigBuf) uint16_t BigBuf_max_traceLen(void) diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 0e2f1744..05b4180e 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -28,7 +28,7 @@ extern void BigBuf_Clear(void); extern uint8_t *BigBuf_malloc(uint16_t); extern void BigBuf_free(void); extern void BigBuf_free_keep_EM(void); - +extern void BigBuf_print_status(void); extern uint16_t BigBuf_get_traceLen(void); extern void clear_trace(); extern void set_tracing(bool enable); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7aa353b2..23540806 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -25,6 +25,7 @@ #include #include "lfsampling.h" #include "BigBuf.h" +#include "mifareutil.h" #ifdef WITH_LCD #include "LCD.h" #endif @@ -297,6 +298,19 @@ void SendVersion(void) uint32_t compressed_data_section_size = common_area.arg1; cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); } +/** + * Prints runtime information about the PM3. +**/ +void SendStatus(void) +{ + BigBuf_print_status(); + Fpga_print_status(); + printConfig(); //LF Sampling config + Dbprintf("Various"); + Dbprintf(" MF_DBGLEVEL......%d", MF_DBGLEVEL); + Dbprintf(" ToSendMax........%d",ToSendMax); + Dbprintf(" ToSendBit........%d",ToSendBit); +} #if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF) @@ -1143,7 +1157,12 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_VERSION: SendVersion(); break; - + case CMD_STATUS: + SendStatus(); + break; + case CMD_PING: + cmd_send(CMD_ACK,0,0,0,0,0); + break; #ifdef WITH_LCD case CMD_LCD_RESET: LCDReset(); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 16fed7c5..308dda8c 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -558,3 +558,11 @@ void SetAdcMuxFor(uint32_t whichGpio) HIGH(whichGpio); } + +void Fpga_print_status(void) +{ + Dbprintf("Fgpa"); + if(downloaded_bitstream == FPGA_BITSTREAM_HF) Dbprintf(" mode.............HF"); + else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf(" mode.............LF"); + else Dbprintf(" mode.............%d", downloaded_bitstream); +} diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 0bad3809..52d6c677 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -17,6 +17,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len); void FpgaSetupSsc(void); void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, int len); +void Fpga_print_status(); #define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; void SetAdcMuxFor(uint32_t whichGpio); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 662ebf24..6e783769 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -17,7 +17,7 @@ sample_config config = { 1, 8, 1, 95, 0 } ; void printConfig() { - Dbprintf("Sampling config: "); + Dbprintf("LF Sampling config: "); Dbprintf(" [q] divisor: %d ", config.divisor); Dbprintf(" [b] bps: %d ", config.bits_per_sample); Dbprintf(" [d] decimation: %d ", config.decimation); diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 6c671ec8..7d3925cd 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -56,4 +56,8 @@ void LFSetupFPGAForADC(int divisor, bool lf_field); void setSamplingConfig(sample_config *sc); sample_config * getSamplingConfig(); + +void printConfig(); + + #endif // LFSAMPLING_H diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 85a34ef6..7a09ce64 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -8,6 +8,7 @@ //----------------------------------------------------------------------------- // code for work with mifare cards. //----------------------------------------------------------------------------- +#include "crapto1.h" #ifndef __MIFAREUTIL_H #define __MIFAREUTIL_H diff --git a/client/cmdhw.c b/client/cmdhw.c index 2b6f9518..23b6ce21 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -405,33 +405,64 @@ int CmdTune(const char *Cmd) int CmdVersion(const char *Cmd) { + clearCommandBuffer(); UsbCommand c = {CMD_VERSION}; - UsbCommand resp = {0, {0, 0, 0}}; + static UsbCommand resp = {0, {0, 0, 0}}; - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + PrintAndLog("Prox/RFID mark3 RFID instrument"); + PrintAndLog((char*)resp.d.asBytes); + lookupChipID(resp.arg[0], resp.arg[1]); + } + } else { + PrintAndLog("[[[ Cached information ]]]\n"); PrintAndLog("Prox/RFID mark3 RFID instrument"); PrintAndLog((char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); + PrintAndLog(""); } + return 0; +} +int CmdStatus(const char *Cmd) +{ + UsbCommand c = {CMD_STATUS}; + SendCommand(&c); + return 0; +} + +int CmdPing(const char *Cmd) +{ + clearCommandBuffer(); + UsbCommand resp; + UsbCommand c = {CMD_PING}; + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + PrintAndLog("Ping successfull"); + }else{ + PrintAndLog("Ping failed"); + } return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, - {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, - {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, - {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, - {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, - {"reset", CmdReset, 0, "Reset the Proxmark3"}, - {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, - {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, - {"tune", CmdTune, 0, "Measure antenna tuning"}, - {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, + {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, + {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, + {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, + {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, + {"reset", CmdReset, 0, "Reset the Proxmark3"}, + {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, + {"tune", CmdTune, 0, "Measure antenna tuning"}, + {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, + {"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"}, + {"ping", CmdPing, 0, "Test if the pm3 is responsive"}, + {NULL, NULL, 0, NULL} }; int CmdHW(const char *Cmd) diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 127508e6..64f16e44 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -20,7 +20,8 @@ local _commands = { CMD_BUFF_CLEAR = 0x0105, CMD_READ_MEM = 0x0106, CMD_VERSION = 0x0107, - + CMD_STATUS = 0x0108, + CMD_PING = 0x0109, --// For low-frequency tags CMD_READ_TI_TYPE = 0x0202, CMD_WRITE_TI_TYPE = 0x0203, diff --git a/include/usb_cmd.h b/include/usb_cmd.h index e45bf35e..f443e970 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -60,6 +60,8 @@ typedef struct{ #define CMD_BUFF_CLEAR 0x0105 #define CMD_READ_MEM 0x0106 #define CMD_VERSION 0x0107 +#define CMD_STATUS 0x0108 +#define CMD_PING 0x0109 // For low-frequency tags #define CMD_READ_TI_TYPE 0x0202 From 987dfb66e2982d229f0681f991b04e325613fc5f Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 21 Jul 2015 23:21:16 +0200 Subject: [PATCH 02/14] changelog docs --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 649b4d04..a8a5662e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,13 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ### Added - ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young) - -### Added - AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young) +- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) +- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman) ### Changed - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers) +- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi) ## [2.2.0][2015-07-12] From c89274cc60bf433cbf1091d9a6ca0b813ea9b224 Mon Sep 17 00:00:00 2001 From: Craig Young Date: Sat, 25 Jul 2015 14:35:14 -0400 Subject: [PATCH 03/14] Stand Alone Mode changes for NFC (part 2) --- CHANGELOG.md | 6 +- armsrc/appmain.c | 275 ++++++++++++++++++++++++++++----------------- armsrc/iso14443a.c | 1 - armsrc/mifarecmd.c | 8 +- 4 files changed, 185 insertions(+), 105 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 649b4d04..682d87eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,12 +6,14 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ### Added - ISO14443a stand-alone operation with ARM CFLAG="WITH_ISO14443a_StandAlone". This code can read & emulate two banks of 14a tag UIDs and write to "magic" cards (Craig Young) - -### Added - AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young) +- Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) +- Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman) ### Changed +- Revised workflow for StandAloneMode14a (Craig Young) - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers) +- 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi) ## [2.2.0][2015-07-12] diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7aa353b2..b5e7d7ea 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -25,6 +25,7 @@ #include #include "lfsampling.h" #include "BigBuf.h" +#include "mifareutil.h" #ifdef WITH_LCD #include "LCD.h" #endif @@ -297,6 +298,19 @@ void SendVersion(void) uint32_t compressed_data_section_size = common_area.arg1; cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); } +/** + * Prints runtime information about the PM3. +**/ +void SendStatus(void) +{ + BigBuf_print_status(); + Fpga_print_status(); + printConfig(); //LF Sampling config + Dbprintf("Various"); + Dbprintf(" MF_DBGLEVEL......%d", MF_DBGLEVEL); + Dbprintf(" ToSendMax........%d",ToSendMax); + Dbprintf(" ToSendBit........%d",ToSendBit); +} #if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF) @@ -329,11 +343,14 @@ void StandAloneMode14a() FpgaDownloadAndGo(FPGA_BITSTREAM_HF); int selected = 0; - int playing = 0; + int playing = 0, iGotoRecord = 0, iGotoClone = 0; int cardRead[OPTS] = {0}; uint8_t readUID[10] = {0}; uint32_t uid_1st[OPTS]={0}; uint32_t uid_2nd[OPTS]={0}; + uint32_t uid_tmp1 = 0; + uint32_t uid_tmp2 = 0; + iso14a_card_select_t hi14a_card[OPTS]; LED(selected + 1, 0); @@ -341,24 +358,17 @@ void StandAloneMode14a() { usb_poll(); WDT_HIT(); - - // Was our button held down or pressed? - int button_pressed = BUTTON_HELD(1000); SpinDelay(300); - // Button was held for a second, begin recording - if (button_pressed > 0 && cardRead[selected] == 0) + if (iGotoRecord == 1 || cardRead[selected] == 0) { + iGotoRecord = 0; LEDsoff(); LED(selected + 1, 0); LED(LED_RED2, 0); // record Dbprintf("Enabling iso14443a reader mode for [Bank: %u]...", selected); - - // wait for button to be released - while(BUTTON_PRESS()) - WDT_HIT(); /* need this delay to prevent catching some weird data */ SpinDelay(500); /* Code for reading from 14a tag */ @@ -369,22 +379,54 @@ void StandAloneMode14a() for ( ; ; ) { WDT_HIT(); - if (!iso14443a_select_card(uid, NULL, &cuid)) + if (BUTTON_PRESS()) { + if (cardRead[selected]) { + Dbprintf("Button press detected -- replaying card in bank[%d]", selected); + break; + } + else if (cardRead[(selected+1)%OPTS]) { + Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); + selected = (selected+1)%OPTS; + break; // playing = 1; + } + else { + Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); + SpinDelay(300); + } + } + if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid)) continue; else { Dbprintf("Read UID:"); Dbhexdump(10,uid,0); memcpy(readUID,uid,10*sizeof(uint8_t)); - uint8_t *dst = (uint8_t *)&uid_1st[selected]; + uint8_t *dst = (uint8_t *)&uid_tmp1; // Set UID byte order for (int i=0; i<4; i++) dst[i] = uid[3-i]; - dst = (uint8_t *)&uid_2nd[selected]; + dst = (uint8_t *)&uid_tmp2; for (int i=0; i<4; i++) dst[i] = uid[7-i]; - break; + if (uid_1st[(selected+1)%OPTS] == uid_tmp1 && uid_2nd[(selected+1)%OPTS] == uid_tmp2) { + Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); + } + else { + if (uid_tmp2) { + Dbprintf("Bank[%d] received a 7-byte UID",selected); + uid_1st[selected] = (uid_tmp1)>>8; + uid_2nd[selected] = (uid_tmp1<<24) + (uid_tmp2>>8); + } + else { + Dbprintf("Bank[%d] received a 4-byte UID",selected); + uid_1st[selected] = uid_tmp1; + uid_2nd[selected] = uid_tmp2; + } + break; + } } } + Dbprintf("ATQA = %02X%02X",hi14a_card[selected].atqa[0],hi14a_card[selected].atqa[1]); + Dbprintf("SAK = %02X",hi14a_card[selected].sak); LEDsoff(); LED(LED_GREEN, 200); LED(LED_ORANGE, 200); @@ -393,101 +435,101 @@ void StandAloneMode14a() LEDsoff(); LED(selected + 1, 0); - // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; + // Next state is replay: + playing = 1; cardRead[selected] = 1; - } - /* MF UID clone */ - else if (button_pressed > 0 && cardRead[selected] == 1) + /* MF Classic UID clone */ + else if (iGotoClone==1) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 250); + iGotoClone=0; + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 250); - // record - Dbprintf("Preparing to Clone card [Bank: %x]; uid: %08x", selected, uid_1st[selected]); + // record + Dbprintf("Preparing to Clone card [Bank: %x]; uid: %08x", selected, uid_1st[selected]); - // wait for button to be released - while(BUTTON_PRESS()) - { - // Delay cloning until card is in place - WDT_HIT(); - } - Dbprintf("Starting clone. [Bank: %u]", selected); - // need this delay to prevent catching some weird data - SpinDelay(500); - // Begin clone function here: - /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: - UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}}; - memcpy(c.d.asBytes, data, 16); - SendCommand(&c); + // wait for button to be released + while(BUTTON_PRESS()) + { + // Delay cloning until card is in place + WDT_HIT(); + } + Dbprintf("Starting clone. [Bank: %u]", selected); + // need this delay to prevent catching some weird data + SpinDelay(500); + // Begin clone function here: + /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: + UsbCommand c = {CMD_MIFARE_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}}; + memcpy(c.d.asBytes, data, 16); + SendCommand(&c); - Block read is similar: - UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}}; - We need to imitate that call with blockNo 0 to set a uid. + Block read is similar: + UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, 0, blockNo}}; + We need to imitate that call with blockNo 0 to set a uid. - The get and set commands are handled in this file: - // Work with "magic Chinese" card - case CMD_MIFARE_CSETBLOCK: - MifareCSetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_CGETBLOCK: - MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - // - break; + The get and set commands are handled in this file: + // Work with "magic Chinese" card + case CMD_MIFARE_CSETBLOCK: + MifareCSetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_CGETBLOCK: + MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; - mfCSetUID provides example logic for UID set workflow: - -Read block0 from card in field with MifareCGetBlock() - -Configure new values without replacing reserved bytes - memcpy(block0, uid, 4); // Copy UID bytes from byte array - // Mifare UID BCC - block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5 - Bytes 5-7 are reserved SAK and ATQA for mifare classic - -Use mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER) to write it - */ - uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; - // arg0 = Flags == CSETBLOCK_SINGLE_OPER=0x1F, arg1=returnSlot, arg2=blockNo - MifareCGetBlock(0x1F, 1, 0, oldBlock0); - Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]); - memcpy(newBlock0,oldBlock0,16); - // Copy uid_1st for bank (2nd is for longer UIDs not supported if classic) + mfCSetUID provides example logic for UID set workflow: + -Read block0 from card in field with MifareCGetBlock() + -Configure new values without replacing reserved bytes + memcpy(block0, uid, 4); // Copy UID bytes from byte array + // Mifare UID BCC + block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5 + Bytes 5-7 are reserved SAK and ATQA for mifare classic + -Use mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER) to write it + */ + uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; + // arg0 = Flags == CSETBLOCK_SINGLE_OPER=0x1F, arg1=returnSlot, arg2=blockNo + MifareCGetBlock(0x3F, 1, 0, oldBlock0); + if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { + Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); + playing = 1; + } + else { + Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0],oldBlock0[1],oldBlock0[2],oldBlock0[3]); + memcpy(newBlock0,oldBlock0,16); + // Copy uid_1st for bank (2nd is for longer UIDs not supported if classic) - newBlock0[0] = uid_1st[selected]>>24; - newBlock0[1] = 0xFF & (uid_1st[selected]>>16); - newBlock0[2] = 0xFF & (uid_1st[selected]>>8); - newBlock0[3] = 0xFF & (uid_1st[selected]); - newBlock0[4] = newBlock0[0]^newBlock0[1]^newBlock0[2]^newBlock0[3]; - // arg0 = needWipe, arg1 = workFlags, arg2 = blockNo, datain - MifareCSetBlock(0, 0xFF,0, newBlock0); - MifareCGetBlock(0x1F, 1, 0, testBlock0); - if (memcmp(testBlock0,newBlock0,16)==0) - { - DbpString("Cloned successfull!"); - cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it - } - LEDsoff(); - LED(selected + 1, 0); - // Finished recording - - // If we were previously playing, set playing off - // so next button push begins playing what we recorded + newBlock0[0] = uid_1st[selected]>>24; + newBlock0[1] = 0xFF & (uid_1st[selected]>>16); + newBlock0[2] = 0xFF & (uid_1st[selected]>>8); + newBlock0[3] = 0xFF & (uid_1st[selected]); + newBlock0[4] = newBlock0[0]^newBlock0[1]^newBlock0[2]^newBlock0[3]; + // arg0 = needWipe, arg1 = workFlags, arg2 = blockNo, datain + MifareCSetBlock(0, 0xFF,0, newBlock0); + MifareCGetBlock(0x3F, 1, 0, testBlock0); + if (memcmp(testBlock0,newBlock0,16)==0) + { + DbpString("Cloned successfull!"); + cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it playing = 0; + iGotoRecord = 1; + selected = (selected+1) % OPTS; + } + else { + Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected); + playing = 1; + } + } + LEDsoff(); + LED(selected + 1, 0); } // Change where to record (or begin playing) - else if (button_pressed && cardRead[selected]) + else if (playing==1) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) { - // Next option if we were previously playing - if (playing) - selected = (selected + 1) % OPTS; - playing = !playing; - LEDsoff(); LED(selected + 1, 0); @@ -496,19 +538,45 @@ void StandAloneMode14a() { LED(LED_GREEN, 0); DbpString("Playing"); - while (!BUTTON_HELD(500)) { // Loop simulating tag until the button is held a half-sec + for ( ; ; ) { + WDT_HIT(); + int button_action = BUTTON_HELD(1000); + if (button_action == 0) { // No button action, proceed with sim + uint8_t data[512] = {0}; // in case there is a read command received we shouldn't break Dbprintf("Simulating ISO14443a tag with uid[0]: %08x, uid[1]: %08x [Bank: %u]", uid_1st[selected],uid_2nd[selected],selected); - SimulateIso14443aTag(1,uid_1st[selected],uid_2nd[selected],NULL); + if (hi14a_card[selected].sak == 8 && hi14a_card[selected].atqa[0] == 4 && hi14a_card[selected].atqa[1] == 0) { + DbpString("Mifare Classic"); + SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); // Mifare Classic + } + else if (hi14a_card[selected].sak == 0 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 0) { + DbpString("Mifare Ultralight"); + SimulateIso14443aTag(2,uid_1st[selected],uid_2nd[selected],data); // Mifare Ultralight + } + else if (hi14a_card[selected].sak == 20 && hi14a_card[selected].atqa[0] == 0x44 && hi14a_card[selected].atqa[1] == 3) { + DbpString("Mifare DESFire"); + SimulateIso14443aTag(3,uid_1st[selected],uid_2nd[selected],data); // Mifare DESFire + } + else { + Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); + SimulateIso14443aTag(1,uid_1st[selected], uid_2nd[selected], data); + } } - //cardRead[selected] = 1; - Dbprintf("Done playing [Bank: %u]",selected); + else if (button_action == BUTTON_SINGLE_CLICK) { + selected = (selected + 1) % OPTS; + Dbprintf("Done playing. Switching to record mode on bank %d",selected); + iGotoRecord = 1; + break; + } + else if (button_action == BUTTON_HOLD) { + Dbprintf("Playtime over. Begin cloning..."); + iGotoClone = 1; + break; + } + WDT_HIT(); + } /* We pressed a button so ignore it here with a delay */ SpinDelay(300); - - // when done, we're done playing, move to next option - selected = (selected + 1) % OPTS; - playing = !playing; LEDsoff(); LED(selected + 1, 0); } @@ -1143,7 +1211,12 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_VERSION: SendVersion(); break; - + case CMD_STATUS: + SendStatus(); + break; + case CMD_PING: + cmd_send(CMD_ACK,0,0,0,0,0); + break; #ifdef WITH_LCD case CMD_LCD_RESET: LCDReset(); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 5c7367a1..f81a1a99 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1063,7 +1063,6 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) LED_A_ON(); for(;;) { // Clean receive command buffer - if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString("Button press"); break; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index fd6fde63..a3d6609d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1143,6 +1143,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // bit 2 - need HALT after sequence // bit 3 - need init FPGA and field before sequence // bit 4 - need reset FPGA and LED + // bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) uint8_t workFlags = arg0; uint8_t blockNo = arg2; @@ -1202,7 +1203,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai } LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,data,18); + if (workFlags & 0x20) { + if (isOK) + memcpy(datain, data, 18); + } + else + cmd_send(CMD_ACK,isOK,0,0,data,18); LED_B_OFF(); if ((workFlags & 0x10) || (!isOK)) { From d976c9ddb2b57ff690cbdca033f5423983f60635 Mon Sep 17 00:00:00 2001 From: Craig Young Date: Sat, 25 Jul 2015 14:38:57 -0400 Subject: [PATCH 04/14] Merging changes from main repo --- armsrc/BigBuf.c | 10 ++++++ armsrc/BigBuf.h | 2 +- armsrc/fpgaloader.c | 8 +++++ armsrc/fpgaloader.h | 1 + armsrc/lfsampling.c | 2 +- armsrc/lfsampling.h | 4 +++ armsrc/mifareutil.h | 1 + client/cmdhw.c | 61 ++++++++++++++++++++++++++++--------- client/lualibs/commands.lua | 3 +- include/usb_cmd.h | 2 ++ 10 files changed, 76 insertions(+), 18 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 510f7bef..a938d5c6 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -88,6 +88,16 @@ void BigBuf_free_keep_EM(void) } } +void BigBuf_print_status(void) +{ + Dbprintf("Memory"); + Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); + Dbprintf(" BigBuf_hi .............%d", BigBuf_hi); + Dbprintf("Tracing"); + Dbprintf(" tracing ................%d", tracing); + Dbprintf(" traceLen ...............%d", traceLen); +} + // return the maximum trace length (i.e. the unallocated size of BigBuf) uint16_t BigBuf_max_traceLen(void) diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 0e2f1744..05b4180e 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -28,7 +28,7 @@ extern void BigBuf_Clear(void); extern uint8_t *BigBuf_malloc(uint16_t); extern void BigBuf_free(void); extern void BigBuf_free_keep_EM(void); - +extern void BigBuf_print_status(void); extern uint16_t BigBuf_get_traceLen(void); extern void clear_trace(); extern void set_tracing(bool enable); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 16fed7c5..308dda8c 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -558,3 +558,11 @@ void SetAdcMuxFor(uint32_t whichGpio) HIGH(whichGpio); } + +void Fpga_print_status(void) +{ + Dbprintf("Fgpa"); + if(downloaded_bitstream == FPGA_BITSTREAM_HF) Dbprintf(" mode.............HF"); + else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf(" mode.............LF"); + else Dbprintf(" mode.............%d", downloaded_bitstream); +} diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 0bad3809..52d6c677 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -17,6 +17,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len); void FpgaSetupSsc(void); void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, int len); +void Fpga_print_status(); #define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; void SetAdcMuxFor(uint32_t whichGpio); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 662ebf24..6e783769 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -17,7 +17,7 @@ sample_config config = { 1, 8, 1, 95, 0 } ; void printConfig() { - Dbprintf("Sampling config: "); + Dbprintf("LF Sampling config: "); Dbprintf(" [q] divisor: %d ", config.divisor); Dbprintf(" [b] bps: %d ", config.bits_per_sample); Dbprintf(" [d] decimation: %d ", config.decimation); diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 6c671ec8..7d3925cd 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -56,4 +56,8 @@ void LFSetupFPGAForADC(int divisor, bool lf_field); void setSamplingConfig(sample_config *sc); sample_config * getSamplingConfig(); + +void printConfig(); + + #endif // LFSAMPLING_H diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 85a34ef6..7a09ce64 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -8,6 +8,7 @@ //----------------------------------------------------------------------------- // code for work with mifare cards. //----------------------------------------------------------------------------- +#include "crapto1.h" #ifndef __MIFAREUTIL_H #define __MIFAREUTIL_H diff --git a/client/cmdhw.c b/client/cmdhw.c index 2b6f9518..23b6ce21 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -405,33 +405,64 @@ int CmdTune(const char *Cmd) int CmdVersion(const char *Cmd) { + clearCommandBuffer(); UsbCommand c = {CMD_VERSION}; - UsbCommand resp = {0, {0, 0, 0}}; + static UsbCommand resp = {0, {0, 0, 0}}; - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + PrintAndLog("Prox/RFID mark3 RFID instrument"); + PrintAndLog((char*)resp.d.asBytes); + lookupChipID(resp.arg[0], resp.arg[1]); + } + } else { + PrintAndLog("[[[ Cached information ]]]\n"); PrintAndLog("Prox/RFID mark3 RFID instrument"); PrintAndLog((char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); + PrintAndLog(""); } + return 0; +} +int CmdStatus(const char *Cmd) +{ + UsbCommand c = {CMD_STATUS}; + SendCommand(&c); + return 0; +} + +int CmdPing(const char *Cmd) +{ + clearCommandBuffer(); + UsbCommand resp; + UsbCommand c = {CMD_PING}; + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { + PrintAndLog("Ping successfull"); + }else{ + PrintAndLog("Ping failed"); + } return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, - {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, - {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, - {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, - {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, - {"reset", CmdReset, 0, "Reset the Proxmark3"}, - {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, - {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, - {"tune", CmdTune, 0, "Measure antenna tuning"}, - {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)"}, + {"fpgaoff", CmdFPGAOff, 0, "Set FPGA off"}, + {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, + {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, + {"readmem", CmdReadmem, 0, "[address] -- Read memory at decimal address from flash"}, + {"reset", CmdReset, 0, "Reset the Proxmark3"}, + {"setlfdivisor", CmdSetDivisor, 0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"}, + {"setmux", CmdSetMux, 0, " -- Set the ADC mux to a specific value"}, + {"tune", CmdTune, 0, "Measure antenna tuning"}, + {"version", CmdVersion, 0, "Show version information about the connected Proxmark"}, + {"status", CmdStatus, 0, "Show runtime status information about the connected Proxmark"}, + {"ping", CmdPing, 0, "Test if the pm3 is responsive"}, + {NULL, NULL, 0, NULL} }; int CmdHW(const char *Cmd) diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 127508e6..64f16e44 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -20,7 +20,8 @@ local _commands = { CMD_BUFF_CLEAR = 0x0105, CMD_READ_MEM = 0x0106, CMD_VERSION = 0x0107, - + CMD_STATUS = 0x0108, + CMD_PING = 0x0109, --// For low-frequency tags CMD_READ_TI_TYPE = 0x0202, CMD_WRITE_TI_TYPE = 0x0203, diff --git a/include/usb_cmd.h b/include/usb_cmd.h index e45bf35e..f443e970 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -60,6 +60,8 @@ typedef struct{ #define CMD_BUFF_CLEAR 0x0105 #define CMD_READ_MEM 0x0106 #define CMD_VERSION 0x0107 +#define CMD_STATUS 0x0108 +#define CMD_PING 0x0109 // For low-frequency tags #define CMD_READ_TI_TYPE 0x0202 From 73d336ae1dc311e8a8a8d9e893ce4c5ad8c31f49 Mon Sep 17 00:00:00 2001 From: Craig Young Date: Sun, 26 Jul 2015 11:55:50 -0400 Subject: [PATCH 05/14] Adding STL files for 3D printed coil forms --- doc/RFID_Antenna-Basic-Form.stl | Bin 0 -> 3084 bytes doc/RFID_Antenna-With-Lanyard-Hook.stl | Bin 0 -> 8484 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 doc/RFID_Antenna-Basic-Form.stl create mode 100755 doc/RFID_Antenna-With-Lanyard-Hook.stl diff --git a/doc/RFID_Antenna-Basic-Form.stl b/doc/RFID_Antenna-Basic-Form.stl new file mode 100755 index 0000000000000000000000000000000000000000..6679ae8b5b72814e032869494007d8b69efecffc GIT binary patch literal 3084 zcmb7_L2eU45Jme8oWL7UR>+E2umCZ@2Be@!gag$PvO-zbBH=_;vSX_xa(+?)G;7cAua9e)skM?*8Y;d7l67{wqE-Ma)CJKeaYZt;Mmm z10HIQe9!r4JuVUNk|tsF6+(VbAdPkc+E&^n;`ga-5Lh`Q)YWssR?dhxj-8{!;-M9e zPHX;U1WBXep_6S0->o$3Q$J3v4UbCX%0fE<9VnbZlB?6yYb^xo_W9LAl!)pYb5029Afw{m+A?UG1fCkY6BT2e*A5KuKtKlI^MD-Az^Qg_}ol*Q5=g#p4e$1jS z9+(utdh&4kWrXM_co`jdL&(Ec`tIrH#N%>SmB7jwp{_s&9nvG#-IB1ZMd#^?!06{A z?Q{~Tt*$&vdvaoQ)w4k{Nc8voJ*Y{j5~{?y2NC+!L^}Zuq6bFS^DK5%J(55+Lj*lo z*9qHGAaj2G{nZ;}Fs!aL$LmD(Z~{75ctpP;(t}yr(*+{ViF#I|a~|1#`|zgb3Gm*P zJ{;E@eB8U0n5Jz4G&~d}S+9D~kMmh6kk1DpqI#&qm0(R#^57`#9+(Rx7lO66h_Q1x zbPtk#KJwsb|8_C5@!h>_W$8+O=}iLBI~#J*?(yxkR-%aFiV>6M#po)&xhFz5s<<65$@$4)QqeYlz0##s)y*6pc2*5^5q^Qvl9K?C?}vJ zmoPHZ&&Qy;^Q1&n50N>q?EFpKLt0%W=|t*WSvqtg_km1xa)Yy{*1t@j&$~V6<)IVK Kn|h1j-Tn{btXe<- literal 0 HcmV?d00001 diff --git a/doc/RFID_Antenna-With-Lanyard-Hook.stl b/doc/RFID_Antenna-With-Lanyard-Hook.stl new file mode 100755 index 0000000000000000000000000000000000000000..62f5397a8391cd0a0e2ae5c176d19bc13c44083b GIT binary patch literal 8484 zcmb7J&#Ps{5pE(AXBQ9>&=E5T83zI~41zzvxi7jgL=n_%vdBt87XAxD$$%&*hzn7Y z#hdt?8R3Qe2Xn{kk3b>>gph3(3hpG^Y?AM*s;|5Hoco^Iy!%eyuKMb$s;=&HPT%KW zc>0O+zj*$c^OrAQdhk;IUAlDs$!DK__PNKm+wK3(f3J44wRZF7nOnHDU;pFfO>1v_ z)SBUXeHVR7uJ6A7@--j-=T{%>npMOkadbtr7Kk5z^RaXM_UcQp{i@r#_q`9&Zff~> zYaDO(w||}6($YhB|7!E;)vJ#9(N7^MS~1?5j~g_%um9zX2Y}qX{fAc~4m;Xatr&+{ zj5mWf&H?YP{Q39hh|fNIe^<3)yfuzDLyjDQ3|xVc;ArpfCM_SQ?+e5&aXj|upAZMp zp(V7ByH|hw>$w}u*@)v>=b+Z`@EW{gUwY2kQ!-3z6j|!Zt+A9JQ|G z6)R3!UVRzgx~>$tOEM1jmBUe2^pJH`CCVtZ#yqL6KL5?R2Uu5CGG^^4XVW(8x>A); zqRMcsQg6KyGs~kA*L7u^QCA4VXHp!Lh-1_h*1xH){(JuyH&|CAj%$1B$~IG7c||H$ zlqgrDu52^vieAN99F@4PtC;_0&}K9IZCd*QDv)j7uVOs+F@u;NG$B$__N!5$u*9rl zefyq>+9d}OtakAo?%sIw4j=E;-Vu{zh0yw7b&w+>KjXHTlR&3d<9KV4D^?)CalPMn z<%f=lj1H|BZ!PA7yC?RNi=4rSFW>11&TZ9-ahUZvhd0i_mG$A@1HsCuS~1>Q)K%O! zbRRhz9N7CNt;TV-+!LLHSr$iB_|OtM)(5?Mv3^LzW)Y5FmeX!IOI8;~HXRTf_i%Q&sunq0b z9L1}xykd;uv)W4u57~U7=ELvRXzQM|*ti6$T06#?dn(r*`)te=`o=CkXhNi9LJ(aL zt{w>0F89Q7r>^^>?2BXUoHL?60Z?~%^ayMp9N_zH?7jG~&nv&@xHWHzp&}kiG!X@T z3PR|2fh_2XK)*=ZKEykb-Ij3_1SAteUab*DG9m1CL=F#Om(3%$DJMNz@_j!9c?&n~ zmU^nus!#juzje@Bc(p{Nq{mSa=z~LzNJC6RL9WWj zJ}u#D_`g7;WG^BjZ)}MqJL9Mv?8~d*=pKQqNIHkm!z(a^XYAnFnG#+vf=~To$sk4Z zSa`kNBb?CR4I%Wq;40jPZ)oBulFnBVZ;jezhS@R>NG6250@_@!&xxWXqGauB53O*L`3e^6It^k4qnUM4w^j=wANXbBB%HhHD~ah?b(@>u6_isOJlH0>YpPCn4nNwHxZALp15WAEae zvt>+%-qr{FAG6D*Xye;5@+G3?XNkafOOJ3psgaK@Jl}^%NvPp}MWAmfz?GVcBS-s1 z)q??O3MIsnL$Dkt0xhDC>eE?hJwYhkM)gGC%4*LO)8b*Q51orrLmU+`^PRxa^y@;yRYeRB`5aWx&}Libsv;D5f4%s(=W3F4uZU1x6~u<)6^H O3=Fu$Cdpm|koJEJ#e`%4 literal 0 HcmV?d00001 From bfb01844fb0ce48e960374c3bc6ecf208b6c6bb0 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Wed, 29 Jul 2015 18:52:43 +0200 Subject: [PATCH 06/14] add: USB Speed Test to hw status fix: choose Real Time Clock divider based on actual slow clock frequency --- armsrc/appmain.c | 34 ++++++++++++++++++++++++++++++++-- armsrc/util.c | 11 ++++++----- client/cmdhw.c | 12 +++++++++++- client/cmdmain.c | 21 ++++++++++----------- 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b5e7d7ea..99776a98 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -298,18 +298,48 @@ void SendVersion(void) uint32_t compressed_data_section_size = common_area.arg1; cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); } + +// measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time. +// Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included. +void printUSBSpeed(uint32_t SpeedTestBufferSize) +{ + Dbprintf("USB Speed:"); + Dbprintf(" Sending %d bytes payload...", SpeedTestBufferSize); + + uint8_t *test_data = BigBuf_get_addr(); + + uint32_t start_time = GetTickCount(); + + LED_B_ON(); + for(size_t i=0; i Client = %d Bytes/s", + end_time - start_time, + 1000* SpeedTestBufferSize / (end_time - start_time)); + +} + /** * Prints runtime information about the PM3. **/ -void SendStatus(void) +void SendStatus(uint32_t SpeedTestBufferSize) { BigBuf_print_status(); Fpga_print_status(); printConfig(); //LF Sampling config + printUSBSpeed(SpeedTestBufferSize); Dbprintf("Various"); Dbprintf(" MF_DBGLEVEL......%d", MF_DBGLEVEL); Dbprintf(" ToSendMax........%d",ToSendMax); Dbprintf(" ToSendBit........%d",ToSendBit); + + cmd_send(CMD_ACK,1,0,0,0,0); } #if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF) @@ -1212,7 +1242,7 @@ void UsbPacketReceived(uint8_t *packet, int len) SendVersion(); break; case CMD_STATUS: - SendStatus(); + SendStatus(c->arg[0]); break; case CMD_PING: cmd_send(CMD_ACK,0,0,0,0,0); diff --git a/armsrc/util.c b/armsrc/util.c index 8576ddce..1dd8dc75 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -304,11 +304,12 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers void StartTickCount() { -// must be 0x40, but on my cpu - included divider is optimal -// 0x20 - 1 ms / bit -// 0x40 - 2 ms / bit - - AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST + 0x001D; // was 0x003B + // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz. + // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register. + uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency + // set RealTimeCounter divider to count at 1kHz: + AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf); + // note: worst case precision is approx 2.5% } /* diff --git a/client/cmdhw.c b/client/cmdhw.c index 23b6ce21..44f878af 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -18,6 +18,7 @@ #include "cmdhw.h" #include "cmdmain.h" #include "cmddata.h" +#include "data.h" /* low-level hardware control */ @@ -428,11 +429,20 @@ int CmdVersion(const char *Cmd) int CmdStatus(const char *Cmd) { - UsbCommand c = {CMD_STATUS}; + uint8_t speed_test_buffer[USB_CMD_DATA_SIZE]; + sample_buf = speed_test_buffer; + #define USB_SPEED_TEST_SIZE (1000*USB_CMD_DATA_SIZE) + + clearCommandBuffer(); + UsbCommand c = {CMD_STATUS, {USB_SPEED_TEST_SIZE}}; SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK,&c,1500)) { + PrintAndLog("Status command failed. USB Speed Test timed out"); + } return 0; } + int CmdPing(const char *Cmd) { clearCommandBuffer(); diff --git a/client/cmdmain.c b/client/cmdmain.c index 512aa13c..9298360d 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -131,24 +131,23 @@ int getCommand(UsbCommand* response) */ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { - UsbCommand resp; + UsbCommand resp; if (response == NULL) - response = &resp; + response = &resp; - // Wait until the command is received - for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { - + // Wait until the command is received + for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { while(getCommand(response)) { - if(response->cmd == cmd){ - return true; - } - } + if(response->cmd == cmd){ + return true; + } + } msleep(10); // XXX ugh if (dm_seconds == 200) { // Two seconds elapsed - PrintAndLog("Waiting for a response from the proxmark..."); - PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); + PrintAndLog("Waiting for a response from the proxmark..."); + PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); } } return false; From 67b7d6fa31f4426f18d223faa06c7b1f3c59fa97 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 31 Jul 2015 20:05:30 +0200 Subject: [PATCH 07/14] fix: avoid USB Speed Test timeout in case of slow transfer speeds fix: don't add CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K commands into command buffer --- armsrc/appmain.c | 33 ++++++++++++++++++--------------- client/cmdhw.c | 5 ++--- client/cmdmain.c | 23 ++++++++++++++--------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 99776a98..38afd85d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -301,39 +301,42 @@ void SendVersion(void) // measure the USB Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time. // Note: this mimics GetFromBigbuf(), i.e. we have the overhead of the UsbCommand structure included. -void printUSBSpeed(uint32_t SpeedTestBufferSize) +void printUSBSpeed(void) { Dbprintf("USB Speed:"); - Dbprintf(" Sending %d bytes payload...", SpeedTestBufferSize); + Dbprintf(" Sending USB packets to client..."); + #define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds uint8_t *test_data = BigBuf_get_addr(); + uint32_t end_time; - uint32_t start_time = GetTickCount(); - + uint32_t start_time = end_time = GetTickCount(); + uint32_t bytes_transferred = 0; + LED_B_ON(); - for(size_t i=0; i Client = %d Bytes/s", - end_time - start_time, - 1000* SpeedTestBufferSize / (end_time - start_time)); + Dbprintf(" Time elapsed: %dms", end_time - start_time); + Dbprintf(" Bytes transferred: %d", bytes_transferred); + Dbprintf(" USB Transfer Speed PM3 -> Client = %d Bytes/s", + 1000 * bytes_transferred / (end_time - start_time)); } /** * Prints runtime information about the PM3. **/ -void SendStatus(uint32_t SpeedTestBufferSize) +void SendStatus(void) { BigBuf_print_status(); Fpga_print_status(); printConfig(); //LF Sampling config - printUSBSpeed(SpeedTestBufferSize); + printUSBSpeed(); Dbprintf("Various"); Dbprintf(" MF_DBGLEVEL......%d", MF_DBGLEVEL); Dbprintf(" ToSendMax........%d",ToSendMax); @@ -1242,7 +1245,7 @@ void UsbPacketReceived(uint8_t *packet, int len) SendVersion(); break; case CMD_STATUS: - SendStatus(c->arg[0]); + SendStatus(); break; case CMD_PING: cmd_send(CMD_ACK,0,0,0,0,0); diff --git a/client/cmdhw.c b/client/cmdhw.c index 44f878af..33dc78ae 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -431,12 +431,11 @@ int CmdStatus(const char *Cmd) { uint8_t speed_test_buffer[USB_CMD_DATA_SIZE]; sample_buf = speed_test_buffer; - #define USB_SPEED_TEST_SIZE (1000*USB_CMD_DATA_SIZE) clearCommandBuffer(); - UsbCommand c = {CMD_STATUS, {USB_SPEED_TEST_SIZE}}; + UsbCommand c = {CMD_STATUS}; SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK,&c,1500)) { + if (!WaitForResponseTimeout(CMD_ACK,&c,1900)) { PrintAndLog("Status command failed. USB Speed Test timed out"); } return 0; diff --git a/client/cmdmain.c b/client/cmdmain.c index 9298360d..deced558 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -97,8 +97,9 @@ void storeCommand(UsbCommand *command) memcpy(destination, command, sizeof(UsbCommand)); cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; //increment head and wrap - } + + /** * @brief getCommand gets a command from an internal circular buffer. * @param response location to write command @@ -117,9 +118,9 @@ int getCommand(UsbCommand* response) cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE; return 1; - } + /** * Waits for a certain response type. This method waits for a maximum of * ms_timeout milliseconds for a specified response command. @@ -133,9 +134,9 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou UsbCommand resp; - if (response == NULL) + if (response == NULL) { response = &resp; - + } // Wait until the command is received for(size_t dm_seconds=0; dm_seconds < ms_timeout/10; dm_seconds++) { @@ -144,19 +145,21 @@ bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeou return true; } } - msleep(10); // XXX ugh - if (dm_seconds == 200) { // Two seconds elapsed + msleep(10); // XXX ugh + if (dm_seconds == 200) { // Two seconds elapsed PrintAndLog("Waiting for a response from the proxmark..."); PrintAndLog("Don't forget to cancel its operation first by pressing on the button"); - } + } } - return false; + return false; } + bool WaitForResponse(uint32_t cmd, UsbCommand* response) { return WaitForResponseTimeout(cmd,response,-1); } + //----------------------------------------------------------------------------- // Entry point into our code: called whenever the user types a command and // then presses Enter, which the full command line that they typed. @@ -165,6 +168,7 @@ void CommandReceived(char *Cmd) { CmdsParse(CommandTable, Cmd); } + //----------------------------------------------------------------------------- // Entry point into our code: called whenever we received a packet over USB // that we weren't necessarily expecting, for example a debug print. @@ -188,12 +192,13 @@ void UsbCommandReceived(UsbCommand *UC) case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: { memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]); + return; } break; default: + storeCommand(UC); break; } - storeCommand(UC); } From f68211671cf3230b3ddbe948f3802418ee03d378 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 31 Jul 2015 23:27:09 +0200 Subject: [PATCH 08/14] Implemented `data hex2bin` and `data bin2hex` as per suggestion in http://www.proxmark.org/forum/viewtopic.php?pid=17504 --- CHANGELOG.md | 1 + client/cmddata.c | 115 ++++++++++++++++++++++++++++++++++++++++------- client/util.h | 1 + 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 682d87eb..e2196a39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - AWID26 command context added as 'lf awid' containing realtime demodulation as well as cloning/simulation based on tag numbers (Craig Young) - Added 'hw status'. This command makes the ARM print out some runtime information. (holiman) - Added 'hw ping'. This command just sends a usb packets and checks if the pm3 is responsive. Can be used to abort certain operations which supports abort over usb. (holiman) +- Added `data hex2bin` and `data bin2hex` for command line conversion between binary and hexadecimal (holiman) ### Changed - Revised workflow for StandAloneMode14a (Craig Young) diff --git a/client/cmddata.c b/client/cmddata.c index cb1c7cd4..0907f3c5 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -24,6 +24,7 @@ #include "usb_cmd.h" #include "crc.h" #include "crc16.h" +#include "loclass/cipherutils.h" uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; uint8_t g_debugMode=0; @@ -1943,26 +1944,14 @@ int CmdHpf(const char *Cmd) RepaintGraphWindow(); return 0; } -typedef struct { - uint8_t * buffer; - uint32_t numbits; - uint32_t position; -}BitstreamOut; -bool _headBit( BitstreamOut *stream) -{ - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = (stream->position++) & 7; // mask out 00000111 - return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; -} - -uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) +uint8_t getByte(uint8_t bits_per_sample, BitstreamIn* b) { int i; uint8_t val = 0; for(i =0 ; i < bits_per_sample; i++) { - val |= (_headBit(b) << (7-i)); + val |= (headBit(b) << (7-i)); } return val; } @@ -2002,7 +1991,7 @@ int getSamples(const char *Cmd, bool silent) if(bits_per_sample < 8) { PrintAndLog("Unpacking..."); - BitstreamOut bout = { got, bits_per_sample * n, 0}; + BitstreamIn bout = { got, bits_per_sample * n, 0}; int j =0; for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { uint8_t sample = getByte(bits_per_sample, &bout); @@ -2265,6 +2254,99 @@ int CmdZerocrossings(const char *Cmd) return 0; } +int usage_data_bin2hex(){ + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); + return 0; +} + +/** + * @brief Utility for conversion via cmdline. + * @param Cmd + * @return + */ +int Cmdbin2hex(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_bin2hex(); + } + //Number of digits supplied as argument + size_t length = en - bg +1; + size_t bytelen = (length+7) / 8; + uint8_t* arr = (uint8_t *) malloc(bytelen); + memset(arr, 0, bytelen); + BitstreamOut bout = { arr, 0, 0 }; + + for(; bg <= en ;bg++) + { + char c = Cmd[bg]; + if( c == '1') pushBit(&bout, 1); + else if( c == '0') pushBit(&bout, 0); + else PrintAndLog("Ignoring '%c'", c); + } + + if(bout.numbits % 8 != 0) + { + printf("[padded with %d zeroes]\n", 8-(bout.numbits % 8)); + } + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + for(size_t x = 0; x < bytelen ; x++) + { + printf("%02X", arr[x]); + } + printf("\n"); + free(arr); + return 0; +} + +int usage_data_hex2bin(){ + + PrintAndLog("Usage: data bin2hex "); + PrintAndLog(" This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); + return 0; + +} + +int Cmdhex2bin(const char *Cmd) +{ + int bg =0, en =0; + if(param_getptr(Cmd, &bg, &en, 0)) + { + return usage_data_hex2bin(); + } + + + while(bg <= en ) + { + char x = Cmd[bg++]; + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else + continue; + + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + + for(int i= 0 ; i < 4 ; ++i) + printf("%d",(x >> (3 - i)) & 1); + } + printf("\n"); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -2287,6 +2369,9 @@ static command_t CommandTable[] = {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, + {"bin2hex", Cmdbin2hex, 1, "bin2hex -- Converts binary to hexadecimal"}, + {"hex2bin", Cmdhex2bin, 1, "hex2bin -- Converts hexadecimal to binary"}, + {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, {"hide", CmdHide, 1, "Hide graph window"}, {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, {"load", CmdLoad, 1, " -- Load trace (to graph window"}, diff --git a/client/util.h b/client/util.h index 2d2beaf4..94021c2c 100644 --- a/client/util.h +++ b/client/util.h @@ -47,6 +47,7 @@ char * printBits(size_t const size, void const * const ptr); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); char param_getchar(const char *line, int paramnum); +int param_getptr(const char *line, int *bg, int *en, int paramnum); uint8_t param_get8(const char *line, int paramnum); uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); From 5d01f50ae1be5c7de81cc089d60d3bdbf80dc738 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Fri, 31 Jul 2015 23:30:48 +0200 Subject: [PATCH 09/14] Minor corrections --- client/cmddata.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 0907f3c5..22da1805 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -2355,6 +2355,7 @@ static command_t CommandTable[] = {"askgproxiidemod", CmdG_Prox_II_Demod, 1, "Demodulate a G Prox II tag from GraphBuffer"}, {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, + {"bin2hex", Cmdbin2hex, 1, "bin2hex -- Converts binary to hexadecimal"}, {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, {"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"}, {"dec", CmdDec, 1, "Decimate samples"}, @@ -2369,9 +2370,7 @@ static command_t CommandTable[] = {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, - {"bin2hex", Cmdbin2hex, 1, "bin2hex -- Converts binary to hexadecimal"}, {"hex2bin", Cmdhex2bin, 1, "hex2bin -- Converts hexadecimal to binary"}, - {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, {"hide", CmdHide, 1, "Hide graph window"}, {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, {"load", CmdLoad, 1, " -- Load trace (to graph window"}, From dc4300bafb4dd3917a230b27fa2d1efa9ef08dd0 Mon Sep 17 00:00:00 2001 From: Dake Date: Wed, 26 Aug 2015 15:53:49 +0200 Subject: [PATCH 10/14] add : writing on PCF7931 tags --- armsrc/appmain.c | 3 + armsrc/apps.h | 6 + armsrc/lfops.c | 283 +++++++++++++++++++++++++++++++++++++++++- client/cmdlfpcf7931.c | 88 ++++++++++++- client/cmdlfpcf7931.h | 13 +- include/usb_cmd.h | 2 + 6 files changed, 388 insertions(+), 7 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 38afd85d..321782da 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -987,6 +987,9 @@ void UsbPacketReceived(uint8_t *packet, int len) ReadPCF7931(); cmd_send(CMD_ACK,0,0,0,0,0); break; + case CMD_PCF7931_WRITE: + WritePCF7931(c->d.asDwords[0],c->d.asDwords[1],c->d.asDwords[2],c->d.asDwords[3],c->d.asDwords[4],c->d.asDwords[5],c->d.asDwords[6], c->d.asDwords[9], c->d.asDwords[7]-128,c->d.asDwords[8]-128, c->arg[0], c->arg[1], c->arg[2]); + break; case CMD_EM4X_READ_WORD: EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index b5638ee1..d5c8ba0a 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -61,6 +61,7 @@ void AcquireRawAdcSamples125k(int divisor); void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,uint8_t *command); void ReadTItag(void); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); + void AcquireTiType(void); void AcquireRawBitsTI(void); void SimulateTagLowFrequency(int period, int gap, int ledcontrol); @@ -85,6 +86,11 @@ int DemodPCF7931(uint8_t **outBlocks); int IsBlock0PCF7931(uint8_t *Block); int IsBlock1PCF7931(uint8_t *Block); void ReadPCF7931(); +void SendCmdPCF7931(uint32_t * tab); +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p); +bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p); +bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab); +void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data); void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 733bc953..dc7ffd88 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -16,8 +16,7 @@ #include "string.h" #include "lfdemod.h" #include "lfsampling.h" -#include "usb_cdc.h" - +#include "usb_cdc.h" //test /** * Function to do a modulation and then get samples. @@ -214,6 +213,8 @@ void ReadTItag(void) } } + + void WriteTIbyte(uint8_t b) { int i = 0; @@ -310,12 +311,17 @@ void AcquireTiType(void) } } + + + // arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc // if crc provided, it will be written with the data verbatim (even if bogus) // if not provided a valid crc will be computed from the data and written. void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) { - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + +FpgaDownloadAndGo(FPGA_BITSTREAM_LF); if(crc == 0) { crc = update_crc16(crc, (idlo)&0xff); crc = update_crc16(crc, (idlo>>8)&0xff); @@ -1705,6 +1711,8 @@ int DemodPCF7931(uint8_t **outBlocks) { if(num_blocks == 4) break; } memcpy(outBlocks, Blocks, 16*num_blocks); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return num_blocks; } @@ -1828,14 +1836,21 @@ void ReadPCF7931() { Dbprintf("Memory content:"); Dbprintf("-----------------------------------------"); for(i=0; i", i); } Dbprintf("-----------------------------------------"); + return ; } @@ -2058,3 +2073,261 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } + + +#define T0_PCF 8 //period for the pcf7931 in us + +/* Write on a byte of a PCF7931 tag + * @param address : address of the block to write + @param byte : address of the byte to write + @param data : data to write + */ +void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) +{ + + uint32_t tab[1024]={0}; // data times frame + uint32_t u = 0; + uint8_t parity = 0; + bool comp = 0; + + + //BUILD OF THE DATA FRAME + + //alimentation of the tag (time for initializing) + AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); + + //PMC + Dbprintf("Initialization delay : %d us", init_delay); + AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); + + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + + //password indication bit + AddBitPCF7931(1, tab, l, p); + + + //password (on 56 bits) + Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); + AddBytePCF7931(pass1, tab, l, p); + AddBytePCF7931(pass2, tab, l, p); + AddBytePCF7931(pass3, tab, l, p); + AddBytePCF7931(pass4, tab, l, p); + AddBytePCF7931(pass5, tab, l, p); + AddBytePCF7931(pass6, tab, l, p); + AddBytePCF7931(pass7, tab, l, p); + + + //programming mode (0 or 1) + AddBitPCF7931(0, tab, l, p); + + //block adress on 6 bits + Dbprintf("Block address : %02x", address); + for (u=0; u<6; u++) + { + if (address&(1< 0xFFFF){ + tab[u] -= 0xFFFF; + comp = 0; + } + } + } + + SendCmdPCF7931(tab); +} + + + +/* Send a trame to a PCF7931 tags + * @param tab : array of the data frame + */ + +void SendCmdPCF7931(uint32_t * tab){ + uint16_t u=0; + uint16_t tempo=0; + + Dbprintf("SENDING DATA FRAME..."); + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); + + LED_A_ON(); + + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + + //initialization of the timer + AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; + AT91C_BASE_TCB->TCB_BCR = 1; + + + tempo = AT91C_BASE_TC0->TC_CV; + for(u=0;tab[u]!= 0;u+=3){ + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + // stop modulating antenna + LOW(GPIO_SSC_DOUT); + while(tempo != tab[u+1]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while(tempo != tab[u+2]){ + tempo = AT91C_BASE_TC0->TC_CV; + } + + + } + + LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + + + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + DbpString("FINISH !"); + DbpString("(Could be usefull to send the same trame many times)"); + LED(0xFFFF, 1000); +} + + +/* Add a byte for building the data frame of PCF7931 tags + * @param b : byte to add + * @param tab : array of the data frame + * @param l : offset on low pulse width + * @param p : offset on low pulse positioning + */ + +bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ + + uint32_t u; + for (u=0; u<8; u++) + { + if (byte&(1< -// +// 2015 Dake + // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -21,6 +22,8 @@ static int CmdHelp(const char *Cmd); +struct pcf7931_config configPcf = {{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},17500,{0,0}}; + int CmdLFPCF7931Read(const char *Cmd) { UsbCommand c = {CMD_PCF7931_READ}; @@ -30,10 +33,93 @@ int CmdLFPCF7931Read(const char *Cmd) return 0; } +int CmdLFPCF7931Config(const char *Cmd) +{ + int res = 0; + res = sscanf(Cmd, "%02x %02x %02x %02x %02x %02x %02x %d %d %d", &configPcf.password[0], &configPcf.password[1], &configPcf.password[2], &configPcf.password[3], &configPcf.password[4], &configPcf.password[5], &configPcf.password[6], &configPcf.init_delay, &configPcf.offset[0], &configPcf.offset[1]); + + if (res >= 7 || res < 1){ + if(res == 7) configPcf.init_delay = 17500; //default value + + if(res<=8){ + configPcf.offset[0] = -10; //default value + configPcf.offset[1] = 30; //default value + } + + if(res < 1){ + PrintAndLog("Usage: [...] "); + PrintAndLog("The time offsets could be usefull to correct slew rate generated by the antenna."); + } + + PrintAndLog("Current configuration :"); + PrintAndLog("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", configPcf.password[0], configPcf.password[1], configPcf.password[2], configPcf.password[3], configPcf.password[4], configPcf.password[5], configPcf.password[6]); + PrintAndLog("Tag initialization delay : %d us", configPcf.init_delay); + PrintAndLog("Offsets : %d us on the low pulses width, %d us on the low pulses positions", configPcf.offset[0], configPcf.offset[1]); + + return 0; + } + + //default values + configPcf.password[0] = 0xFF; + configPcf.password[1] = 0xFF; + configPcf.password[2] = 0xFF; + configPcf.password[3] = 0xFF; + configPcf.password[4] = 0xFF; + configPcf.password[5] = 0xFF; + configPcf.password[6] = 0xFF; + + configPcf.init_delay = 17500; + configPcf.offset[0] = 0; + configPcf.offset[1] = 0; + + PrintAndLog("Incorrect format"); + PrintAndLog("Examples of right usage : lf pcf7931 config 11 22 33 44 55 66 77 20000"); + PrintAndLog(" lf pcf7931 config FF FF FF FF FF FF FF 17500 -10 30"); + return 0; +} + + + +int CmdLFPCF7931Write(const char *Cmd) +{ + UsbCommand c = {CMD_PCF7931_WRITE}; + + int res = 0; + res = sscanf(Cmd, "%x %x %x", &c.arg[0], &c.arg[1], &c.arg[2]); + + if(res < 1) { + PrintAndLog("Please specify the block address in hex"); + return 0; + } + if (res == 1){ + PrintAndLog("Please specify the byte address in hex"); + return 0; + } + if(res == 2) { + PrintAndLog("Please specify the data in hex (1 byte)"); + return 0; + } + if(res == 3) { + uint8_t n=0; + for(n=0;n<7;n++) c.d.asDwords[n] = configPcf.password[n]; + c.d.asDwords[7] = (configPcf.offset[0]+128); + c.d.asDwords[8] = (configPcf.offset[1]+128); + c.d.asDwords[9] = configPcf.init_delay; + SendCommand(&c); + return 0; + } + + PrintAndLog("INCORRECT FORMAT"); + return 0; +} + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"read", CmdLFPCF7931Read, 1, "Read content of a PCF7931 transponder"}, + {"write", CmdLFPCF7931Write, 1, "Write data on a PCF7931 transponder. Usage : lf pcf7931 write "}, + {"config", CmdLFPCF7931Config, 1, "Configure the password, the tags initialization delay and time offsets (optional)"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfpcf7931.h b/client/cmdlfpcf7931.h index ed60bc91..78eaff5d 100644 --- a/client/cmdlfpcf7931.h +++ b/client/cmdlfpcf7931.h @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2012 Chalk -// +// 2015 Dake + // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -11,8 +12,18 @@ #ifndef CMDLFPCF7931_H__ #define CMDLFPCF7931_H__ +struct pcf7931_config{ + uint8_t password[7]; + uint16_t init_delay; + int16_t offset[2]; +}; + int CmdLFPCF7931(const char *Cmd); int CmdLFPCF7931Read(const char *Cmd); +int CmdLFPCF7931Write(const char *Cmd); + +int CmdLFPCF7931Config(const char *Cmd); + #endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index f443e970..a58feb38 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -87,6 +87,7 @@ typedef struct{ #define CMD_T55XX_WRITE_BLOCK 0x0215 #define CMD_T55XX_READ_TRACE 0x0216 #define CMD_PCF7931_READ 0x0217 +#define CMD_PCF7931_WRITE 0x0222 #define CMD_EM4X_READ_WORD 0x0218 #define CMD_EM4X_WRITE_WORD 0x0219 #define CMD_IO_DEMOD_FSK 0x021A @@ -99,6 +100,7 @@ typedef struct{ #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 + /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ // For the 13.56 MHz tags From 940d53098c64fde87ac035a3b6ba7722d43e755e Mon Sep 17 00:00:00 2001 From: Dake Date: Wed, 26 Aug 2015 15:57:41 +0200 Subject: [PATCH 11/14] corrective values --- client/cmdlfpcf7931.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index 8265126e..b1e1ae9e 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -42,8 +42,8 @@ int CmdLFPCF7931Config(const char *Cmd) if(res == 7) configPcf.init_delay = 17500; //default value if(res<=8){ - configPcf.offset[0] = -10; //default value - configPcf.offset[1] = 30; //default value + configPcf.offset[0] = 0; //default value + configPcf.offset[1] = 0; //default value } if(res < 1){ From fff58476af2e83ff89dbbc6c9804bfea116c88dd Mon Sep 17 00:00:00 2001 From: Dake Date: Wed, 26 Aug 2015 16:01:08 +0200 Subject: [PATCH 12/14] syntax corrective --- armsrc/lfops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index dc7ffd88..275544f5 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -321,7 +321,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) { -FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); if(crc == 0) { crc = update_crc16(crc, (idlo)&0xff); crc = update_crc16(crc, (idlo>>8)&0xff); From 29c90533eb7e369acf819edd1e209cea3db94e80 Mon Sep 17 00:00:00 2001 From: Dake Date: Thu, 27 Aug 2015 08:58:15 +0200 Subject: [PATCH 13/14] remove debug --- armsrc/lfops.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 275544f5..d7f91c53 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1840,12 +1840,6 @@ void ReadPCF7931() { Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7], Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]); - if(i==3){ - if(Blocks[3][0] == 0xAA) - Dbprintf("Solde actuel : %d centimes, solde précédent : %d centimes", (Blocks[3][1] << 8 | Blocks[3][2]), (Blocks[3][6] << 8 | Blocks[3][7])); - else - Dbprintf("Solde actuel : %d centimes, solde précédent : %d centimes", (Blocks[3][6] << 8 | Blocks[3][7]), (Blocks[3][1] << 8 | Blocks[3][2])); - } }else Dbprintf("", i); } From dfb387bf0f73129f4bcb27eb4c840d9a35f390d6 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Wed, 30 Sep 2015 20:59:50 +0200 Subject: [PATCH 14/14] hf mf mifare: - gracefully exit on unsuccessful syncs instead of hard watchdog reset --- armsrc/iso14443a.c | 62 +++++++++++++++++++++++-------- client/cmdhfmf.c | 1 + client/scripts/mifare_autopwn.lua | 2 + 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index f81a1a99..0431876e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2016,6 +2016,7 @@ void ReaderMifare(bool first_try) byte_t par_list[8] = {0x00}; byte_t ks_list[8] = {0x00}; + #define PRNG_SEQUENCE_LENGTH (1 << 16); static uint32_t sync_time; static uint32_t sync_cycles; int catch_up_cycles = 0; @@ -2026,7 +2027,7 @@ void ReaderMifare(bool first_try) if (first_try) { mf_nr_ar3 = 0; sync_time = GetCountSspClk() & 0xfffffff8; - sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + sync_cycles = PRNG_SEQUENCE_LENGTH; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces). nt_attacked = 0; nt = 0; par[0] = 0; @@ -2043,8 +2044,12 @@ void ReaderMifare(bool first_try) LED_C_OFF(); - #define DARKSIDE_MAX_TRIES 32 // number of tries to sync on PRNG cycle. Then give up. - uint16_t unsuccessfull_tries = 0; + #define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. + #define MAX_SYNC_TRIES 16 + uint16_t unexpected_random = 0; + uint16_t sync_tries = 0; + int16_t debug_info_nr = -1; + uint32_t debug_info[MAX_SYNC_TRIES]; for(uint16_t i = 0; TRUE; i++) { @@ -2062,16 +2067,20 @@ void ReaderMifare(bool first_try) continue; } - sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; - catch_up_cycles = 0; + if (debug_info_nr == -1) { + sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; + catch_up_cycles = 0; - // if we missed the sync time already, advance to the next nonce repeat - while(GetCountSspClk() > sync_time) { - sync_time = (sync_time & 0xfffffff8) + sync_cycles; - } + // if we missed the sync time already, advance to the next nonce repeat + while(GetCountSspClk() > sync_time) { + sync_time = (sync_time & 0xfffffff8) + sync_cycles; + } - // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) - ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) + ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + } else { + ReaderTransmit(mf_auth, sizeof(mf_auth), NULL); + } // Receive the (4 Byte) "random" nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) { @@ -2089,19 +2098,32 @@ void ReaderMifare(bool first_try) int nt_distance = dist_nt(previous_nt, nt); if (nt_distance == 0) { nt_attacked = nt; - } - else { + } else { if (nt_distance == -99999) { // invalid nonce received - unsuccessfull_tries++; - if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) { + unexpected_random++; + if (!nt_attacked && unexpected_random > MAX_UNEXPECTED_RANDOM) { isOK = -3; // Card has an unpredictable PRNG. Give up break; } else { continue; // continue trying... } } + if (++sync_tries > MAX_SYNC_TRIES) { + if (sync_tries > 2 * MAX_SYNC_TRIES) { + isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } else { // continue for a while, just to collect some debug info + debug_info[++debug_info_nr] = nt_distance; + continue; + } + } sync_cycles = (sync_cycles - nt_distance); - if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); + if (sync_cycles <= 0) { + sync_cycles += PRNG_SEQUENCE_LENGTH; + } + if (MF_DBGLEVEL >= 3) { + Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); + } continue; } } @@ -2172,6 +2194,14 @@ void ReaderMifare(bool first_try) mf_nr_ar[3] &= 0x1F; + + if (isOK == -4) { + if (MF_DBGLEVEL >= 3) { + for(uint16_t i = 0; i < MAX_SYNC_TRIES; i++) { + Dbprintf("collected debug info[%d] = %d\n", i, debug_info[i]); + } + } + } byte_t buf[28]; memcpy(buf + 0, uid, 4); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 16612cba..8a8a38fc 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -58,6 +58,7 @@ start: case -1 : PrintAndLog("Button pressed. Aborted.\n"); break; case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break; case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break; + case -4 : PrintAndLog("The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). This needs to be fixed.\n"); break; default: ; } break; diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index 9cc865f0..77f36ae4 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -112,6 +112,8 @@ function mfcrack_inner() return nil, "Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." elseif isOK == 0xFFFFFFFD then return nil, "Card is not vulnerable to Darkside attack (its random number generator is not predictable). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." + elseif isOK == 0xFFFFFFFC then + return nil, "The card's random number generator is vulnerable but behaves somewhat weird (Mifare clone?). You can try 'script run mfkeys' or 'hf mf chk' to test various known keys." elseif isOK ~= 1 then return nil, "Error occurred" end