merge master

This commit is contained in:
merlokk 2017-11-13 12:54:04 +02:00
commit 2acff2ef06
33 changed files with 514 additions and 248 deletions

View file

@ -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,27 +1368,27 @@ 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
@ -1408,7 +1407,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
// 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) {

View file

@ -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,11 +1424,22 @@ 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

View file

@ -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);

View file

@ -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();

View file

@ -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;
}

View file

@ -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.

View file

@ -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;
}

View file

@ -9,13 +9,15 @@
// Work with mifare cards.
//-----------------------------------------------------------------------------
#include <string.h>
#include "mifareutil.h"
#include <string.h>
#include <stdbool.h>
#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) {

View file

@ -12,6 +12,9 @@
#ifndef __MIFAREUTIL_H
#define __MIFAREUTIL_H
#include <stdint.h>
#include <stdbool.h>
#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);

View file

@ -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];

View file

@ -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;

View file

@ -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, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
{"sim", CmdHF14ASim, 0, "<UID> -- 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}
};

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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:

View file

@ -239,6 +239,7 @@ int CmdLFHitagReader(const char *Cmd) {
c.arg[0] = htf;
// Send the command to the proxmark
clearCommandBuffer();
SendCommand(&c);
UsbCommand resp;

View file

@ -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;

View file

@ -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) {

View file

@ -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);

View file

@ -18,8 +18,12 @@
#endif
#include "dump.h"
#include <stdio.h>
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]);

View file

@ -17,10 +17,10 @@
#define DUMP_H
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
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

View file

@ -22,6 +22,8 @@
#include <stdlib.h>
#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;
};

View file

@ -19,6 +19,6 @@
#include "tlv.h"
#include <stdio.h>
bool emv_tag_dump(const struct tlv *tlv, FILE *f);
bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level);
#endif

View file

@ -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.");

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

Binary file not shown.

View file

@ -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;