From: marshmellow42 Date: Fri, 31 Mar 2017 16:18:50 +0000 (-0400) Subject: Merge remote-tracking branch 'upstream/master' X-Git-Tag: v3.0.0~19^2~2 X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/5249ff940f17a0ae619c178ea8648c112106e9ae?hp=4ab135c0cdb190d6d29608204d3d7c15a25b07ee Merge remote-tracking branch 'upstream/master' --- diff --git a/Makefile b/Makefile index bafd8161..1ab83f9e 100644 --- a/Makefile +++ b/Makefile @@ -1,17 +1,40 @@ -include common/Makefile.common - +GZIP=gzip +# Windows' echo echos its input verbatim, on Posix there is some +# amount of shell command line parsing going on. echo "" on +# Windows yields literal "", on Linux yields an empty line +ifeq ($(shell echo ""),) +# This is probably a proper system, so we can use uname +DELETE=rm -rf +FLASH_TOOL=client/flasher +platform=$(shell uname) +ifneq (,$(findstring MINGW,$(platform))) +FLASH_PORT=com3 +PATHSEP=\\# +else FLASH_PORT=/dev/ttyACM0 +PATHSEP=/ +endif +else +# Assume that we are running on native Windows +DELETE=del /q +FLASH_TOOL=client/flasher.exe +platform=Windows +FLASH_PORT=com3 +PATHSEP=\\# +endif -all clean: %: client/% bootrom/% armsrc/% recovery/% +all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% bootrom/%: FORCE - $(MAKE) -C bootrom $(patsubst bootrom/%,%,$@) + $(MAKE) -C bootrom $(patsubst bootrom/%, %, $@) armsrc/%: FORCE - $(MAKE) -C armsrc $(patsubst armsrc/%,%,$@) + $(MAKE) -C armsrc $(patsubst armsrc/%, %, $@) client/%: FORCE - $(MAKE) -C client $(patsubst client/%,%,$@) + $(MAKE) -C client $(patsubst client/%, %, $@) recovery/%: FORCE - $(MAKE) -C recovery $(patsubst recovery/%,%,$@) + $(MAKE) -C recovery $(patsubst recovery/%, %, $@) +mfkey/%: FORCE + $(MAKE) -C tools/mfkey $(patsubst mfkey/%, %, $@) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) .PHONY: all clean help _test flash-bootrom flash-os flash-all FORCE @@ -28,6 +51,8 @@ help: client: client/all +mfkey: mfkey/all + flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL) $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<) diff --git a/README.txt b/README.txt index 295d5741..bb4dceb8 100644 --- a/README.txt +++ b/README.txt @@ -30,6 +30,9 @@ RESOURCES: irc.freenode.org #proxmark3 -or- http://webchat.freenode.net/?channels=#proxmark3 + + * The Homebrew formula repository + https://github.com/Proxmark/homebrew-proxmark3 DEVELOPMENT: diff --git a/armsrc/appmain.c b/armsrc/appmain.c index f4c51e3d..d7159000 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -450,7 +450,7 @@ void StandAloneMode14a() SpinDelay(300); } } - if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid)) + if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid, true, 0)) continue; else { diff --git a/armsrc/epa.c b/armsrc/epa.c index 5e69ffa8..f434aa34 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -530,7 +530,7 @@ int EPA_Setup() // power up the field iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); // select the card - return_code = iso14443a_select_card(uid, &card_select_info, NULL); + return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0); if (return_code == 1) { // send the PPS request ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index bd3bd845..b18a2fe6 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -10,19 +10,74 @@ // Routines to support ISO 14443 type A. //----------------------------------------------------------------------------- +#include "iso14443a.h" + #include "proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" #include "cmd.h" #include "iso14443crc.h" -#include "iso14443a.h" #include "crapto1/crapto1.h" #include "mifareutil.h" +#include "mifaresniff.h" #include "BigBuf.h" #include "protocols.h" #include "parity.h" +typedef struct { + enum { + DEMOD_UNSYNCD, + // DEMOD_HALF_SYNCD, + // DEMOD_MOD_FIRST_HALF, + // DEMOD_NOMOD_FIRST_HALF, + DEMOD_MANCHESTER_DATA + } state; + uint16_t twoBits; + uint16_t highCnt; + uint16_t bitCount; + uint16_t collisionPos; + uint16_t syncBit; + uint8_t parityBits; + uint8_t parityLen; + uint16_t shiftReg; + uint16_t samples; + uint16_t len; + uint32_t startTime, endTime; + uint8_t *output; + uint8_t *parity; +} tDemod; + +typedef enum { + MOD_NOMOD = 0, + MOD_SECOND_HALF, + MOD_FIRST_HALF, + MOD_BOTH_HALVES + } Modulation_t; + +typedef struct { + enum { + STATE_UNSYNCD, + STATE_START_OF_COMMUNICATION, + STATE_MILLER_X, + STATE_MILLER_Y, + STATE_MILLER_Z, + // DROP_NONE, + // DROP_FIRST_HALF, + } state; + uint16_t shiftReg; + int16_t bitCount; + uint16_t len; + uint16_t byteCntMax; + uint16_t posCnt; + uint16_t syncBit; + uint8_t parityBits; + uint8_t parityLen; + uint32_t fourBits; + uint32_t startTime, endTime; + uint8_t *output; + uint8_t *parity; +} tUart; static uint32_t iso14a_timeout; int rsamples = 0; @@ -37,7 +92,7 @@ static uint8_t iso14_pcb_blocknum = 0; #define REQUEST_GUARD_TIME (7000/16 + 1) // minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles #define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1) -// bool LastCommandWasRequest = FALSE; +// bool LastCommandWasRequest = false; // // Total delays including SSC-Transfers between ARM and FPGA. These are in carrier clock cycles (1/13,56MHz) @@ -125,7 +180,6 @@ static uint32_t LastProxToAirDuration; #define SEC_Y 0x00 #define SEC_Z 0xc0 - void iso14a_set_trigger(bool enable) { trigger = enable; } @@ -223,8 +277,8 @@ static tUart Uart; // 0111 - a 2 tick wide pause shifted left // 1001 - a 2 tick wide pause shifted right const bool Mod_Miller_LUT[] = { - FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, - FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE + false, true, false, true, false, false, false, true, + false, true, false, false, false, false, false, false }; #define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4]) #define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)]) @@ -334,13 +388,13 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) Uart.parityBits <<= 1; // add a (void) parity bit Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align parity bits Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it - return TRUE; + return true; } else if (Uart.len & 0x0007) { // there are some parity bits to store Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align remaining parity bits Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them } if (Uart.len) { - return TRUE; // we are finished with decoding the raw data sequence + return true; // we are finished with decoding the raw data sequence } else { UartReset(); // Nothing received - start over } @@ -368,7 +422,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) } - return FALSE; // not finished yet, need more data + return false; // not finished yet, need more data } @@ -393,8 +447,8 @@ static tDemod Demod; // Lookup-Table to decide if 4 raw bits are a modulation. // We accept three or four "1" in any position const bool Mod_Manchester_LUT[] = { - FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, - FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE + false, false, false, false, false, false, false, true, + false, false, false, true, false, true, true, true }; #define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4]) @@ -499,13 +553,13 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non Demod.parityBits <<= 1; // add a (void) parity bit Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them - return TRUE; + return true; } else if (Demod.len & 0x0007) { // there are some parity bits to store Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them } if (Demod.len) { - return TRUE; // we are finished with decoding the raw data sequence + return true; // we are finished with decoding the raw data sequence } else { // nothing received. Start over DemodReset(); } @@ -514,7 +568,7 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non } - return FALSE; // not finished yet, need more data + return false; // not finished yet, need more data } //============================================================================= @@ -553,14 +607,14 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { // init trace buffer clear_trace(); - set_tracing(TRUE); + set_tracing(true); uint8_t *data = dmaBuf; uint8_t previous_data = 0; int maxDataLen = 0; int dataLen = 0; - bool TagIsActive = FALSE; - bool ReaderIsActive = FALSE; + bool TagIsActive = false; + bool ReaderIsActive = false; // Set up the demodulator for tag -> reader responses. DemodInit(receivedResponse, receivedResponsePar); @@ -574,11 +628,11 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a // response from the tag. - // triggered == FALSE -- to wait first for card + // triggered == false -- to wait first for card bool triggered = !(param & 0x03); // And now we loop, receiving samples. - for(uint32_t rsamples = 0; TRUE; ) { + for(uint32_t rsamples = 0; true; ) { if(BUTTON_PRESS()) { DbpString("cancelled by button"); @@ -627,7 +681,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { LED_C_ON(); // check - if there is a short 7bit request from reader - if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = TRUE; + if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = true; if(triggered) { if (!LogTrace(receivedCmd, @@ -635,7 +689,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, Uart.parity, - TRUE)) break; + true)) break; } /* And ready to receive another command. */ UartReset(); @@ -657,9 +711,9 @@ void RAMFUNC SnoopIso14443a(uint8_t param) { Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.parity, - FALSE)) break; + false)) break; - if ((!triggered) && (param & 0x01)) triggered = TRUE; + if ((!triggered) && (param & 0x01)) triggered = true; // And ready to receive another response. DemodReset(); @@ -789,7 +843,7 @@ static void Code4bitAnswerAsTag(uint8_t cmd) //----------------------------------------------------------------------------- // Wait for commands from reader // Stop when button is pressed -// Or return TRUE when command is captured +// Or return true when command is captured //----------------------------------------------------------------------------- static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) { @@ -808,13 +862,13 @@ static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int for(;;) { WDT_HIT(); - if(BUTTON_PRESS()) return FALSE; + if(BUTTON_PRESS()) return false; if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; if(MillerDecoding(b, 0)) { *len = Uart.len; - return TRUE; + return true; } } } @@ -1024,7 +1078,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) // clear trace clear_trace(); - set_tracing(TRUE); + set_tracing(true); // Prepare the responses of the anticollision phase // there will be not enough time to do this at the moment the reader sends it REQA @@ -1078,7 +1132,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) } else if(receivedCmd[0] == 0x50) { // Received a HALT if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); } p_response = NULL; } else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request @@ -1092,7 +1146,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) } } else if (order == 7 && len == 8) { // Received {nr] and {ar} (part of authentication) if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); } uint32_t nr = bytes_to_num(receivedCmd,4); uint32_t ar = bytes_to_num(receivedCmd+4,4); @@ -1136,7 +1190,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) default: { // Never seen this command before if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); } Dbprintf("Received unknown command (len=%d):",len); Dbhexdump(len,receivedCmd,false); @@ -1156,7 +1210,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) if (prepare_tag_modulation(&dynamic_response_info,DYNAMIC_MODULATION_BUFFER_SIZE) == false) { Dbprintf("Error preparing tag response"); if (tracing) { - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); } break; } @@ -1450,7 +1504,7 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe // include correction bit if necessary if (Uart.parityBits & 0x01) { - correctionNeeded = TRUE; + correctionNeeded = true; } if(correctionNeeded) { // 1236, so correction bit needed @@ -1571,18 +1625,18 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; reader_EndTime = tag_StartTime - exact_fdt; reader_StartTime = reader_EndTime - reader_modlen; - if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, TRUE)) { - return FALSE; - } else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, FALSE)); + if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, true)) { + return false; + } else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false)); } else { - return TRUE; + return true; } } //----------------------------------------------------------------------------- // Wait a certain time for tag response -// If a response is captured return TRUE -// If it takes too long return FALSE +// If a response is captured return true +// If it takes too long return false //----------------------------------------------------------------------------- static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { @@ -1608,9 +1662,9 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; if(ManchesterDecoding(b, offset, 0)) { NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD); - return TRUE; + return true; } else if (c++ > iso14a_timeout && Demod.state == DEMOD_UNSYNCD) { - return FALSE; + return false; } } } @@ -1628,7 +1682,7 @@ void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t // Log reader command in trace buffer if (tracing) { - LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, TRUE); + LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, true); } } @@ -1658,26 +1712,28 @@ void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return FALSE; + if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return false; if (tracing) { - LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE); + LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false); } return Demod.len; } int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) return FALSE; + if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) return false; if (tracing) { - LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, FALSE); + LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false); } return Demod.len; } -/* performs iso14443a anticollision procedure - * fills the uid pointer unless NULL - * fills resp_data unless NULL */ -int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) { +// performs iso14443a anticollision (optional) and card select procedure +// fills the uid and cuid pointer unless NULL +// fills the card info record unless NULL +// if anticollision is false, then the UID must be provided in uid_ptr[] +// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) +int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades) { 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}; @@ -1692,7 +1748,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u int len; // Broadcast for a card, WUPA (0x52) will force response from all cards in the field - ReaderTransmitBitsPar(wupa,7,0, NULL); + ReaderTransmitBitsPar(wupa, 7, NULL, NULL); // Receive the ATQA if(!ReaderReceive(resp, resp_par)) return 0; @@ -1703,9 +1759,11 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u memset(p_hi14a_card->uid,0,10); } - // clear uid - if (uid_ptr) { - memset(uid_ptr,0,10); + if (anticollision) { + // clear uid + if (uid_ptr) { + memset(uid_ptr,0,10); + } } // check for proprietary anticollision: @@ -1720,40 +1778,49 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; - // SELECT_ALL - ReaderTransmit(sel_all, sizeof(sel_all), NULL); - if (!ReaderReceive(resp, resp_par)) return 0; - - if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit - memset(uid_resp, 0, 4); - uint16_t uid_resp_bits = 0; - uint16_t collision_answer_offset = 0; - // anti-collision-loop: - while (Demod.collisionPos) { - Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); - for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point - uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; - uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8); + if (anticollision) { + // SELECT_ALL + ReaderTransmit(sel_all, sizeof(sel_all), NULL); + if (!ReaderReceive(resp, resp_par)) return 0; + + if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit + memset(uid_resp, 0, 4); + uint16_t uid_resp_bits = 0; + uint16_t collision_answer_offset = 0; + // anti-collision-loop: + while (Demod.collisionPos) { + Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); + for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point + uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; + uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8); + } + uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position + uid_resp_bits++; + // construct anticollosion command: + sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits + for (uint16_t i = 0; i <= uid_resp_bits/8; i++) { + sel_uid[2+i] = uid_resp[i]; + } + collision_answer_offset = uid_resp_bits%8; + ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); + if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0; } - uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position - uid_resp_bits++; - // construct anticollosion command: - sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits - for (uint16_t i = 0; i <= uid_resp_bits/8; i++) { - sel_uid[2+i] = uid_resp[i]; + // finally, add the last bits and BCC of the UID + for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) { + uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; + uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); } - collision_answer_offset = uid_resp_bits%8; - ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); - if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0; + + } else { // no collision, use the response to SELECT_ALL as current uid + memcpy(uid_resp, resp, 4); } - // finally, add the last bits and BCC of the UID - for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) { - uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; - uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); + } else { + if (cascade_level < num_cascades - 1) { + uid_resp[0] = 0x88; + memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); + } else { + memcpy(uid_resp, uid_ptr+cascade_level*3, 4); } - - } else { // no collision, use the response to SELECT_ALL as current uid - memcpy(uid_resp, resp, 4); } uid_resp_len = 4; @@ -1764,7 +1831,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u // Construct SELECT UID command sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) - memcpy(sel_uid+2, uid_resp, 4); // the UID + memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC AppendCrc14443a(sel_uid, 7); // calculate and add CRC ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); @@ -1772,19 +1839,18 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u // Receive the SAK if (!ReaderReceive(resp, resp_par)) return 0; sak = resp[0]; - - // Test if more parts of the uid are coming + + // Test if more parts of the uid are coming 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 uid_resp[0] = uid_resp[1]; uid_resp[1] = uid_resp[2]; uid_resp[2] = uid_resp[3]; - uid_resp_len = 3; } - if(uid_ptr) { + if(uid_ptr && anticollision) { memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); } @@ -1895,17 +1961,17 @@ void ReaderIso14443a(UsbCommand *c) clear_trace(); } - set_tracing(TRUE); + set_tracing(true); if(param & ISO14A_REQUEST_TRIGGER) { - iso14a_set_trigger(TRUE); + iso14a_set_trigger(true); } if(param & ISO14A_CONNECT) { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if(!(param & ISO14A_NO_SELECT)) { iso14a_card_select_t *card = (iso14a_card_select_t*)buf; - arg0 = iso14443a_select_card(NULL,card,NULL); + arg0 = iso14443a_select_card(NULL, card, NULL, true, 0); cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t)); } } @@ -1959,7 +2025,7 @@ void ReaderIso14443a(UsbCommand *c) } if(param & ISO14A_REQUEST_TRIGGER) { - iso14a_set_trigger(FALSE); + iso14a_set_trigger(false); } if(param & ISO14A_NO_DISCONNECT) { @@ -2019,12 +2085,12 @@ void ReaderMifare(bool first_try) BigBuf_free(); clear_trace(); - set_tracing(TRUE); + set_tracing(true); byte_t nt_diff = 0; uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough static byte_t par_low = 0; - bool led_on = TRUE; + bool led_on = true; uint8_t uid[10] ={0}; uint32_t cuid; @@ -2074,7 +2140,7 @@ void ReaderMifare(bool first_try) uint32_t select_time; uint32_t halt_time; - for(uint16_t i = 0; TRUE; i++) { + for(uint16_t i = 0; true; i++) { LED_C_ON(); WDT_HIT(); @@ -2102,7 +2168,7 @@ void ReaderMifare(bool first_try) SpinDelay(100); } - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card"); continue; } @@ -2283,7 +2349,7 @@ void ReaderMifare(bool first_try) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - set_tracing(FALSE); + set_tracing(false); } typedef struct { @@ -2481,9 +2547,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // clear trace clear_trace(); - set_tracing(TRUE); + set_tracing(true); - bool finished = FALSE; + bool finished = false; bool button_pushed = BUTTON_PRESS(); while (!button_pushed && !finished && !usb_poll_validate_length()) { WDT_HIT(); @@ -2529,7 +2595,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * case MFEMUL_NOFIELD: case MFEMUL_HALTED: case MFEMUL_IDLE:{ - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } case MFEMUL_SELECT1:{ @@ -2570,7 +2636,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } case MFEMUL_SELECT3:{ if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } // select all cl3 - 0x97 0x20 @@ -2596,7 +2662,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * case MFEMUL_AUTH1:{ if( len != 8) { cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } @@ -2679,7 +2745,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // reader to do a WUPA after a while. /Martin // -- which is the correct response. /piwi cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } @@ -2698,7 +2764,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } case MFEMUL_SELECT2:{ if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } // select all cl2 - 0x95 0x20 @@ -2728,7 +2794,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // i guess there is a command). go into the work state. if (len != 4) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } cardSTATE = MFEMUL_WORK; @@ -2738,7 +2804,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * case MFEMUL_WORK:{ if (len == 0) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } @@ -2798,7 +2864,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } if(len != 4) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } @@ -2877,7 +2943,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * LED_C_OFF(); cardSTATE = MFEMUL_HALTED; if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } // RATS @@ -2898,7 +2964,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE = MFEMUL_WORK; } else { cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); } break; } @@ -2911,7 +2977,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE_TO_IDLE(); break; } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); cardINTREG = cardINTREG + ans; cardSTATE = MFEMUL_WORK; break; @@ -2924,7 +2990,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE_TO_IDLE(); break; } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); cardINTREG = cardINTREG - ans; cardSTATE = MFEMUL_WORK; break; @@ -2937,7 +3003,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE_TO_IDLE(); break; } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); cardSTATE = MFEMUL_WORK; break; } @@ -2999,7 +3065,7 @@ void RAMFUNC SniffMifare(uint8_t param) { LEDsoff(); // init trace buffer clear_trace(); - set_tracing(TRUE); + set_tracing(true); // The command (reader -> tag) that we're receiving. // The length of a received command will in most cases be no more than 18 bytes. @@ -3020,8 +3086,8 @@ void RAMFUNC SniffMifare(uint8_t param) { uint8_t previous_data = 0; int maxDataLen = 0; int dataLen = 0; - bool ReaderIsActive = FALSE; - bool TagIsActive = FALSE; + bool ReaderIsActive = false; + bool TagIsActive = false; // Set up the demodulator for tag -> reader responses. DemodInit(receivedResponse, receivedResponsePar); @@ -3038,7 +3104,7 @@ void RAMFUNC SniffMifare(uint8_t param) { MfSniffInit(); // And now we loop, receiving samples. - for(uint32_t sniffCounter = 0; TRUE; ) { + for(uint32_t sniffCounter = 0; true; ) { if(BUTTON_PRESS()) { DbpString("cancelled by button"); @@ -3056,8 +3122,8 @@ void RAMFUNC SniffMifare(uint8_t param) { sniffCounter = 0; data = dmaBuf; maxDataLen = 0; - ReaderIsActive = FALSE; - TagIsActive = FALSE; + ReaderIsActive = false; + TagIsActive = false; FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. } } @@ -3099,7 +3165,7 @@ void RAMFUNC SniffMifare(uint8_t param) { uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); if(MillerDecoding(readerdata, (sniffCounter-1)*4)) { LED_C_INV(); - if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break; + if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, true)) break; /* And ready to receive another command. */ UartInit(receivedCmd, receivedCmdPar); @@ -3115,7 +3181,7 @@ void RAMFUNC SniffMifare(uint8_t param) { if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) { LED_C_INV(); - if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, FALSE)) break; + if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, false)) break; // And ready to receive another response. DemodReset(); diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 60833f18..658216e7 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -13,63 +13,9 @@ #ifndef __ISO14443A_H #define __ISO14443A_H -#include "common.h" -#include "mifaresniff.h" - -typedef struct { - enum { - DEMOD_UNSYNCD, - // DEMOD_HALF_SYNCD, - // DEMOD_MOD_FIRST_HALF, - // DEMOD_NOMOD_FIRST_HALF, - DEMOD_MANCHESTER_DATA - } state; - uint16_t twoBits; - uint16_t highCnt; - uint16_t bitCount; - uint16_t collisionPos; - uint16_t syncBit; - uint8_t parityBits; - uint8_t parityLen; - uint16_t shiftReg; - uint16_t samples; - uint16_t len; - uint32_t startTime, endTime; - uint8_t *output; - uint8_t *parity; -} tDemod; - -typedef enum { - MOD_NOMOD = 0, - MOD_SECOND_HALF, - MOD_FIRST_HALF, - MOD_BOTH_HALVES - } Modulation_t; - -typedef struct { - enum { - STATE_UNSYNCD, - STATE_START_OF_COMMUNICATION, - STATE_MILLER_X, - STATE_MILLER_Y, - STATE_MILLER_Z, - // DROP_NONE, - // DROP_FIRST_HALF, - } state; - uint16_t shiftReg; - int16_t bitCount; - uint16_t len; - uint16_t byteCntMax; - uint16_t posCnt; - uint16_t syncBit; - uint8_t parityBits; - uint8_t parityLen; - uint32_t fourBits; - uint32_t startTime, endTime; - uint8_t *output; - uint8_t *parity; -} tUart; - +#include +#include +#include "mifare.h" extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); extern void AppendCrc14443a(uint8_t *data, int len); @@ -81,7 +27,6 @@ extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); extern void iso14443a_setup(uint8_t fpga_minor_mode); extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); -extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr); +extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades); extern void iso14a_set_trigger(bool enable); - #endif /* __ISO14443A_H */ diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 8f141d65..6f57c113 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -14,13 +14,18 @@ //----------------------------------------------------------------------------- #include "mifarecmd.h" + #include "apps.h" #include "util.h" #include "parity.h" #include "crc.h" +#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication + + // the block number for the ISO14443-4 PCB -uint8_t pcb_blocknum = 0; +static 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}; @@ -54,7 +59,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; @@ -101,7 +106,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ clear_trace(); - if(!iso14443a_select_card(NULL, NULL, NULL)) { + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; @@ -136,7 +141,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) clear_trace(); - int len = iso14443a_select_card(NULL, NULL, NULL); + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); OnError(1); @@ -212,7 +217,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); isOK = 1; - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { isOK = 0; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } @@ -276,7 +281,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) return; } - int len = iso14443a_select_card(NULL, NULL, NULL); + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0); if (!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); OnError(1); @@ -378,7 +383,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LED_C_OFF(); while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; @@ -432,7 +437,7 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) clear_trace(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - if(!iso14443a_select_card(uid, NULL, NULL)) { + if(!iso14443a_select_card(uid, NULL, NULL, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); return; @@ -478,7 +483,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) clear_trace(); - if(!iso14443a_select_card(NULL, NULL, NULL)) { + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); return; @@ -537,7 +542,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ clear_trace(); - if(!iso14443a_select_card(NULL, NULL, NULL)) { + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); return; @@ -602,6 +607,135 @@ int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { } +//----------------------------------------------------------------------------- +// acquire encrypted nonces in order to perform the attack described in +// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Computer and Communications Security, 2015 +//----------------------------------------------------------------------------- +void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) +{ + uint64_t ui64Key = 0; + uint8_t uid[10]; + uint32_t cuid; + uint8_t cascade_levels = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + int16_t isOK = 0; + uint8_t par_enc[1]; + uint8_t nt_par_enc = 0; + uint8_t buf[USB_CMD_DATA_SIZE]; + uint32_t timeout; + + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + uint8_t targetBlockNo = arg1 & 0xff; + uint8_t targetKeyType = (arg1 >> 8) & 0xff; + ui64Key = bytes_to_num(datain, 6); + bool initialize = flags & 0x0001; + bool slow = flags & 0x0002; + bool field_off = flags & 0x0004; + + LED_A_ON(); + LED_C_OFF(); + + if (initialize) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + } + + LED_C_ON(); + + uint16_t num_nonces = 0; + bool have_uid = false; + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { + + // Test if the action was cancelled + if(BUTTON_PRESS()) { + isOK = 2; + field_off = true; + break; + } + + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + continue; + } + } + + if (slow) { + timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME; + while(GetCountSspClk() < timeout); + } + + uint32_t nt1; + if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); + continue; + } + + // nested authentication + uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); + if (len != 4) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); + continue; + } + + // send a dummy byte as reader response in order to trigger the cards authentication timeout + uint8_t dummy_answer = 0; + ReaderTransmit(&dummy_answer, 1, NULL); + timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; + + num_nonces++; + if (num_nonces % 2) { + memcpy(buf+i, receivedAnswer, 4); + nt_par_enc = par_enc[0] & 0xf0; + } else { + nt_par_enc |= par_enc[0] >> 4; + memcpy(buf+i+4, receivedAnswer, 4); + memcpy(buf+i+8, &nt_par_enc, 1); + i += 9; + } + + // wait for the card to become ready again + while(GetCountSspClk() < timeout); + + } + + LED_C_OFF(); + + crypto1_destroy(pcs); + + LED_B_ON(); + cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); + LED_B_OFF(); + + if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); + + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } +} + + //----------------------------------------------------------------------------- // MIFARE nested authentication. // @@ -673,7 +807,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat continue; } - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); rtr--; continue; @@ -747,7 +881,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat continue; } - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Can't select card"); continue; }; @@ -829,14 +963,15 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat //----------------------------------------------------------------------------- void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { - // params uint8_t blockNo = arg0 & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff; bool clearTrace = arg1; uint8_t keyCount = arg2; uint64_t ui64Key = 0; - // variables + bool have_uid = false; + uint8_t cascade_levels = 0; + uint32_t timeout = 0; int i; byte_t isOK = 0; uint8_t uid[10]; @@ -855,30 +990,51 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if (clearTrace) clear_trace(); - set_tracing(TRUE); + set_tracing(true); for (i = 0; i < keyCount; i++) { - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error"); +// if(mifare_classic_halt(pcs, cuid)) { +// if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error"); +// } + + // Iceman: use piwi's faster nonce collecting part in hardnested. + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) { + if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card"); + --i; // try same key once again + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) { + if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); + --i; // try same key once again + continue; + } } - if(!iso14443a_select_card(uid, NULL, &cuid)) { - if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card"); - break; - }; - ui64Key = bytes_to_num(datain + i * 6, 6); if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + uint8_t dummy_answer = 0; + ReaderTransmit(&dummy_answer, 1, NULL); + timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; + + // wait for the card to become ready again + while(GetCountSspClk() < timeout); continue; - }; + } isOK = 1; break; } - // ----------------------------- crypto1 destroy - crypto1_destroy(pcs); - LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6); LED_B_OFF(); @@ -955,7 +1111,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai bool isOK = true; - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { isOK = false; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } @@ -1048,14 +1204,14 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); - set_tracing(TRUE); + set_tracing(true); } while (true) { // get UID from chip if (workFlags & 0x01) { - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; @@ -1167,7 +1323,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); - set_tracing(TRUE); + set_tracing(true); } while (true) { @@ -1260,7 +1416,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); - int len = iso14443a_select_card(uid, NULL, &cuid); + int len = iso14443a_select_card(uid, NULL, &cuid, true, 0); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); OnError(1); diff --git a/client/Makefile b/client/Makefile index a6b1942f..3b4ce89e 100644 --- a/client/Makefile +++ b/client/Makefile @@ -3,11 +3,15 @@ # at your option, any later version. See the LICENSE.txt file for the text of # the license. #----------------------------------------------------------------------------- -include ../common/Makefile.common +CC = gcc +CXX = g++ +LD = g++ +TAR = tar +TARFLAGS = -C .. --ignore-failed-read -rvf +RM = rm -f +MV = mv -CC=gcc -CXX=g++ #COMMON_FLAGS = -m32 VPATH = ../common ../zlib OBJDIR = obj @@ -15,46 +19,52 @@ OBJDIR = obj LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm LUALIB = ../liblua/liblua.a LDFLAGS = $(COMMON_FLAGS) -CFLAGS = -std=c99 -D_ISOC99_SOURCE -I. -I../include -I../common -I../tools -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 +CFLAGS = -std=c99 -D_ISOC99_SOURCE -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 LUAPLATFORM = generic +platform = $(shell uname) ifneq (,$(findstring MINGW,$(platform))) CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui - MOC = $(QTDIR)/bin/moc - LUAPLATFORM = mingw ifneq ($(wildcard $(QTDIR)/include/QtWidgets),) CXXFLAGS += -I$(QTDIR)/include/QtWidgets QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets else QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4 endif -else ifeq ($(platform),Darwin) - CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4 - QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) - MOC = $(shell pkg-config --variable=moc_location QtCore) - LUAPLATFORM = macosx + MOC = $(QTDIR)/bin/moc + LUAPLATFORM = mingw else - CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4 - QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) - LUALIB += -ldl - LDLIBS += -ltermcap -lncurses - MOC = $(shell pkg-config --variable=moc_location QtCore) - # Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info. - #MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc - LUAPLATFORM = linux + CXXFLAGS = $(shell pkg-config --cflags Qt5Core Qt5Widgets 2>/dev/null) -Wall -O4 + QTLDLIBS = $(shell pkg-config --libs Qt5Core Qt5Widgets 2>/dev/null) + MOC = $(shell pkg-config --variable=host_bins Qt5Core)/moc + ifeq ($(QTLDLIBS), ) + CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4 + QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) + MOC = $(shell pkg-config --variable=moc_location QtCore) + endif + ifeq ($(platform),Darwin) + LUAPLATFORM = macosx + else + LUALIB += -ldl + LDLIBS += -ltermcap -lncurses + LUAPLATFORM = linux + endif endif ifneq ($(QTLDLIBS),) - QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o + QTGUIOBJS = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o CFLAGS += -DHAVE_GUI - LINK.o = $(LINK.cpp) else - QTGUI = guidummy.o + QTGUIOBJS = $(OBJDIR)/guidummy.o endif -CORESRCS = uart.c \ - util.c \ +# Flags to generate temporary dependency files +DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td +# make temporary to final dependeny files after successful compilation +POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d +CORESRCS = uart.c \ + util.c CMDSRCS = crapto1/crapto1.c\ crapto1/crypto1.c\ @@ -129,57 +139,82 @@ CMDSRCS = crapto1/crapto1.c\ reveng/getopt.c\ ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c -ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED +ZLIBFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED #-DDEBUG -Dverbose=1 +QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp guidummy.cpp COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o) -RM = rm -f -BINS = proxmark3 flasher fpga_compress #snooper cli -CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe fpga_compress fpga_compress.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp +BINS = proxmark3 flasher fpga_compress +WINBINS = $(patsubst %, %.exe, $(BINS)) +CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(OBJDIR)/*.o *.moc.cpp -all: lua_build $(BINS) +all: lua_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) -all-static: snooper cli flasher fpga_compress +all-static: proxmark3 flasher fpga_compress proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS) -proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUI) - $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ - -snooper: $(OBJDIR)/snooper.o $(COREOBJS) $(CMDOBJS) $(OBJDIR)/guidummy.o - $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ - -cli: $(OBJDIR)/cli.o $(COREOBJS) $(CMDOBJS) $(OBJDIR)/guidummy.o - $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ +proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUIOBJS) lualibs/usb_cmd.lua + $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUIOBJS) $(LDLIBS) -o $@ flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) - $(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@ + $(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS) - $(CXX) $(CXXFLAGS) $(ZLIB_FLAGS) $^ $(LDLIBS) -o $@ - -$(OBJDIR)/%.o: %.c - $(CC) $(CFLAGS) $(ZLIB_FLAGS) -c -o $@ $< - -$(OBJDIR)/%.o: %.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< + $(LD) $(LDFLAGS) $(ZLIBFLAGS) $^ $(LDLIBS) -o $@ proxguiqt.moc.cpp: proxguiqt.h $(MOC) -o$@ $^ +lualibs/usb_cmd.lua: ../include/usb_cmd.h + awk -f usb_cmd_h2lua.awk $^ > $@ + clean: $(RM) $(CLEAN) cd ../liblua && make clean tarbin: $(BINS) - $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) + $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) lua_build: @echo Compiling liblua, using platform $(LUAPLATFORM) cd ../liblua && make $(LUAPLATFORM) .PHONY: all clean + +%.o: %.c +$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d + $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $< + $(POSTCOMPILE) + +%.o: %.cpp +$(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d + $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c -o $@ $< + $(POSTCOMPILE) + + +#$(CMDOBJS) $(COREOBJS): $(notdir $(%.c)) %.d +# $(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< +# $(POSTCOMPILE) + +#$(ZLIBOBJS): $(notdir $(%.c)) %.d +# $(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $< +# $(POSTCOMPILE) + +#$(QTGUIOBJS): $(notdir $(%.cpp)) %.d +# $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c -o $@ $< +# $(POSTCOMPILE) + +DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBSRCS)) \ + $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ + $(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d + +$(DEPENDENCY_FILES): ; +.PRECIOUS: $(DEPENDENCY_FILES) + +-include $(DEPENDENCY_FILES) + diff --git a/client/cli.c b/client/cli.c deleted file mode 100644 index c5c2acf4..00000000 --- a/client/cli.c +++ /dev/null @@ -1,58 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- -// Command line binary -//----------------------------------------------------------------------------- - -#include -#include "sleep.h" -#include "ui.h" -#include "proxusb.h" -#include "cmdmain.h" - -#define HANDLE_ERROR if (error_occured) { \ - error_occured = 0;\ - break;\ -} - -int main(int argc, char **argv) -{ - if (argc != 3 && argc != 4) - { - printf("\n\tusage: cli [logfile (default cli.log)]\n"); - printf("\n"); - printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); - printf("\n"); - return -1; - } - - usb_init(); - if (argc == 4) - SetLogFilename(argv[3]); - else - SetLogFilename("cli.log"); - - return_on_error = 1; - - while (1) { - while (!OpenProxmark(0)) { sleep(1); } - while (1) { - UsbCommand cmdbuf; - CommandReceived(argv[1]); - HANDLE_ERROR; - ReceiveCommand(&cmdbuf); - HANDLE_ERROR; - for (int i = 0; i < 5; ++i) { - ReceiveCommandPoll(&cmdbuf); - } - HANDLE_ERROR; - CommandReceived(argv[2]); - HANDLE_ERROR; - } - } - - CloseProxmark(); - return 0; -} diff --git a/client/guidummy.c b/client/guidummy.c deleted file mode 100644 index b42dea24..00000000 --- a/client/guidummy.c +++ /dev/null @@ -1,27 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2009 Michael Gernoth -// -// 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. -//----------------------------------------------------------------------------- -// GUI dummy file -//----------------------------------------------------------------------------- - -#include - -void ShowGraphWindow(void) -{ - static int warned = 0; - - if (!warned) { - printf("No GUI in this build!\n"); - warned = 1; - } -} - -void HideGraphWindow(void) {} -void RepaintGraphWindow(void) {} -void MainGraphics() {} -void InitGraphics(int argc, char **argv) {} -void ExitGraphics(void) {} diff --git a/client/guidummy.cpp b/client/guidummy.cpp new file mode 100644 index 00000000..6c24973b --- /dev/null +++ b/client/guidummy.cpp @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// +// 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. +//----------------------------------------------------------------------------- +// GUI dummy file +//----------------------------------------------------------------------------- + +#include + +extern "C" void ShowGraphWindow(void) +{ + static int warned = 0; + + if (!warned) { + printf("No GUI in this build!\n"); + warned = 1; + } +} + +extern "C" void HideGraphWindow(void) {} +extern "C" void RepaintGraphWindow(void) {} +extern "C" void MainGraphics() {} +extern "C" void InitGraphics(int argc, char **argv) {} +extern "C" void ExitGraphics(void) {} diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 2a97196a..dadd2fc5 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -1,164 +1,8 @@ --[[ -These are command definitions. This file should correspond exactly to usb_cmd.h. +Handle Proxmark USB Commands --]] ---// For the bootloader -local _commands = { - CMD_DEVICE_INFO = 0x0000, - CMD_SETUP_WRITE = 0x0001, - CMD_FINISH_WRITE = 0x0003, - CMD_HARDWARE_RESET = 0x0004, - CMD_START_FLASH = 0x0005, - CMD_NACK = 0x00fe, - CMD_ACK = 0x00ff, - - --// For general mucking around - CMD_DEBUG_PRINT_STRING = 0x0100, - CMD_DEBUG_PRINT_INTEGERS = 0x0101, - CMD_DEBUG_PRINT_BYTES = 0x0102, - CMD_LCD_RESET = 0x0103, - CMD_LCD = 0x0104, - 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, - CMD_DOWNLOADED_RAW_BITS_TI_TYPE = 0x0204, - CMD_ACQUIRE_RAW_ADC_SAMPLES_125K = 0x0205, - CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K = 0x0206, - CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K = 0x0207, - CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K = 0x0208, - CMD_DOWNLOADED_SIM_SAMPLES_125K = 0x0209, - CMD_SIMULATE_TAG_125K = 0x020A, - CMD_HID_DEMOD_FSK = 0x020B, - CMD_HID_SIM_TAG = 0x020C, - CMD_SET_LF_DIVISOR = 0x020D, - CMD_LF_SIMULATE_BIDIR = 0x020E, - CMD_SET_ADC_MUX = 0x020F, - CMD_HID_CLONE_TAG = 0x0210, - CMD_EM410X_WRITE_TAG = 0x0211, - CMD_INDALA_CLONE_TAG = 0x0212, - --// for 224 bits UID - CMD_INDALA_CLONE_TAG_L = 0x0213, - CMD_T55XX_READ_BLOCK = 0x0214, - CMD_T55XX_WRITE_BLOCK = 0x0215, - CMD_T55XX_RESET_READ = 0x0216, - CMD_PCF7931_READ = 0x0217, - CMD_EM4X_READ_WORD = 0x0218, - CMD_EM4X_WRITE_WORD = 0x0219, - CMD_IO_DEMOD_FSK = 0x021A, - CMD_IO_CLONE_TAG = 0x021B, - CMD_EM410X_DEMOD = 0x021c, - CMD_SET_LF_SAMPLING_CONFIG = 0x021d, - CMD_FSK_SIM_TAG = 0x021E, - CMD_ASK_SIM_TAG = 0x021F, - CMD_PSK_SIM_TAG = 0x0220, - CMD_AWID_DEMOD_FSK = 0x0221, - CMD_VIKING_CLONE_TAG = 0x0223, - CMD_T55XX_WAKEUP = 0x0224, - CMD_COTAG = 0x0225, - --/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ - - --// For the 13.56 MHz tags - CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300, - CMD_READ_SRI512_TAG = 0x0303, - CMD_READ_SRIX4K_TAG = 0x0304, - CMD_READER_ISO_15693 = 0x0310, - CMD_SIMTAG_ISO_15693 = 0x0311, - CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 = 0x0312, - CMD_ISO_15693_COMMAND = 0x0313, - CMD_ISO_15693_COMMAND_DONE = 0x0314, - CMD_ISO_15693_FIND_AFI = 0x0315, - CMD_ISO_15693_DEBUG = 0x0316, - CMD_LF_SNOOP_RAW_ADC_SAMPLES = 0x0317, - - --// For Hitag2 transponders - CMD_SNOOP_HITAG = 0x0370, - CMD_SIMULATE_HITAG = 0x0371, - CMD_READER_HITAG = 0x0372, - - CMD_SIMULATE_TAG_ISO_14443B = 0x0381, - CMD_SNOOP_ISO_14443B = 0x0382, - CMD_SNOOP_ISO_14443a = 0x0383, - CMD_SIMULATE_TAG_ISO_14443a = 0x0384, - CMD_READER_ISO_14443a = 0x0385, - CMD_SIMULATE_TAG_LEGIC_RF = 0x0387, - CMD_READER_LEGIC_RF = 0x0388, - CMD_WRITER_LEGIC_RF = 0x0389, - CMD_EPA_PACE_COLLECT_NONCE = 0x038A, - --//CMD_EPA_ = 0x038B, - - CMD_ICLASS_READCHECK = 0x038F, - CMD_ICLASS_CLONE = 0x0390, - CMD_ICLASS_DUMP = 0x0391, - CMD_SNOOP_ICLASS = 0x0392, - CMD_SIMULATE_TAG_ICLASS = 0x0393, - CMD_READER_ICLASS = 0x0394, - CMD_READER_ICLASS_REPLAY = 0x0395, - CMD_ICLASS_READBLOCK = 0x0396, - CMD_ICLASS_WRITEBLOCK = 0x0397, - CMD_ICLASS_EML_MEMSET = 0x0398, - CMD_ICLASS_AUTHENTICATION = 0x0399, - - --// For measurements of the antenna tuning - CMD_MEASURE_ANTENNA_TUNING = 0x0400, - CMD_MEASURE_ANTENNA_TUNING_HF = 0x0401, - CMD_MEASURED_ANTENNA_TUNING = 0x0410, - CMD_LISTEN_READER_FIELD = 0x0420, - - --// For direct FPGA control - CMD_FPGA_MAJOR_MODE_OFF = 0x0500, - - --// For mifare commands - CMD_MIFARE_SET_DBGMODE = 0x0600, - CMD_MIFARE_EML_MEMCLR = 0x0601, - CMD_MIFARE_EML_MEMSET = 0x0602, - CMD_MIFARE_EML_MEMGET = 0x0603, - CMD_MIFARE_EML_CARDLOAD = 0x0604, - - --// magic chinese card commands - CMD_MIFARE_CSETBLOCK = 0x0605, - CMD_MIFARE_CGETBLOCK = 0x0606, - CMD_MIFARE_CIDENT = 0x0607, - - CMD_SIMULATE_MIFARE_CARD = 0x0610, - - CMD_READER_MIFARE = 0x0611, - CMD_MIFARE_NESTED = 0x0612, - - CMD_MIFARE_READBL = 0x0620, - CMD_MIFAREU_READBL = 0x0720, - - CMD_MIFARE_READSC = 0x0621, - CMD_MIFAREU_READCARD = 0x0721, - - CMD_MIFARE_WRITEBL = 0x0622, - CMD_MIFAREU_WRITEBL = 0x0722, - CMD_MIFAREU_WRITEBL_COMPAT = 0x0723, - - CMD_MIFARE_CHKKEYS = 0x0623, - - CMD_MIFARE_SNIFFER = 0x0630, - - --//ultralightC - CMD_MIFAREUC_AUTH = 0x0724, - CMD_MIFAREUC_SETPWD = 0x0727, - CMD_MIFAREU_SETUID = 0x0728, - - --// mifare desfire - CMD_MIFARE_DESFIRE_READBL = 0x0728, - CMD_MIFARE_DESFIRE_WRITEBL = 0x0729, - CMD_MIFARE_DESFIRE_AUTH1 = 0x072a, - CMD_MIFARE_DESFIRE_AUTH2 = 0x072b, - CMD_MIFARE_DES_READER = 0x072c, - CMD_MIFARE_DESFIRE_INFO = 0x072d, - CMD_MIFARE_DESFIRE = 0x072e, - - CMD_UNKNOWN = 0xFFFF, -} +local _commands = require('usb_cmd') local _reverse_lookup,k,v = {} for k, v in pairs(_commands) do diff --git a/client/lualibs/usb_cmd.lua b/client/lualibs/usb_cmd.lua new file mode 100644 index 00000000..52757990 --- /dev/null +++ b/client/lualibs/usb_cmd.lua @@ -0,0 +1,137 @@ +--[[ +These are Proxmark command definitions. +This file is automatically generated from usb_cmd.h - DON'T EDIT MANUALLY. +--]] +local __commands = { +CMD_DEVICE_INFO = 0x0000, +CMD_SETUP_WRITE = 0x0001, +CMD_FINISH_WRITE = 0x0003, +CMD_HARDWARE_RESET = 0x0004, +CMD_START_FLASH = 0x0005, +CMD_NACK = 0x00fe, +CMD_ACK = 0x00ff, +CMD_DEBUG_PRINT_STRING = 0x0100, +CMD_DEBUG_PRINT_INTEGERS = 0x0101, +CMD_DEBUG_PRINT_BYTES = 0x0102, +CMD_LCD_RESET = 0x0103, +CMD_LCD = 0x0104, +CMD_BUFF_CLEAR = 0x0105, +CMD_READ_MEM = 0x0106, +CMD_VERSION = 0x0107, +CMD_STATUS = 0x0108, +CMD_PING = 0x0109, +CMD_READ_TI_TYPE = 0x0202, +CMD_WRITE_TI_TYPE = 0x0203, +CMD_DOWNLOADED_RAW_BITS_TI_TYPE = 0x0204, +CMD_ACQUIRE_RAW_ADC_SAMPLES_125K = 0x0205, +CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K = 0x0206, +CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K = 0x0207, +CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K = 0x0208, +CMD_DOWNLOADED_SIM_SAMPLES_125K = 0x0209, +CMD_SIMULATE_TAG_125K = 0x020A, +CMD_HID_DEMOD_FSK = 0x020B, +CMD_HID_SIM_TAG = 0x020C, +CMD_SET_LF_DIVISOR = 0x020D, +CMD_LF_SIMULATE_BIDIR = 0x020E, +CMD_SET_ADC_MUX = 0x020F, +CMD_HID_CLONE_TAG = 0x0210, +CMD_EM410X_WRITE_TAG = 0x0211, +CMD_INDALA_CLONE_TAG = 0x0212, +CMD_INDALA_CLONE_TAG_L = 0x0213, +CMD_T55XX_READ_BLOCK = 0x0214, +CMD_T55XX_WRITE_BLOCK = 0x0215, +CMD_T55XX_RESET_READ = 0x0216, +CMD_PCF7931_READ = 0x0217, +CMD_PCF7931_WRITE = 0x0222, +CMD_EM4X_READ_WORD = 0x0218, +CMD_EM4X_WRITE_WORD = 0x0219, +CMD_IO_DEMOD_FSK = 0x021A, +CMD_IO_CLONE_TAG = 0x021B, +CMD_EM410X_DEMOD = 0x021c, +CMD_SET_LF_SAMPLING_CONFIG = 0x021d, +CMD_FSK_SIM_TAG = 0x021E, +CMD_ASK_SIM_TAG = 0x021F, +CMD_PSK_SIM_TAG = 0x0220, +CMD_AWID_DEMOD_FSK = 0x0221, +CMD_VIKING_CLONE_TAG = 0x0223, +CMD_T55XX_WAKEUP = 0x0224, +CMD_COTAG = 0x0225, +CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300, +CMD_READ_SRI512_TAG = 0x0303, +CMD_READ_SRIX4K_TAG = 0x0304, +CMD_ISO_14443B_COMMAND = 0x0305, +CMD_READER_ISO_15693 = 0x0310, +CMD_SIMTAG_ISO_15693 = 0x0311, +CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 = 0x0312, +CMD_ISO_15693_COMMAND = 0x0313, +CMD_ISO_15693_COMMAND_DONE = 0x0314, +CMD_ISO_15693_FIND_AFI = 0x0315, +CMD_ISO_15693_DEBUG = 0x0316, +CMD_LF_SNOOP_RAW_ADC_SAMPLES = 0x0317, +CMD_SNOOP_HITAG = 0x0370, +CMD_SIMULATE_HITAG = 0x0371, +CMD_READER_HITAG = 0x0372, +CMD_SIMULATE_HITAG_S = 0x0368, +CMD_TEST_HITAGS_TRACES = 0x0367, +CMD_READ_HITAG_S = 0x0373, +CMD_WR_HITAG_S = 0x0375, +CMD_EMU_HITAG_S = 0x0376, +CMD_SIMULATE_TAG_ISO_14443B = 0x0381, +CMD_SNOOP_ISO_14443B = 0x0382, +CMD_SNOOP_ISO_14443a = 0x0383, +CMD_SIMULATE_TAG_ISO_14443a = 0x0384, +CMD_READER_ISO_14443a = 0x0385, +CMD_SIMULATE_TAG_LEGIC_RF = 0x0387, +CMD_READER_LEGIC_RF = 0x0388, +CMD_WRITER_LEGIC_RF = 0x0389, +CMD_EPA_PACE_COLLECT_NONCE = 0x038A, +CMD_EPA_PACE_REPLAY = 0x038B, +CMD_ICLASS_READCHECK = 0x038F, +CMD_ICLASS_CLONE = 0x0390, +CMD_ICLASS_DUMP = 0x0391, +CMD_SNOOP_ICLASS = 0x0392, +CMD_SIMULATE_TAG_ICLASS = 0x0393, +CMD_READER_ICLASS = 0x0394, +CMD_READER_ICLASS_REPLAY = 0x0395, +CMD_ICLASS_READBLOCK = 0x0396, +CMD_ICLASS_WRITEBLOCK = 0x0397, +CMD_ICLASS_EML_MEMSET = 0x0398, +CMD_ICLASS_AUTHENTICATION = 0x0399, +CMD_MEASURE_ANTENNA_TUNING = 0x0400, +CMD_MEASURE_ANTENNA_TUNING_HF = 0x0401, +CMD_MEASURED_ANTENNA_TUNING = 0x0410, +CMD_LISTEN_READER_FIELD = 0x0420, +CMD_FPGA_MAJOR_MODE_OFF = 0x0500, +CMD_MIFARE_SET_DBGMODE = 0x0600, +CMD_MIFARE_EML_MEMCLR = 0x0601, +CMD_MIFARE_EML_MEMSET = 0x0602, +CMD_MIFARE_EML_MEMGET = 0x0603, +CMD_MIFARE_EML_CARDLOAD = 0x0604, +CMD_MIFARE_CSETBLOCK = 0x0605, +CMD_MIFARE_CGETBLOCK = 0x0606, +CMD_MIFARE_CIDENT = 0x0607, +CMD_SIMULATE_MIFARE_CARD = 0x0610, +CMD_READER_MIFARE = 0x0611, +CMD_MIFARE_NESTED = 0x0612, +CMD_MIFARE_READBL = 0x0620, +CMD_MIFAREU_READBL = 0x0720, +CMD_MIFARE_READSC = 0x0621, +CMD_MIFAREU_READCARD = 0x0721, +CMD_MIFARE_WRITEBL = 0x0622, +CMD_MIFAREU_WRITEBL = 0x0722, +CMD_MIFAREU_WRITEBL_COMPAT = 0x0723, +CMD_MIFARE_CHKKEYS = 0x0623, +CMD_MIFARE_SNIFFER = 0x0630, +CMD_MIFAREUC_AUTH = 0x0724, +CMD_MIFAREUC_SETPWD = 0x0727, +CMD_MIFARE_DESFIRE_READBL = 0x0728, +CMD_MIFARE_DESFIRE_WRITEBL = 0x0729, +CMD_MIFARE_DESFIRE_AUTH1 = 0x072a, +CMD_MIFARE_DESFIRE_AUTH2 = 0x072b, +CMD_MIFARE_DES_READER = 0x072c, +CMD_MIFARE_DESFIRE_INFO = 0x072d, +CMD_MIFARE_DESFIRE = 0x072e, +CMD_HF_SNIFFER = 0x0800, +CMD_UNKNOWN = 0xFFFF, +} +return __commands diff --git a/client/snooper.c b/client/snooper.c deleted file mode 100644 index 14f07063..00000000 --- a/client/snooper.c +++ /dev/null @@ -1,46 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2009 Michael Gernoth -// -// 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. -//----------------------------------------------------------------------------- -// Snooper binary -//----------------------------------------------------------------------------- - -#include "ui.h" -#include "proxusb.h" -#include "cmdmain.h" - -#define HANDLE_ERROR if (error_occured) { \ - error_occured = 0;\ - break;\ -} - -int main() -{ - usb_init(); - SetLogFilename("snooper.log"); - - return_on_error = 1; - - while(1) { - while (!OpenProxmark(0)) { sleep(1); } - while (1) { - UsbCommand cmdbuf; - CommandReceived("hf 14a snoop"); - HANDLE_ERROR; - ReceiveCommand(&cmdbuf); - HANDLE_ERROR; - for (int i = 0; i < 5; ++i) { - ReceiveCommandPoll(&cmdbuf); - } - HANDLE_ERROR; - CommandReceived("hf 14a list"); - HANDLE_ERROR; - } - } - - CloseProxmark(); - return 0; -} diff --git a/client/usb_cmd_h2lua.awk b/client/usb_cmd_h2lua.awk new file mode 100644 index 00000000..8e003562 --- /dev/null +++ b/client/usb_cmd_h2lua.awk @@ -0,0 +1,15 @@ +BEGIN { + print "--[[" + print "These are Proxmark command definitions." + print "This file is automatically generated from usb_cmd.h - DON'T EDIT MANUALLY." + print "--]]" + print "local __commands = {" +} + +#$1 ~ /#define/ && $2 ~ /^CMD_([[:alnum:]_])+/ { print $2, "=", $3, "," } +$1 ~ /#define/ && $2 ~ /^CMD_[A-Za-z0-9_]+/ { sub(/\r/, ""); print $2, "=", $3 "," } + +END { + print "}" + print "return __commands" +} diff --git a/client/util.c b/client/util.c index d07c915c..d4e59165 100644 --- a/client/util.c +++ b/client/util.c @@ -634,13 +634,22 @@ void msleep(uint32_t n) { // a milliseconds timer for performance measurement uint64_t msclock() { #if defined(_WIN32) -#include - struct _timeb t; - if (_ftime_s(&t)) { - return 0; - } else { - return 1000 * t.time + t.millitm; - } + #include + + // WORKAROUND FOR MinGW (some versions - use if normal code does not compile) + // It has no _ftime_s and needs explicit inclusion of timeb.h + #include + struct _timeb t; + _ftime(&t); + return 1000 * t.time + t.millitm; + + // NORMAL CODE (use _ftime_s) + //struct _timeb t; + //if (_ftime_s(&t)) { + // return 0; + //} else { + // return 1000 * t.time + t.millitm; + //} #else struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t);