diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 7702025b..aec01860 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1217,7 +1217,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { int reset_sof; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; - bool bStop; + bool bStop = false; bool bQuitTraceFull = false; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1324,7 +1324,6 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { frame_count = 0; response = 0; lastbit = 1; - bStop = false; // Tag specific configuration settings (sof, timings, etc.) if (htf < 10){ @@ -1369,46 +1368,46 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { // By default reset the transmission buffer tx = txbuf; switch(htf) { - case RHT2F_PASSWORD: { - bStop = !hitag2_password(rx,rxlen,tx,&txlen); - } break; - case RHT2F_AUTHENTICATE: { - bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen); - } break; - case RHT2F_CRYPTO: { - bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, false); - } break; - case RHT2F_TEST_AUTH_ATTEMPTS: { - bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen); - } break; - case RHT2F_UID_ONLY: { - bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen); - attempt_count++; //attempt 3 times to get uid then quit - if (!bStop && attempt_count == 3) bStop = true; - } break; - default: { - Dbprintf("Error, unknown function: %d",htf); - return; - } break; + case RHT2F_PASSWORD: { + bStop = !hitag2_password(rx,rxlen,tx,&txlen); + } break; + case RHT2F_AUTHENTICATE: { + bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen); + } break; + case RHT2F_CRYPTO: { + bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, false); + } break; + case RHT2F_TEST_AUTH_ATTEMPTS: { + bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen); + } break; + case RHT2F_UID_ONLY: { + bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen); + attempt_count++; //attempt 3 times to get uid then quit + if (!bStop && attempt_count == 3) bStop = true; + } break; + default: { + Dbprintf("Error, unknown function: %d",htf); + return; + } break; } - + // Send and store the reader command // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, // Since the clock counts since the last falling edge, a 'one' means that the // falling edge occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit))); - + //Dbprintf("DEBUG: Sending reader frame"); // Transmit the reader frame hitag_reader_send_frame(tx,txlen); - // Enable and reset external trigger in timer for capturing future frames + // Enable and reset external trigger in timer for capturing future frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Add transmitted frame to total count @@ -1521,7 +1520,11 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); //Dbprintf("frame received: %d",frame_count); //DbpString("All done"); - cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48); + if (bSuccessful) + cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48); + else + cmd_send(CMD_ACK,bSuccessful,0,0,0,0); + } void WriterHitag(hitag_function htf, hitag_data* htd, int page) { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 45425e07..ebbddbd8 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -901,11 +901,11 @@ static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int } -static int EmSend4bitEx(uint8_t resp, bool correctionNeeded); +static int EmSend4bitEx(uint8_t resp); int EmSend4bit(uint8_t resp); -static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par); -int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded); -int EmSendPrecompiledCmd(tag_response_info_t *response_info, bool correctionNeeded); +static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, uint8_t *par); +int EmSendCmdEx(uint8_t *resp, uint16_t respLen); +int EmSendPrecompiledCmd(tag_response_info_t *response_info); static bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) { @@ -1139,7 +1139,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x95) { // Received a SELECT (cascade 2) p_response = &responses[4]; order = 30; } else if(receivedCmd[0] == 0x30) { // Received a (plain) READ - EmSendCmdEx(data+(4*receivedCmd[1]),16,false); + EmSendCmdEx(data+(4*receivedCmd[1]),16); // Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]); // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; @@ -1232,7 +1232,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) cmdsRecvd++; if (p_response != NULL) { - EmSendPrecompiledCmd(p_response, receivedCmd[0] == 0x52); + EmSendPrecompiledCmd(p_response); } if (!tracing) { @@ -1414,12 +1414,6 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) int analogCnt = 0; int analogAVG = 0; - // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); - // Set ADC to read field strength AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; AT91C_BASE_ADC->ADC_MR = @@ -1430,12 +1424,23 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) // start ADC AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - // Now run a 'software UART' on the stream of incoming samples. + // Run a 'software UART' on the stream of incoming samples. UartInit(received, parity); - // Clear RXRDY: - uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - + // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN + do { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = SEC_F; + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void) b; + } + } while (GetCountSspClk() < LastTimeProxToAirStart + LastProxToAirDuration + (FpgaSendQueueDelay>>3)); + + // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + for(;;) { WDT_HIT(); @@ -1461,7 +1466,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) // receive and test the miller decoding if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; if(MillerDecoding(b, 0)) { *len = Uart.len; EmLogTraceReader(); @@ -1473,18 +1478,27 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) } -static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded) +static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) { uint8_t b; uint16_t i = 0; - + bool correctionNeeded; + // Modulate Manchester FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); // include correction bit if necessary - if (Uart.parityBits & 0x01) { - correctionNeeded = true; + if (Uart.bitCount == 7) + { + // Short tags (7 bits) don't have parity, determine the correct value from MSB + correctionNeeded = Uart.output[0] & 0x40; } + else + { + // Look at the last parity bit + correctionNeeded = Uart.parity[(Uart.len-1)/8] & (0x80 >> ((Uart.len-1) & 7)); + } + if(correctionNeeded) { // 1236, so correction bit needed i = 0; @@ -1518,23 +1532,13 @@ static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNe } } - // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: - uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; - for (i = 0; i < fpga_queued_bits/8; ) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = SEC_F; - FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - } - } - return 0; } -static int EmSend4bitEx(uint8_t resp, bool correctionNeeded){ +static int EmSend4bitEx(uint8_t resp){ Code4bitAnswerAsTag(resp); - int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); + int res = EmSendCmd14443aRaw(ToSend, ToSendMax); // do the tracing for the previous reader request and this tag answer: EmLogTraceTag(&resp, 1, NULL, LastProxToAirDuration); return res; @@ -1542,40 +1546,40 @@ static int EmSend4bitEx(uint8_t resp, bool correctionNeeded){ int EmSend4bit(uint8_t resp){ - return EmSend4bitEx(resp, false); + return EmSend4bitEx(resp); } -static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par){ +static int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ CodeIso14443aAsTagPar(resp, respLen, par); - int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); + int res = EmSendCmd14443aRaw(ToSend, ToSendMax); // do the tracing for the previous reader request and this tag answer: EmLogTraceTag(resp, respLen, par, LastProxToAirDuration); return res; } -int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded){ +int EmSendCmdEx(uint8_t *resp, uint16_t respLen){ uint8_t par[MAX_PARITY_SIZE]; GetParity(resp, respLen, par); - return EmSendCmdExPar(resp, respLen, correctionNeeded, par); + return EmSendCmdExPar(resp, respLen, par); } int EmSendCmd(uint8_t *resp, uint16_t respLen){ uint8_t par[MAX_PARITY_SIZE]; GetParity(resp, respLen, par); - return EmSendCmdExPar(resp, respLen, false, par); + return EmSendCmdExPar(resp, respLen, par); } int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ - return EmSendCmdExPar(resp, respLen, false, par); + return EmSendCmdExPar(resp, respLen, par); } -int EmSendPrecompiledCmd(tag_response_info_t *response_info, bool correctionNeeded) { - int ret = EmSendCmd14443aRaw(response_info->modulation, response_info->modulation_n, correctionNeeded); +int EmSendPrecompiledCmd(tag_response_info_t *response_info) { + int ret = EmSendCmd14443aRaw(response_info->modulation, response_info->modulation_n); // do the tracing for the previous reader request and this tag answer: EmLogTraceTag(response_info->response, response_info->response_n, &(response_info->par), response_info->ProxToAirDuration); return ret; @@ -1871,7 +1875,30 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { iso14a_set_timeout(1060); // 10ms default } - +/* Peter Fillmore 2015 +Added card id field to the function + info from ISO14443A standard +b1 = Block Number +b2 = RFU (always 1) +b3 = depends on block +b4 = Card ID following if set to 1 +b5 = depends on block type +b6 = depends on block type +b7,b8 = block type. +Coding of I-BLOCK: +b8 b7 b6 b5 b4 b3 b2 b1 +0 0 0 x x x 1 x +b5 = chaining bit +Coding of R-block: +b8 b7 b6 b5 b4 b3 b2 b1 +1 0 1 x x 0 1 x +b5 = ACK/NACK +Coding of S-block: +b8 b7 b6 b5 b4 b3 b2 b1 +1 1 x x x 0 1 0 +b5,b6 = 00 - DESELECT + 11 - WTX +*/ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { uint8_t parity[MAX_PARITY_SIZE]; uint8_t real_cmd[cmd_len + 4]; @@ -1890,10 +1917,23 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { if (!len) { return 0; //DATA LINK ERROR - - // if we received an I- or R(ACK)-Block with a block number equal to the - // current block number, toggle the current block number } else{ + // S-Block WTX + while((data_bytes[0] & 0xF2) == 0xF2) { + // Transmit WTX back + // byte1 - WTXM [1..59]. command FWT=FWT*WTXM + data_bytes[1] = data_bytes[1] & 0x3f; // 2 high bits mandatory set to 0b + // now need to fix CRC. + AppendCrc14443a(data_bytes, len - 2); + // transmit S-Block + ReaderTransmit(data_bytes, len, NULL); + // retrieve the result again + len = ReaderReceive(data, parity); + data_bytes = data; + } + + // if we received an I- or R(ACK)-Block with a block number equal to the + // current block number, toggle the current block number if (len >= 3 // PCB+CRC = 3 bytes && ((data_bytes[0] & 0xC0) == 0 // I-Block || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 8bd80510..8796edf5 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -41,10 +41,10 @@ extern void ReaderMifare(bool first_try); extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); extern int EmSendCmd(uint8_t *resp, uint16_t respLen); -extern int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded); +extern int EmSendCmdEx(uint8_t *resp, uint16_t respLen); extern int EmSend4bit(uint8_t resp); extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); -extern int EmSendPrecompiledCmd(tag_response_info_t *response_info, bool correctionNeeded); +extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 641c02e8..4344742b 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1159,7 +1159,7 @@ void T55xxResetRead(void) { TurnReadLFOn(READ_GAP); // Acquisition - DoPartialAcquisition(0, true, BigBuf_max_traceLen()); + DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1291,7 +1291,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Acquisition // Now do the acquisition - DoPartialAcquisition(0, true, 12000); + DoPartialAcquisition(0, true, 12000, 0); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1690,7 +1690,7 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { SendForward(fwd_bit_count); WaitUS(400); // Now do the acquisition - DoPartialAcquisition(20, true, 6000); + DoPartialAcquisition(20, true, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); @@ -1723,7 +1723,7 @@ void EM4xWriteWord(uint32_t flag, uint32_t Data, uint32_t Pwd) { WaitUS(6500); //Capture response if one exists - DoPartialAcquisition(20, true, 6000); + DoPartialAcquisition(20, true, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_A_OFF(); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 5d1f9248..999f56bb 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -119,7 +119,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) * @param silent - is true, now outputs are made. If false, dbprints the status * @return the number of bits occupied by the samples. */ -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize) +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, int cancel_after) { //. uint8_t *dest = BigBuf_get_addr(); @@ -140,6 +140,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag uint32_t sample_sum =0 ; uint32_t sample_total_numbers =0 ; uint32_t sample_total_saved =0 ; + uint32_t cancel_counter = 0; while(!BUTTON_PRESS() && !usb_poll_validate_length() ) { WDT_HIT(); @@ -151,9 +152,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); // threshold either high or low values 128 = center 0. if trigger = 178 - if ((trigger_threshold > 0) && (sample < (trigger_threshold+128)) && (sample > (128-trigger_threshold))) // + if ((trigger_threshold > 0) && (sample < (trigger_threshold+128)) && (sample > (128-trigger_threshold))) { // + if (cancel_after > 0) cancel_counter++; + if (cancel_after == cancel_counter) break; continue; - + } trigger_threshold = 0; sample_total_numbers++; @@ -213,7 +216,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag */ uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { - return DoAcquisition(1,8,0,trigger_threshold,silent,0); + return DoAcquisition(1,8,0,trigger_threshold,silent,0,0); } uint32_t DoAcquisition_config(bool silent, int sample_size) { @@ -222,11 +225,12 @@ uint32_t DoAcquisition_config(bool silent, int sample_size) ,config.averaging ,config.trigger_threshold ,silent - ,sample_size); + ,sample_size + ,0); } -uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size) { - return DoAcquisition(1,8,0,trigger_threshold,silent,sample_size); +uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, int cancel_after) { + return DoAcquisition(1,8,0,trigger_threshold,silent,sample_size,cancel_after); } uint32_t ReadLF(bool activeField, bool silent, int sample_size) @@ -329,8 +333,8 @@ uint32_t doCotagAcquisitionManchester() { uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint16_t sample_counter = 0, period = 0; uint8_t curr = 0, prev = 0; - - while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) ) { + uint16_t noise_counter = 0; + while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1<<1)) ) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = 0x43; @@ -343,14 +347,20 @@ uint32_t doCotagAcquisitionManchester() { // find first peak if ( !firsthigh ) { - if (sample < COTAG_ONE_THRESHOLD) + if (sample < COTAG_ONE_THRESHOLD) { + noise_counter++; continue; + } + noise_counter = 0; firsthigh = 1; } if ( !firstlow ){ - if (sample > COTAG_ZERO_THRESHOLD ) + if (sample > COTAG_ZERO_THRESHOLD ) { + noise_counter++; continue; + } + noise_counter=0; firstlow = 1; } diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 0531e0c9..ea044f3c 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -21,7 +21,7 @@ uint32_t SampleLF(bool silent, int sample_size); uint32_t SnoopLF(); // adds sample size to default options -uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size); +uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, int cancel_after); /** * @brief Does sample acquisition, ignoring the config values set in the sample_config. diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 91f45efd..1fdf99d6 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -41,6 +41,132 @@ #define cardSTATE_TO_IDLE() { cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); } +#define AC_DATA_READ 0 +#define AC_DATA_WRITE 1 +#define AC_DATA_INC 2 +#define AC_DATA_DEC_TRANS_REST 3 +#define AC_KEYA_READ 0 +#define AC_KEYA_WRITE 1 +#define AC_KEYB_READ 2 +#define AC_KEYB_WRITE 3 +#define AC_AC_READ 4 +#define AC_AC_WRITE 5 + +#define AUTHKEYA 0 +#define AUTHKEYB 1 +#define AUTHKEYNONE 0xff + + +static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { + uint8_t sector_trailer[16]; + emlGetMem(sector_trailer, blockNo, 1); + uint8_t AC = ((sector_trailer[7] >> 5) & 0x04) + | ((sector_trailer[8] >> 2) & 0x02) + | ((sector_trailer[8] >> 7) & 0x01); + switch (action) { + case AC_KEYA_READ: { + return false; + break; + } + case AC_KEYA_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01)) + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + break; + } + case AC_KEYB_READ: { + return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); + break; + } + case AC_KEYB_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04)) + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + break; + } + case AC_AC_READ: { + return ((keytype == AUTHKEYA) + || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); + break; + } + case AC_AC_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x01)) + || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); + break; + } + default: return false; + } +} + + +static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) +{ + uint8_t sector_trailer[16]; + emlGetMem(sector_trailer, SectorTrailer(blockNo), 1); + + uint8_t sector_block; + if (blockNo < 32*4) { + sector_block = blockNo & 0x03; + } else { + sector_block = (blockNo & 0x0f) / 5; + } + + uint8_t AC; + switch (sector_block) { + case 0x00: { + AC = ((sector_trailer[7] >> 2) & 0x04) + | ((sector_trailer[8] << 1) & 0x02) + | ((sector_trailer[8] >> 4) & 0x01); + break; + } + case 0x01: { + AC = ((sector_trailer[7] >> 3) & 0x04) + | ((sector_trailer[8] >> 0) & 0x02) + | ((sector_trailer[8] >> 5) & 0x01); + break; + } + case 0x02: { + AC = ((sector_trailer[7] >> 4) & 0x04) + | ((sector_trailer[8] >> 1) & 0x02) + | ((sector_trailer[8] >> 6) & 0x01); + break; + } + default: + return false; + } + + switch (action) { + case AC_DATA_READ: { + return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07)) + || (keytype == AUTHKEYB && !(AC == 0x07))); + break; + } + case AC_DATA_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x00)) + || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03))); + break; + } + case AC_DATA_INC: { + return ((keytype == AUTHKEYA && (AC == 0x00)) + || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06))); + break; + } + case AC_DATA_DEC_TRANS_REST: { + return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01)) + || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01))); + break; + } + } + + return false; +} + + +static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { + if (IsSectorTrailer(blockNo)) { + return IsTrailerAccessAllowed(blockNo, keytype, action); + } else { + return IsDataAccessAllowed(blockNo, keytype, action); + } +} static void MifareSimInit(uint8_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len) { @@ -155,7 +281,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint32_t cuid = 0; uint8_t cardWRBL = 0; uint8_t cardAUTHSC = 0; - uint8_t cardAUTHKEY = 0xff; // no authentication + uint8_t cardAUTHKEY = AUTHKEYNONE; // no authentication uint32_t cardRr = 0; //uint32_t rn_enc = 0; uint32_t ans = 0; @@ -244,11 +370,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // WUPA in HALTED state or REQA or WUPA in any other state if (receivedCmd_len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { - EmSendPrecompiledCmd(&responses[ATQA], (receivedCmd[0] == ISO14443A_CMD_WUPA)); + EmSendPrecompiledCmd(&responses[ATQA]); // init crypto block crypto1_destroy(pcs); - cardAUTHKEY = 0xff; + cardAUTHKEY = AUTHKEYNONE; if (flags & FLAG_RANDOM_NONCE) { nonce = prand(); } @@ -268,7 +394,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // select all - 0x93 0x20 if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL CL1 received"); - EmSendPrecompiledCmd(&responses[UIDBCC1], false); + EmSendPrecompiledCmd(&responses[UIDBCC1]); break; } // select card - 0x93 0x70 ... @@ -276,12 +402,12 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) { if (MF_DBGLEVEL >= 4) Dbprintf("SELECT CL1 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]); if (uid_len == 4) { - EmSendPrecompiledCmd(&responses[SAKfinal], false); + EmSendPrecompiledCmd(&responses[SAKfinal]); LED_B_ON(); cardSTATE = MFEMUL_WORK; break; } else if (uid_len == 7) { - EmSendPrecompiledCmd(&responses[SAK1], false); + EmSendPrecompiledCmd(&responses[SAK1]); cardSTATE = MFEMUL_SELECT2; break; } @@ -293,7 +419,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // select all cl2 - 0x95 0x20 if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL CL2 received"); - EmSendPrecompiledCmd(&responses[UIDBCC2], false); + EmSendPrecompiledCmd(&responses[UIDBCC2]); break; } // select cl2 card - 0x95 0x70 xxxxxxxxxxxx @@ -301,7 +427,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC2].response, 4) == 0)) { if (uid_len == 7) { if (MF_DBGLEVEL >= 4) Dbprintf("SELECT CL2 %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]); - EmSendPrecompiledCmd(&responses[SAKfinal], false); + EmSendPrecompiledCmd(&responses[SAKfinal]); LED_B_ON(); cardSTATE = MFEMUL_WORK; break; @@ -314,7 +440,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (receivedCmd_len != 4) { // all commands must have exactly 4 bytes break; } - bool encrypted_data = (cardAUTHKEY != 0xFF) ; + bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ; if (encrypted_data) { // decrypt seqence mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); @@ -371,10 +497,24 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } } if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { + uint8_t blockNo = receivedCmd_dec[1]; if (MF_DBGLEVEL >= 4) { - Dbprintf("Reader reading block %d (0x%02x)",receivedCmd_dec[1],receivedCmd_dec[1]); + Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); + } + emlGetMem(response, blockNo, 1); + if (IsSectorTrailer(blockNo)) { + memset(response, 0x00, 6); // keyA can never be read + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { + memset(response+10, 0x00, 6); // keyB cannot be read + } + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) { + memset(response+6, 0x00, 4); // AC bits cannot be read + } + } else { + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) { + memset(response, 0x00, 16); // datablock cannot be read + } } - emlGetMem(response, receivedCmd_dec[1], 1); AppendCrc14443a(response, 16); mf_crypto1_encrypt(pcs, response, 18, response_par); EmSendCmdPar(response, 18, response_par); @@ -386,21 +526,23 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; } if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd_dec[1],receivedCmd_dec[1]); + uint8_t blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", blockNo, blockNo); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - cardWRBL = receivedCmd_dec[1]; + cardWRBL = blockNo; cardSTATE = MFEMUL_WRITEBL2; break; } if (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); - if (emlCheckValBl(receivedCmd_dec[1])) { + uint8_t blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo); + if (emlCheckValBl(blockNo)) { if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - cardWRBL = receivedCmd_dec[1]; + cardWRBL = blockNo; if (receivedCmd_dec[0] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC; if (receivedCmd_dec[0] == MIFARE_CMD_DEC) @@ -410,7 +552,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; } if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd_dec[0],receivedCmd_dec[1],receivedCmd_dec[1]); + uint8_t blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd_dec[0], blockNo, blockNo); if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1])) EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); else @@ -508,20 +651,20 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // test if auth OK if (cardRr != prng_successor(nonce, 64)){ if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x", - cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', + cardAUTHSC, cardAUTHKEY == AUTHKEYA ? 'A' : 'B', cardRr, prng_successor(nonce, 64)); // Shouldn't we respond anything here? // Right now, we don't nack or anything, which causes the // reader to do a WUPA after a while. /Martin // -- which is the correct response. /piwi - cardAUTHKEY = 0xff; // not authenticated + cardAUTHKEY = AUTHKEYNONE; // not authenticated cardSTATE_TO_IDLE(); break; } ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); num_to_bytes(ans, 4, rAUTH_AT); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); - if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED for sector %d with key %c.", cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B'); + if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED for sector %d with key %c.", cardAUTHSC, cardAUTHKEY == AUTHKEYA ? 'A' : 'B'); LED_C_ON(); cardSTATE = MFEMUL_WORK; break; @@ -530,8 +673,24 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (receivedCmd_len == 18) { mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); if (HasValidCRC(receivedCmd_dec, receivedCmd_len)) { + if (IsSectorTrailer(cardWRBL)) { + emlGetMem(response, cardWRBL, 1); + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE)) { + memcpy(receivedCmd_dec, response, 6); // don't change KeyA + } + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYB_WRITE)) { + memcpy(receivedCmd_dec+10, response+10, 6); // don't change KeyA + } + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_AC_WRITE)) { + memcpy(receivedCmd_dec+6, response+6, 4); // don't change AC bits + } + } else { + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_DATA_WRITE)) { + memcpy(receivedCmd_dec, response, 16); // don't change anything + } + } emlSetMem(receivedCmd_dec, cardWRBL, 1); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? cardSTATE = MFEMUL_WORK; break; } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index e5ef6c19..38ca934a 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -9,13 +9,15 @@ // Work with mifare cards. //----------------------------------------------------------------------------- -#include #include "mifareutil.h" + +#include +#include + #include "proxmark3.h" #include "apps.h" #include "util.h" #include "parity.h" - #include "iso14443crc.h" #include "iso14443a.h" #include "crapto1/crapto1.h" @@ -585,6 +587,19 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) } +uint8_t SectorTrailer(uint8_t blockNo) +{ + if (blockNo < 32*4) { + return (blockNo | 0x03); + } else { + return (blockNo | 0x0f); + } +} + +bool IsSectorTrailer(uint8_t blockNo) +{ + return (blockNo == SectorTrailer(blockNo)); +} // work with emulator memory void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 645d0e7d..c34dc8f4 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -12,6 +12,9 @@ #ifndef __MIFAREUTIL_H #define __MIFAREUTIL_H +#include +#include + #include "crapto1/crapto1.h" #include "usb_cdc.h" @@ -75,6 +78,8 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); // Mifare memory structure uint8_t NumBlocksPerSector(uint8_t sectorNo); uint8_t FirstBlockOfSector(uint8_t sectorNo); +bool IsSectorTrailer(uint8_t blockNo); +uint8_t SectorTrailer(uint8_t blockNo); // emulator functions void emlClearMem(void); diff --git a/client/cmdcrc.c b/client/cmdcrc.c index 01f65f55..27d081b9 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -434,9 +434,9 @@ int CmdrevengTestC(const char *Cmd){ char result[30]; int dataLen; char endian = 0; - dataLen = param_getstr(Cmd, cmdp++, inModel); + dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel)); if (dataLen < 4) return 0; - dataLen = param_getstr(Cmd, cmdp++, inHexStr); + dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); if (dataLen < 4) return 0; bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; endian = param_getchar(Cmd, cmdp++); @@ -464,7 +464,7 @@ char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize // takes hex string in and searches for a matching result (hex string must include checksum) int CmdrevengSearch(const char *Cmd){ char inHexStr[50] = {0x00}; - int dataLen = param_getstr(Cmd, 0, inHexStr); + int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); if (dataLen < 4) return 0; char *Models[80]; diff --git a/client/cmdhf.c b/client/cmdhf.c index 30e05990..7a2f3252 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -563,7 +563,7 @@ int CmdHFList(const char *Cmd) bool showWaitCycles = false; bool markCRCBytes = false; char type[40] = {0}; - int tlen = param_getstr(Cmd,0,type); + int tlen = param_getstr(Cmd,0,type, sizeof(type)); char param1 = param_getchar(Cmd, 1); char param2 = param_getchar(Cmd, 2); bool errors = false; diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 24a66b88..4b3975b3 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -132,28 +132,27 @@ int CmdHF14AList(const char *Cmd) int CmdHF14AReader(const char *Cmd) { uint32_t cm = ISO14A_CONNECT; - bool disconnectAfter = false; + bool disconnectAfter = true; int cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) { case 'h': case 'H': - PrintAndLog("Usage: hf 14a reader [d] [3]"); - PrintAndLog(" d drop the signal field after command executed"); + PrintAndLog("Usage: hf 14a reader [k|x] [3]"); + PrintAndLog(" k keep the field active after command executed"); PrintAndLog(" x just drop the signal field"); PrintAndLog(" 3 ISO14443-3 select only (skip RATS)"); return 0; case '3': cm |= ISO14A_NO_RATS; break; - case 'd': - case 'D': - disconnectAfter = true; + case 'k': + case 'K': + disconnectAfter = false; break; case 'x': case 'X': - disconnectAfter = true; cm = cm - ISO14A_CONNECT; break; default: @@ -196,10 +195,15 @@ int CmdHF14AReader(const char *Cmd) { if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len)); } - PrintAndLog("Card is selected. You can now start sending commands"); - } else { + if (!disconnectAfter) { + PrintAndLog("Card is selected. You can now start sending commands"); + } + } + + if (disconnectAfter) { PrintAndLog("Field dropped."); } + return 0; } @@ -1009,7 +1013,7 @@ static command_t CommandTable[] = {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443 Type A UIDs in one go"}, {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443a tag"}, {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"}, - {"apdu", CmdHF14AAPDU, 0, "Send ISO 1443-4 APDU to tag"}, + {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index d02eff8d..60713a01 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -278,7 +278,7 @@ int CmdHFiClassELoad(const char *Cmd) { //File handling and reading FILE *f; char filename[FILE_PATH_SIZE]; - if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) + if(opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) { f = fopen(filename, "rb"); }else{ @@ -384,7 +384,7 @@ int CmdHFiClassDecrypt(const char *Cmd) { //Open the tagdump-file FILE *f; char filename[FILE_PATH_SIZE]; - if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) { + if(opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) { f = fopen(filename, "rb"); if ( f == NULL ) { PrintAndLog("Could not find file %s", filename); @@ -605,7 +605,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { case 'c': case 'C': have_credit_key = true; - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, CreditKEY, dataLen); } else if (dataLen == 1) { @@ -629,7 +629,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { break; case 'f': case 'F': - fileNameLen = param_getstr(Cmd, cmdp+1, filename); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLog("No filename found after f"); errors = true; @@ -639,7 +639,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { case 'k': case 'K': have_debit_key = true; - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { @@ -683,7 +683,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { SendCommand(&c); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLog("Command execute timeout"); - ul_switch_off_field(); + DropField(); return 0; } uint8_t readStatus = resp.arg[0] & 0xff; @@ -691,7 +691,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { if(readStatus == 0){ PrintAndLog("No tag found..."); - ul_switch_off_field(); + DropField(); return 0; } if( readStatus & (FLAG_ICLASS_READER_CSN|FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_CC)){ @@ -702,12 +702,12 @@ int CmdHFiClassReader_Dump(const char *Cmd) { // large memory - not able to dump pages currently if (numblks > maxBlk) numblks = maxBlk; } - ul_switch_off_field(); + DropField(); // authenticate debit key and get div_key - later store in dump block 3 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){ //try twice - for some reason it sometimes fails the first time... if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){ - ul_switch_off_field(); + DropField(); return 0; } } @@ -718,14 +718,14 @@ int CmdHFiClassReader_Dump(const char *Cmd) { SendCommand(&w); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLog("Command execute time-out 1"); - ul_switch_off_field(); + DropField(); return 1; } uint32_t blocksRead = resp.arg[1]; uint8_t isOK = resp.arg[0] & 0xff; if (!isOK && !blocksRead) { PrintAndLog("Read Block Failed"); - ul_switch_off_field(); + DropField(); return 0; } uint32_t startindex = resp.arg[2]; @@ -741,13 +741,13 @@ int CmdHFiClassReader_Dump(const char *Cmd) { // try AA2 if (have_credit_key) { //turn off hf field before authenticating with different key - ul_switch_off_field(); + DropField(); memset(MAC,0,4); // AA2 authenticate credit key and git c_div_key - later store in dump block 4 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){ //try twice - for some reason it sometimes fails the first time... if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){ - ul_switch_off_field(); + DropField(); return 0; } } @@ -760,14 +760,14 @@ int CmdHFiClassReader_Dump(const char *Cmd) { SendCommand(&w); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { PrintAndLog("Command execute timeout 2"); - ul_switch_off_field(); + DropField(); return 0; } uint8_t isOK = resp.arg[0] & 0xff; blocksRead = resp.arg[1]; if (!isOK && !blocksRead) { PrintAndLog("Read Block Failed 2"); - ul_switch_off_field(); + DropField(); return 0; } @@ -782,7 +782,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { gotBytes += blocksRead*8; } else { //field is still on - turn it off... - ul_switch_off_field(); + DropField(); } } @@ -898,7 +898,7 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { break; case 'k': case 'K': - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { @@ -930,7 +930,7 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { if (cmdp < 6) return usage_hf_iclass_writeblock(); int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true); - ul_switch_off_field(); + DropField(); return ans; } @@ -992,7 +992,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { break; case 'f': case 'F': - fileNameLen = param_getstr(Cmd, cmdp+1, filename); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLog("No filename found after f"); errors = true; @@ -1001,7 +1001,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { break; case 'k': case 'K': - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { @@ -1196,7 +1196,7 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { case 'k': case 'K': auth = true; - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { @@ -1253,7 +1253,7 @@ int CmdHFiClass_loclass(const char *Cmd) { char fileName[255] = {0}; if(opt == 'f') { - if(param_getstr(Cmd, 1, fileName) > 0) + if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0) { return bruteforceFileNoKeys(fileName); }else @@ -1318,14 +1318,14 @@ int CmdHFiClassReadTagFile(const char *Cmd) { char tempnum[5]; FILE *f; char filename[FILE_PATH_SIZE]; - if (param_getstr(Cmd, 0, filename) < 1) + if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1) return usage_hf_iclass_readtagfile(); - if (param_getstr(Cmd,1,(char *)&tempnum) < 1) + if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1) startblock = 0; else sscanf(tempnum,"%d",&startblock); - if (param_getstr(Cmd,2,(char *)&tempnum) < 1) + if (param_getstr(Cmd,2, tempnum, sizeof(tempnum)) < 1) endblock = 0; else sscanf(tempnum,"%d",&endblock); @@ -1458,7 +1458,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { return usage_hf_iclass_calc_newkey(); case 'e': case 'E': - dataLen = param_getstr(Cmd, cmdp, tempStr); + dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr)); if (dataLen==2) oldElite = true; elite = true; @@ -1466,7 +1466,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { break; case 'n': case 'N': - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, NEWKEY, dataLen); } else if (dataLen == 1) { @@ -1485,7 +1485,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { break; case 'o': case 'O': - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, OLDKEY, dataLen); } else if (dataLen == 1) { @@ -1626,7 +1626,7 @@ int CmdHFiClassManageKeys(const char *Cmd) { return usage_hf_iclass_managekeys(); case 'f': case 'F': - fileNameLen = param_getstr(Cmd, cmdp+1, filename); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLog("No filename found after f"); errors = true; @@ -1645,7 +1645,7 @@ int CmdHFiClassManageKeys(const char *Cmd) { case 'k': case 'K': operation += 3; //set key - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { //ul-c or ev1/ntag key length errors = param_gethex(tempStr, 0, KEY, dataLen); } else { diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 553803c1..83060b01 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -533,7 +533,7 @@ static void parseParamTDS(const char *Cmd, const uint8_t indx, bool *paramT, boo char ctmp3[3] = {0}; int len = param_getlength(Cmd, indx); if (len > 0 && len < 4){ - param_getstr(Cmd, indx, ctmp3); + param_getstr(Cmd, indx, ctmp3, sizeof(ctmp3)); *paramT |= (ctmp3[0] == 't' || ctmp3[0] == 'T'); *paramD |= (ctmp3[0] == 'd' || ctmp3[0] == 'D'); @@ -1043,7 +1043,7 @@ int CmdHF14AMfChk(const char *Cmd) // double parameters - ts, ds int clen = param_getlength(Cmd, 2); if (clen == 2 || clen == 3){ - param_getstr(Cmd, 2, ctmp3); + param_getstr(Cmd, 2, ctmp3, sizeof(ctmp3)); ctmp = ctmp3[1]; } //parse @@ -1075,7 +1075,7 @@ int CmdHF14AMfChk(const char *Cmd) keycnt++; } else { // May be a dic file - if ( param_getstr(Cmd, 2 + i,filename) >= FILE_PATH_SIZE ) { + if ( param_getstr(Cmd, 2 + i, filename, sizeof(filename)) >= FILE_PATH_SIZE ) { PrintAndLog("File name too long"); free(keyBlock); return 2; @@ -1398,7 +1398,7 @@ int CmdHF14AMf1kSim(const char *Cmd) { break; case 'f': case 'F': - len = param_getstr(Cmd, cmdp+1, filename); + len = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (len < 1) { PrintAndLog("error no filename found"); return 0; @@ -1674,7 +1674,7 @@ int CmdHF14AMfELoad(const char *Cmd) } } - len = param_getstr(Cmd,nameParamNo,filename); + len = param_getstr(Cmd,nameParamNo,filename,sizeof(filename)); if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; @@ -1773,7 +1773,7 @@ int CmdHF14AMfESave(const char *Cmd) } } - len = param_getstr(Cmd,nameParamNo,filename); + len = param_getstr(Cmd,nameParamNo,filename,sizeof(filename)); if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; @@ -2137,7 +2137,7 @@ int CmdHF14AMfCLoad(const char *Cmd) } return 0; } else { - param_getstr(Cmd, 0, filename); + param_getstr(Cmd, 0, filename, sizeof(filename)); len = strlen(filename); if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; @@ -2348,7 +2348,7 @@ int CmdHF14AMfCSave(const char *Cmd) { } return 0; } else { - param_getstr(Cmd, 0, filename); + param_getstr(Cmd, 0, filename, sizeof(filename)); len = strlen(filename); if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index c95fa20b..63c41728 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -153,7 +153,7 @@ static int ul_select( iso14a_card_select_t *card ){ ans = WaitForResponseTimeout(CMD_ACK, &resp, 1500); if (!ans || resp.arg[0] < 1) { PrintAndLog("iso14443a card select failed"); - ul_switch_off_field(); + DropField(); return 0; } @@ -226,7 +226,7 @@ static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool if (hasAuthKey) { if (ulev1_requestAuthentication(authenticationkey, pack, packSize) < 1) { - ul_switch_off_field(); + DropField(); PrintAndLog("Error: Authentication Failed UL-EV1/NTAG"); return 0; } @@ -550,7 +550,7 @@ static int ulc_magic_test(){ } else { returnValue = UL; } - ul_switch_off_field(); + DropField(); return returnValue; } */ @@ -563,7 +563,7 @@ static int ul_magic_test(){ if ( !ul_select(&card) ) return UL_ERROR; int status = ul_comp_write(0, NULL, 0); - ul_switch_off_field(); + DropField(); if ( status == 0 ) return MAGIC; return 0; @@ -582,14 +582,14 @@ uint32_t GetHF14AMfU_Type(void){ // Ultralight - ATQA / SAK if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { PrintAndLog("Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); - ul_switch_off_field(); + DropField(); return UL_ERROR; } if ( card.uid[0] != 0x05) { len = ulev1_getVersion(version, sizeof(version)); - ul_switch_off_field(); + DropField(); switch (len) { case 0x0A: { @@ -629,7 +629,7 @@ uint32_t GetHF14AMfU_Type(void){ // do UL_C check first... uint8_t nonce[11] = {0x00}; status = ulc_requestAuthentication(nonce, sizeof(nonce)); - ul_switch_off_field(); + DropField(); if (status > 1) { tagtype = UL_C; } else { @@ -650,15 +650,15 @@ uint32_t GetHF14AMfU_Type(void){ tagtype = UNKNOWN; } } - ul_switch_off_field(); + DropField(); } } if (tagtype & UL) { tagtype = ul_fudan_check(); - ul_switch_off_field(); + DropField(); } } else { - ul_switch_off_field(); + DropField(); // Infinition MY-D tests Exam high nibble uint8_t nib = (card.uid[1] & 0xf0) >> 4; switch ( nib ){ @@ -703,7 +703,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ return usage_hf_mfu_info(); case 'k': case 'K': - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length errors = param_gethex(tempStr, 0, authenticationkey, dataLen); dataLen /= 2; // handled as bytes from now on @@ -745,7 +745,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ // read pages 0,1,2,3 (should read 4pages) status = ul_read(0, data, sizeof(data)); if ( status == -1 ) { - ul_switch_off_field(); + DropField(); PrintAndLog("Error: tag didn't answer to READ"); return status; } else if (status == 16) { @@ -763,7 +763,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(0x28, ulc_conf, sizeof(ulc_conf)); if ( status == -1 ){ PrintAndLog("Error: tag didn't answer to READ UL-C"); - ul_switch_off_field(); + DropField(); return status; } if (status == 16) ulc_print_configuration(ulc_conf); @@ -774,14 +774,14 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t ulc_deskey[16] = {0x00}; status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey)); if ( status == -1 ) { - ul_switch_off_field(); + DropField(); PrintAndLog("Error: tag didn't answer to READ magic"); return status; } if (status == 16) ulc_print_3deskey(ulc_deskey); } else { - ul_switch_off_field(); + DropField(); // if we called info with key, just return if ( hasAuthKey ) return 1; @@ -816,7 +816,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature)); if ( status == -1 ) { PrintAndLog("Error: tag didn't answer to READ SIGNATURE"); - ul_switch_off_field(); + DropField(); return status; } if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature)); @@ -831,7 +831,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ulev1_getVersion(version, sizeof(version)); if ( status == -1 ) { PrintAndLog("Error: tag didn't answer to GETVERSION"); - ul_switch_off_field(); + DropField(); return status; } else if (status == 10) { ulev1_print_version(version); @@ -851,7 +851,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); if ( status == -1 ) { PrintAndLog("Error: tag didn't answer to READ EV1"); - ul_switch_off_field(); + DropField(); return status; } else if (status == 16) { // save AUTHENTICATION LIMITS for later: @@ -881,7 +881,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } } - ul_switch_off_field(); + DropField(); if (locked) PrintAndLog("\nTag appears to be locked, try using the key to get more info"); PrintAndLog(""); return 1; @@ -1238,7 +1238,7 @@ int CmdHF14AMfUDump(const char *Cmd){ return usage_hf_mfu_dump(); case 'k': case 'K': - dataLen = param_getstr(Cmd, cmdp+1, tempStr); + dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length errors = param_gethex(tempStr, 0, authenticationkey, dataLen); dataLen /= 2; @@ -1256,7 +1256,7 @@ int CmdHF14AMfUDump(const char *Cmd){ break; case 'n': case 'N': - fileNlen = param_getstr(Cmd, cmdp+1, filename); + fileNlen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (!fileNlen) errors = true; if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; cmdp += 2; diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index a5e9f95c..43e71d96 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -16,7 +16,6 @@ int CmdHF14AMfUInfo(const char *Cmd); uint32_t GetHF14AMfU_Type(void); int ul_print_type(uint32_t tagtype, uint8_t spacer); -#define ul_switch_off_field DropField int usage_hf_mfu_dump(void); int usage_hf_mfu_info(void); diff --git a/client/cmdlf.c b/client/cmdlf.c index eb664a11..ef9c3cbb 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -93,7 +93,7 @@ int CmdLFCommandRead(const char *Cmd) cmdp++; break; case 'c': - param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes); + param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes, sizeof(c.d.asBytes)); cmdp+=2; break; case 'd': @@ -491,7 +491,7 @@ int CmdLFfskSim(const char *Cmd) uint8_t fcHigh=0, fcLow=0, clk=0; uint8_t invert=0; bool errors = false; - char hexData[32] = {0x00}; // store entered hex data + char hexData[64] = {0x00}; // store entered hex data uint8_t data[255] = {0x00}; int dataLen = 0; uint8_t cmdp = 0; @@ -522,7 +522,7 @@ int CmdLFfskSim(const char *Cmd) // cmdp++; // break; case 'd': - dataLen = param_getstr(Cmd, cmdp+1, hexData); + dataLen = param_getstr(Cmd, cmdp+1, hexData, sizeof(hexData)); if (dataLen==0) { errors=true; } else { @@ -593,7 +593,7 @@ int CmdLFaskSim(const char *Cmd) uint8_t encoding = 1, separator = 0; uint8_t clk=0, invert=0; bool errors = false; - char hexData[32] = {0x00}; + char hexData[64] = {0x00}; uint8_t data[255]= {0x00}; // store entered hex data int dataLen = 0; uint8_t cmdp = 0; @@ -628,7 +628,7 @@ int CmdLFaskSim(const char *Cmd) cmdp++; break; case 'd': - dataLen = param_getstr(Cmd, cmdp+1, hexData); + dataLen = param_getstr(Cmd, cmdp+1, hexData, sizeof(hexData)); if (dataLen==0) { errors=true; } else { @@ -687,7 +687,7 @@ int CmdLFpskSim(const char *Cmd) uint8_t carrier=0, clk=0; uint8_t invert=0; bool errors = false; - char hexData[32] = {0x00}; // store entered hex data + char hexData[64] = {0x00}; // store entered hex data uint8_t data[255] = {0x00}; int dataLen = 0; uint8_t cmdp = 0; @@ -723,7 +723,7 @@ int CmdLFpskSim(const char *Cmd) cmdp++; break; case 'd': - dataLen = param_getstr(Cmd, cmdp+1, hexData); + dataLen = param_getstr(Cmd, cmdp+1, hexData, sizeof(hexData)); if (dataLen==0) { errors=true; } else { @@ -945,7 +945,7 @@ int CmdLFfind(const char *Cmd) PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nUse lf em 4x05readword/dump commands to read\n"); return 1; } - ans=CmdLFHitagReader("26"); + ans=CmdLFHitagReader("26"); // 26 = RHT2F_UID_ONLY if (ans==0) { return 1; } diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index f5dfee35..6d562be0 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -335,7 +335,7 @@ int CmdEM410xBrute(const char *Cmd) delay = param_get32ex(Cmd, 4, 1000, 10); } - param_getstr(Cmd, 0, filename); + param_getstr(Cmd, 0, filename, sizeof(filename)); uidBlock = calloc(stUidBlock, 5); if (uidBlock == NULL) return 1; @@ -950,7 +950,6 @@ int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *wordDa } int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000; if (graphJustNoise(GraphBuffer, testLen)) { - PrintAndLog("no tag not found"); return -1; } //attempt demod: diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 103f2b77..73c02a14 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -239,6 +239,7 @@ int CmdLFHitagReader(const char *Cmd) { c.arg[0] = htf; // Send the command to the proxmark + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 29fc81f2..2f4bacfe 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -71,7 +71,7 @@ int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode case 'D': case 'd': //param get string int param_getstr(const char *line, int paramnum, char * str) - stringlen = param_getstr(Cmd, cmdp+1, id); + stringlen = param_getstr(Cmd, cmdp+1, id, sizeof(id)); if (stringlen < 2) return -1; cmdp+=2; break; diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 252aaaa2..92a00bce 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -236,7 +236,7 @@ int CmdT55xxSetConfig(const char *Cmd) { cmdp+=2; break; case 'd': - param_getstr(Cmd, cmdp+1, modulation); + param_getstr(Cmd, cmdp+1, modulation, sizeof(modulation)); cmdp += 2; if ( strcmp(modulation, "FSK" ) == 0) { diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c index fbdd714a..ec7a64a1 100644 --- a/client/emv/apduinfo.c +++ b/client/emv/apduinfo.c @@ -278,13 +278,13 @@ int CodeCmp(const char *code1, const char *code2) { } const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) { - char buf[4] = {0}; + char buf[5] = {0}; int res; int mineq = 100; int mineqindx = 0; - sprintf(&buf[0], "%02X ", sw1); - sprintf(&buf[2], "%02X ", sw2); + sprintf(&buf[0], "%02X", sw1); + sprintf(&buf[2], "%02X", sw2); for (int i = 0; i < APDUCodeTableLen; i++) { res = CodeCmp(APDUCodeTable[i].ID, buf); diff --git a/client/emv/dump.c b/client/emv/dump.c index c3934b3d..8b3fb708 100644 --- a/client/emv/dump.c +++ b/client/emv/dump.c @@ -18,8 +18,12 @@ #endif #include "dump.h" +#include -void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) { +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");} + +void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) +{ int i; if (!f) @@ -29,7 +33,8 @@ void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) { fprintf(f, "%s%02hhX", i ? " " : "", ptr[i]); } -void dump_buffer_tab(const unsigned char *ptr, size_t len, FILE *f, int tabs) { +void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level) +{ int i, j; char buf[64] = {0}; memset(buf, ' ', tabs > 64 ? 64 : tabs); @@ -38,7 +43,8 @@ void dump_buffer_tab(const unsigned char *ptr, size_t len, FILE *f, int tabs) { f = stdout; for (i = 0; i < len; i += 16) { - fprintf(f, "%s%02x:", buf, i); + PRINT_INDENT(level); + fprintf(f, "\t%02x:", i); for (j = 0; j < 16; j++) { if (i + j < len) fprintf(f, " %02hhx", ptr[i + j]); diff --git a/client/emv/dump.h b/client/emv/dump.h index 035c6d0d..a981615a 100644 --- a/client/emv/dump.h +++ b/client/emv/dump.h @@ -17,10 +17,10 @@ #define DUMP_H #include -#include +#include void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f); -void dump_buffer(const unsigned char *ptr, size_t len, FILE *f); +void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level); void dump_buffer_tab(const unsigned char *ptr, size_t len, FILE *f, int tabs); #endif diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 52236371..3eafb465 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -22,6 +22,8 @@ #include +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");} + enum emv_tag_t { EMV_TAG_GENERIC, EMV_TAG_BITMASK, @@ -272,16 +274,18 @@ static const char *bitstrings[] = { "1.......", }; -static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { const struct emv_tag_bit *bits = tag->data; unsigned bit, byte; for (byte = 1; byte <= tlv->len; byte ++) { unsigned char val = tlv->value[byte - 1]; + PRINT_INDENT(level); fprintf(f, "\tByte %u (%02x)\n", byte, val); for (bit = 8; bit > 0; bit--, val <<= 1) { if (val & 0x80) + PRINT_INDENT(level); fprintf(f, "\t\t%s - '%s'\n", bitstrings[bit - 1], bits->bit == EMV_BIT(byte, bit) ? bits->name : "Unknown"); if (bits->bit == EMV_BIT(byte, bit)) @@ -290,7 +294,7 @@ static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *ta } } -static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { const unsigned char *buf = tlv->value; size_t left = tlv->len; @@ -300,20 +304,24 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F const struct emv_tag *doltag; if (!tlv_parse_tl(&buf, &left, &doltlv)) { + PRINT_INDENT(level); fprintf(f, "Invalid Tag-Len\n"); continue; } doltag = emv_get_tag(&doltlv); + PRINT_INDENT(level); fprintf(f, "\tTag %4hx len %02zx ('%s')\n", doltlv.tag, doltlv.len, doltag->name); } } -static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); fprintf(f, "\tString value '"); fwrite(tlv->value, 1, tlv->len, f); + PRINT_INDENT(level); fprintf(f, "'\n"); } @@ -348,13 +356,15 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un return ret; } -static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); fprintf(f, "\tNumeric value %lu\n", emv_value_numeric(tlv, 0, tlv->len * 2)); } -static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); fprintf(f, "\tDate: 20%02ld.%ld.%ld\n", emv_value_numeric(tlv, 0, 2), emv_value_numeric(tlv, 2, 4), @@ -366,12 +376,13 @@ static uint32_t emv_get_binary(const unsigned char *S) return (S[0] << 24) | (S[1] << 16) | (S[2] << 8) | (S[3] << 0); } -static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f) +static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { uint32_t X, Y; int i; if (tlv->len < 10 || tlv->len % 2) { + PRINT_INDENT(level); fprintf(f, "\tINVALID!\n"); return; } @@ -379,7 +390,9 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t X = emv_get_binary(tlv->value); Y = emv_get_binary(tlv->value + 4); + PRINT_INDENT(level); fprintf(f, "\tX: %d\n", X); + PRINT_INDENT(level); fprintf(f, "\tY: %d\n", Y); for (i = 8; i < tlv->len; i+= 2) { @@ -455,6 +468,7 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t break; } + PRINT_INDENT(level); fprintf(f, "\t%02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful\n", tlv->value[i], tlv->value[i+1], method, condition, (tlv->value[i] & 0x40) ? "continue" : "fail"); @@ -472,7 +486,7 @@ static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, F } } -bool emv_tag_dump(const struct tlv *tlv, FILE *f) +bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) { if (!tlv) { fprintf(f, "NULL\n"); @@ -481,36 +495,34 @@ bool emv_tag_dump(const struct tlv *tlv, FILE *f) const struct emv_tag *tag = emv_get_tag(tlv); - fprintf(f, "%2hx[%02zx] %s: ", tlv->tag, tlv->len, tag->name); + PRINT_INDENT(level); + fprintf(f, "--%2hx[%02zx] '%s':\n", tlv->tag, tlv->len, tag->name); switch (tag->type) { case EMV_TAG_GENERIC: fprintf(f, "\n"); break; case EMV_TAG_BITMASK: - fprintf(f, "\n"); - emv_tag_dump_bitmask(tlv, tag, f); + emv_tag_dump_bitmask(tlv, tag, f, level); break; case EMV_TAG_DOL: - fprintf(f, "\n"); - emv_tag_dump_dol(tlv, tag, f); + emv_tag_dump_dol(tlv, tag, f, level); break; case EMV_TAG_CVM_LIST: - fprintf(f, "\n"); - emv_tag_dump_cvm_list(tlv, tag, f); + emv_tag_dump_cvm_list(tlv, tag, f, level); break; case EMV_TAG_AFL: fprintf(f, "\n"); emv_tag_dump_afl(tlv, tag, f); break; case EMV_TAG_STRING: - emv_tag_dump_string(tlv, tag, f); + emv_tag_dump_string(tlv, tag, f, level); break; case EMV_TAG_NUMERIC: - emv_tag_dump_numeric(tlv, tag, f); + emv_tag_dump_numeric(tlv, tag, f, level); break; case EMV_TAG_YYMMDD: - emv_tag_dump_yymmdd(tlv, tag, f); + emv_tag_dump_yymmdd(tlv, tag, f, level); break; }; diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index de6d9d1e..8dbd9e00 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -19,6 +19,6 @@ #include "tlv.h" #include -bool emv_tag_dump(const struct tlv *tlv, FILE *f); +bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level); #endif diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 9260605c..21be93ef 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -81,14 +81,11 @@ void SetAPDULogging(bool logging) { APDULogging = logging; } -static bool print_cb(void *data, const struct tlv *tlv, int lvl, bool haveChild) { - char buf[64] = {0}; - memset(buf, '-', lvl > 32 ? 64 : lvl * 2); - printf("%s", buf); - - emv_tag_dump(tlv, stdout); - if (!haveChild) - dump_buffer_tab(tlv->value, tlv->len, stdout, lvl * 2 + 2); +static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) { + emv_tag_dump(tlv, stdout, level); + if (is_leaf) { + dump_buffer(tlv->value, tlv->len, stdout, level); + } return true; } @@ -99,7 +96,7 @@ void TLVPrintFromBuffer(uint8_t *data, int datalen) { if (t) { PrintAndLog("-------------------- TLV decoded --------------------"); - tlvdb_visit(t, print_cb, NULL); + tlvdb_visit(t, print_cb, NULL, 0); tlvdb_free(t); } else { PrintAndLog("TLV ERROR: Can't parse response as TLV tree."); diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 093b860a..f6d435dd 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -342,7 +342,8 @@ void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) tlvdb->next = other; } -void tlvdb_visit_ex(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int lvl) { +void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level) +{ struct tlvdb *next = NULL; lvl++; @@ -351,8 +352,8 @@ void tlvdb_visit_ex(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int lvl) { for (; tlvdb; tlvdb = next) { next = tlvdb->next; - cb(data, &tlvdb->tag, lvl, (tlvdb->children != NULL)); - tlvdb_visit_ex(tlvdb->children, cb, data, lvl); + cb(data, &tlvdb->tag, level, (tlvdb->children == NULL)); + tlvdb_visit(tlvdb->children, cb, data, level+1); } } diff --git a/client/emv/tlv.h b/client/emv/tlv.h index 9709d961..5b8b6825 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -31,7 +31,7 @@ struct tlv { }; struct tlvdb; -typedef bool (*tlv_cb)(void *data, const struct tlv *tlv, int lvl, bool haveChild); +typedef bool (*tlv_cb)(void *data, const struct tlv *tlv, int level, bool is_leaf); struct tlvdb *tlvdb_fixed(tlv_tag_t tag, size_t len, const unsigned char *value); struct tlvdb *tlvdb_external(tlv_tag_t tag, size_t len, const unsigned char *value); @@ -45,7 +45,7 @@ struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]); void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other); -void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data); +void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level); const struct tlv *tlvdb_get(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev); const struct tlv *tlvdb_get_inchild(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev); diff --git a/client/util.c b/client/util.c index 72b15fcb..458100a7 100644 --- a/client/util.c +++ b/client/util.c @@ -564,11 +564,19 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd return 0; } -int param_getstr(const char *line, int paramnum, char * str) +int param_getstr(const char *line, int paramnum, char * str, size_t buffersize) { int bg, en; - if (param_getptr(line, &bg, &en, paramnum)) return 0; + if (param_getptr(line, &bg, &en, paramnum)) { + return 0; + } + + // Prevent out of bounds errors + if (en - bg + 1 >= buffersize) { + printf("out of bounds error: want %lu bytes have %lu bytes\n", en - bg + 1 + 1, buffersize); + return 0; + } memcpy(str, line + bg, en - bg + 1); str[en - bg + 1] = 0; @@ -586,6 +594,7 @@ https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/ int hextobinarray(char *target, char *source) { int length, i, count= 0; + char* start = source; char x; length = strlen(source); @@ -601,8 +610,10 @@ int hextobinarray(char *target, char *source) x -= '0'; else if (x >= 'A' && x <= 'F') x -= 'A' - 10; - else + else { + printf("Discovered unknown character %c %d at idx %d of %s\n", x, x, source - start, start); return 0; + } // output for(i= 0 ; i < 4 ; ++i, ++count) *(target++)= (x >> (3 - i)) & 1; diff --git a/client/util.h b/client/util.h index 5d5cafb4..e9c48b03 100644 --- a/client/util.h +++ b/client/util.h @@ -67,7 +67,7 @@ extern uint8_t param_isdec(const char *line, int paramnum); extern int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt); extern int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt); extern int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxdatalen, int *datalen); -extern int param_getstr(const char *line, int paramnum, char * str); +extern int param_getstr(const char *line, int paramnum, char * str, size_t buffersize); extern int hextobinarray( char *target, char *source); extern int hextobinstring( char *target, char *source); diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index bd8cf8e7..229151df 100644 Binary files a/fpga/fpga_hf.bit and b/fpga/fpga_hf.bit differ diff --git a/fpga/hi_iso14443a.v b/fpga/hi_iso14443a.v index ccb51d8f..b1b7b141 100644 --- a/fpga/hi_iso14443a.v +++ b/fpga/hi_iso14443a.v @@ -311,9 +311,13 @@ reg [3:0] sub_carrier_cnt; // The ARM must not send too early, otherwise the mod_sig_buf will overflow, therefore signal that we are ready // with fdt_indicator. The mod_sig_buf can buffer 29 excess data bits, i.e. a maximum delay of 29 * 16 = 464 adc_clk ticks. -// fdt_indicator could appear at ssp_din after 1 tick, the transfer needs 16 ticks, the ARM can send 128 ticks later. -// 1128 - 464 - 1 - 128 - 8 = 535 -`define FDT_INDICATOR_COUNT 11'd535 +// fdt_indicator is assigned to sendbit after at least 1 tick, the transfer to ARM needs minimum 8 ticks. Response from +// ARM could appear at ssp_dout 8 ticks later. +// 1128 - 464 - 1 - 8 - 8 = 647 +`define FDT_INDICATOR_COUNT 11'd647 +// Note: worst case, assignment to sendbit takes 15 ticks more, and transfer to ARM needs 7*16 = 112 ticks more. +// When the ARM's response then appears, the fdt_count is already 647 + 15 + 112 = 774, which still allows the ARM a possible +// response window of 1128 - 774 = 354 ticks. // reset on a pause in listen mode. I.e. the counter starts when the pause is over: assign fdt_reset = ~after_hysteresis && mod_type == `TAGSIM_LISTEN;