mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-22 06:13:27 -07:00
merge master
This commit is contained in:
commit
2acff2ef06
33 changed files with 514 additions and 248 deletions
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -239,6 +239,7 @@ int CmdLFHitagReader(const char *Cmd) {
|
|||
c.arg[0] = htf;
|
||||
|
||||
// Send the command to the proxmark
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue