Merge branch 'master' into bl

Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
Iceman 2025-05-28 18:10:16 +02:00 committed by GitHub
commit 490c211361
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 601 additions and 195 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Changed `hf iclass info` - now uses CSN values based checks (@antiklesys)
- Changed `hf iclass dump` - now uses default AA1 key when called without a key or key index (@iceman1001)
- Renamed `hf iclass trbl` to `hf iclass tear` (@iceman1001)
- Changed `hw tearoff` - the device side message is now debug log controlled (@iceman1001)

View file

@ -121,7 +121,7 @@ void BigBuf_Clear_ext(bool verbose) {
memset(BigBuf, 0, s_bigbuf_size);
clear_trace();
if (verbose) {
Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
if (g_dbglevel >= DBG_ERROR) Dbprintf("Buffer cleared (%i bytes)", s_bigbuf_size);
}
}

View file

@ -99,6 +99,7 @@ int tearoff_hook(void) {
if (g_tearoff_enabled) {
if (g_tearoff_delay_us == 0) {
Dbprintf(_RED_("No tear-off delay configured!"));
g_tearoff_enabled = false;
return PM3_SUCCESS; // SUCCESS = the hook didn't do anything
}
SpinDelayUsPrecision(g_tearoff_delay_us);
@ -254,7 +255,7 @@ static uint32_t MeasureAntennaTuningLfData(void) {
void print_stack_usage(void) {
for (uint32_t *p = _stack_start; ; ++p) {
if (*p != 0xdeadbeef) {
Dbprintf(" Max stack usage......... %d / %d bytes", (uint32_t)_stack_end - (uint32_t)p, (uint32_t)_stack_end - (uint32_t)_stack_start);
Dbprintf(" Max stack usage..... %d / %d bytes", (uint32_t)_stack_end - (uint32_t)p, (uint32_t)_stack_end - (uint32_t)_stack_start);
break;
}
}
@ -365,7 +366,7 @@ static void print_debug_level(void) {
sprintf(dbglvlstr, "extended");
break;
}
Dbprintf(" Debug log level......... %d ( " _YELLOW_("%s")" )", g_dbglevel, dbglvlstr);
Dbprintf(" Debug log level..... %d ( " _YELLOW_("%s")" )", g_dbglevel, dbglvlstr);
}
// measure the Connection Speed by sending SpeedTestBufferSize bytes to client and measuring the elapsed time.
@ -421,11 +422,11 @@ static void SendStatus(uint32_t wait) {
print_debug_level();
tosend_t *ts = get_tosend();
Dbprintf(" ToSendMax............... %d", ts->max);
Dbprintf(" ToSend BUFFERSIZE....... %d", TOSEND_BUFFER_SIZE);
Dbprintf(" ToSendMax........... %d", ts->max);
Dbprintf(" ToSend BUFFERSIZE... %d", TOSEND_BUFFER_SIZE);
while ((AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINRDY) == 0); // Wait for MAINF value to become available...
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & AT91C_CKGR_MAINF; // Get # main clocks within 16 slow clocks
Dbprintf(" Slow clock.............. %d Hz", (16 * MAINCK) / mainf);
Dbprintf(" Slow clock.......... %d Hz", (16 * MAINCK) / mainf);
uint32_t delta_time = 0;
uint32_t start_time = GetTickCount();
#define SLCK_CHECK_MS 50
@ -449,10 +450,11 @@ static void SendStatus(uint32_t wait) {
} else {
num = 0;
}
if (num > 0) {
Dbprintf(" Mifare.................. "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, MF_KEYS_FILE);
Dbprintf(" Mifare... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, MF_KEYS_FILE);
} else {
Dbprintf(" Mifare.................. "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, MF_KEYS_FILE);
Dbprintf(" Mifare... "_RED_("%u")" keys - "_RED_("%s"), num, MF_KEYS_FILE);
}
if (exists_in_spiffs(T55XX_KEYS_FILE)) {
@ -460,10 +462,11 @@ static void SendStatus(uint32_t wait) {
} else {
num = 0;
}
if (num > 0) {
Dbprintf(" T55xx................... "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, T55XX_KEYS_FILE);
Dbprintf(" T55xx.... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, T55XX_KEYS_FILE);
} else {
Dbprintf(" T55xx................... "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, T55XX_KEYS_FILE);
Dbprintf(" T55xx.... "_RED_("%u")" keys - "_RED_("%s"), num, T55XX_KEYS_FILE);
}
if (exists_in_spiffs(ICLASS_KEYS_FILE)) {
@ -471,10 +474,11 @@ static void SendStatus(uint32_t wait) {
} else {
num = 0;
}
if (num > 0) {
Dbprintf(" iClass.................. "_YELLOW_("%u")" keys (spiffs: "_GREEN_("%s")")", num, ICLASS_KEYS_FILE);
Dbprintf(" iClass... "_YELLOW_("%u")" keys - "_GREEN_("%s"), num, ICLASS_KEYS_FILE);
} else {
Dbprintf(" iClass.................. "_RED_("%u")" keys (spiffs: "_RED_("%s")")", num, ICLASS_KEYS_FILE);
Dbprintf(" iClass... "_RED_("%u")" keys - "_RED_("%s"), num, ICLASS_KEYS_FILE);
}
#endif
DbpString("");
@ -2354,7 +2358,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint16_t available;
uint16_t pre_available = 0;
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
uint8_t *dest = BigBuf_calloc(USART_FIFOLEN);
uint32_t wait = payload->waittime;
StartTicks();
@ -2398,7 +2402,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint16_t available;
uint16_t pre_available = 0;
uint8_t *dest = BigBuf_malloc(USART_FIFOLEN);
uint8_t *dest = BigBuf_calloc(USART_FIFOLEN);
uint32_t wait = payload->waittime;
StartTicks();
@ -2694,7 +2698,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t size = packet->oldarg[1];
uint8_t *buff = BigBuf_malloc(size);
uint8_t *buff = BigBuf_calloc(size);
if (buff == NULL) {
if (g_dbglevel >= DBG_DEBUG) Dbprintf("Failed to allocate memory");
// Trigger a finish downloading signal with an PM3_EMALLOC
@ -2899,7 +2903,7 @@ static void PacketReceived(PacketCommandNG *packet) {
case CMD_FLASHMEM_DOWNLOAD: {
LED_B_ON();
uint8_t *mem = BigBuf_malloc(PM3_CMD_DATA_SIZE);
uint8_t *mem = BigBuf_calloc(PM3_CMD_DATA_SIZE);
uint32_t startidx = packet->oldarg[0];
uint32_t numofbytes = packet->oldarg[1];
// arg0 = startindex
@ -2931,7 +2935,7 @@ static void PacketReceived(PacketCommandNG *packet) {
case CMD_FLASHMEM_INFO: {
LED_B_ON();
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_malloc(sizeof(rdv40_validation_t));
rdv40_validation_t *info = (rdv40_validation_t *)BigBuf_calloc(sizeof(rdv40_validation_t));
bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET_P(spi_flash_pages64k), info->signature, FLASH_MEM_SIGNATURE_LEN);

View file

@ -748,7 +748,7 @@ void em4x50_chk(const char *filename, bool ledcontrol) {
uint16_t pwd_count = 0;
uint32_t size = size_in_spiffs(filename);
pwd_count = size / 4;
uint8_t *pwds = BigBuf_malloc(size);
uint8_t *pwds = BigBuf_calloc(size);
rdv40_spiffs_read_as_filetype(filename, pwds, size, RDV40_SPIFFS_SAFETY_SAFE);

View file

@ -857,7 +857,7 @@ void SmartCardRaw(const smart_card_raw_t *p) {
LED_D_ON();
uint16_t len = 0;
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *resp = BigBuf_calloc(ISO7816_MAX_FRAME);
// check if alloacted...
smartcard_command_t flags = p->flags;
@ -937,7 +937,7 @@ void SmartCardUpgrade(uint64_t arg0) {
bool isOK = true;
uint16_t length = arg0, pos = 0;
const uint8_t *fwdata = BigBuf_get_addr();
uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE);
uint8_t *verfiydata = BigBuf_calloc(I2C_BLOCK_SIZE);
while (length) {

View file

@ -40,7 +40,7 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
LED_D_ON();
uint16_t len = 0;
uint8_t *resp = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *resp = BigBuf_calloc(ISO7816_MAX_FRAME);
resp[0] = prepend;
// check if alloacted...
smartcard_command_t flags = p->flags;

View file

@ -399,40 +399,40 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
int trace_data_size;
// Respond SOF -- takes 1 bytes
uint8_t *resp_sof = BigBuf_malloc(1);
uint8_t resp_sof[1] = {0};
int resp_sof_len;
// Anticollision CSN (rotated CSN)
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
uint8_t *resp_anticoll = BigBuf_malloc(22);
uint8_t *resp_anticoll = BigBuf_calloc(22);
int resp_anticoll_len;
// CSN (block 0)
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
uint8_t *resp_csn = BigBuf_malloc(22);
uint8_t *resp_csn = BigBuf_calloc(22);
int resp_csn_len;
// configuration (blk 1) PICOPASS 2ks
uint8_t *resp_conf = BigBuf_malloc(22);
uint8_t *resp_conf = BigBuf_calloc(22);
int resp_conf_len;
// e-Purse (blk 2)
// 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
uint8_t *resp_cc = BigBuf_malloc(18);
uint8_t *resp_cc = BigBuf_calloc(18);
int resp_cc_len;
// Kd, Kc (blocks 3 and 4). Cannot be read. Always respond with 0xff bytes only
uint8_t *resp_ff = BigBuf_malloc(22);
uint8_t *resp_ff = BigBuf_calloc(22);
int resp_ff_len;
uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
AddCrc(ff_data, 8);
// Application Issuer Area (blk 5)
uint8_t *resp_aia = BigBuf_malloc(22);
uint8_t *resp_aia = BigBuf_calloc(22);
int resp_aia_len;
// receive command
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE);
// Prepare card messages
tosend_t *ts = get_tosend();
@ -474,11 +474,11 @@ int do_iclass_simulation(int simulationMode, uint8_t *reader_mac_buf) {
//This is used for responding to READ-block commands or other data which is dynamically generated
//First the 'trace'-data, not encoded for FPGA
uint8_t *data_generic_trace = BigBuf_malloc(34); // 32 bytes data + 2byte CRC is max tag answer
uint8_t *data_generic_trace = BigBuf_calloc(34); // 32 bytes data + 2byte CRC is max tag answer
//Then storage for the modulated data
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
uint8_t *data_response = BigBuf_malloc((34 * 2) + 3);
uint8_t *data_response = BigBuf_calloc((34 * 2) + 3);
enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE;
@ -942,29 +942,29 @@ int do_iclass_simulation_nonsec(void) {
int trace_data_size = 0;
// Respond SOF -- takes 1 bytes
uint8_t *resp_sof = BigBuf_malloc(2);
uint8_t resp_sof[2] = { 0 };
int resp_sof_len;
// Anticollision CSN (rotated CSN)
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
uint8_t *resp_anticoll = BigBuf_malloc(28);
uint8_t *resp_anticoll = BigBuf_calloc(28);
int resp_anticoll_len;
// CSN
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
uint8_t *resp_csn = BigBuf_malloc(28);
uint8_t *resp_csn = BigBuf_calloc(28);
int resp_csn_len;
// configuration (blk 1) PICOPASS 2ks
uint8_t *resp_conf = BigBuf_malloc(28);
uint8_t *resp_conf = BigBuf_calloc(28);
int resp_conf_len;
// Application Issuer Area (blk 5)
uint8_t *resp_aia = BigBuf_malloc(28);
uint8_t *resp_aia = BigBuf_calloc(28);
int resp_aia_len;
// receive command
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE);
// Prepare card messages
tosend_t *ts = get_tosend();
@ -997,11 +997,11 @@ int do_iclass_simulation_nonsec(void) {
//This is used for responding to READ-block commands or other data which is dynamically generated
//First the 'trace'-data, not encoded for FPGA
uint8_t *data_generic_trace = BigBuf_malloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
uint8_t *data_generic_trace = BigBuf_calloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
//Then storage for the modulated data
//Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes)
uint8_t *data_response = BigBuf_malloc((32 + 2) * 2 + 2);
uint8_t *data_response = BigBuf_calloc((32 + 2) * 2 + 2);
enum { IDLE, ACTIVATED, SELECTED, HALTED } chip_state = IDLE;

View file

@ -190,35 +190,35 @@ struct Crypto1State crypto1_state = {0, 0};
void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config"));
Dbprintf(" [a] Anticol override.............. %s%s%s",
Dbprintf(" [a] Anticol override........... %s%s%s",
(hf14aconfig.forceanticol == 0) ? _GREEN_("std") " ( follow standard )" : "",
(hf14aconfig.forceanticol == 1) ? _RED_("force") " ( always do anticol )" : "",
(hf14aconfig.forceanticol == 2) ? _RED_("skip") " ( always skip anticol )" : ""
);
Dbprintf(" [b] BCC override.................. %s%s%s",
Dbprintf(" [b] BCC override............... %s%s%s",
(hf14aconfig.forcebcc == 0) ? _GREEN_("std") " ( follow standard )" : "",
(hf14aconfig.forcebcc == 1) ? _RED_("fix") " ( fix bad BCC )" : "",
(hf14aconfig.forcebcc == 2) ? _RED_("ignore") " ( ignore bad BCC, always use card BCC )" : ""
);
Dbprintf(" [2] CL2 override.................. %s%s%s",
Dbprintf(" [2] CL2 override............... %s%s%s",
(hf14aconfig.forcecl2 == 0) ? _GREEN_("std") " ( follow standard )" : "",
(hf14aconfig.forcecl2 == 1) ? _RED_("force") " ( always do CL2 )" : "",
(hf14aconfig.forcecl2 == 2) ? _RED_("skip") " ( always skip CL2 )" : ""
);
Dbprintf(" [3] CL3 override.................. %s%s%s",
Dbprintf(" [3] CL3 override............... %s%s%s",
(hf14aconfig.forcecl3 == 0) ? _GREEN_("std") " ( follow standard )" : "",
(hf14aconfig.forcecl3 == 1) ? _RED_("force") " ( always do CL3 )" : "",
(hf14aconfig.forcecl3 == 2) ? _RED_("skip") " ( always skip CL3 )" : ""
);
Dbprintf(" [r] RATS override................. %s%s%s",
Dbprintf(" [r] RATS override.............. %s%s%s",
(hf14aconfig.forcerats == 0) ? _GREEN_("std") " ( follow standard )" : "",
(hf14aconfig.forcerats == 1) ? _RED_("force") " ( always do RATS )" : "",
(hf14aconfig.forcerats == 2) ? _RED_("skip") " ( always skip RATS )" : ""
);
Dbprintf(" [m] Magsafe polling............... %s",
Dbprintf(" [m] Magsafe polling............ %s",
(hf14aconfig.magsafe == 1) ? _GREEN_("enabled") : _YELLOW_("disabled")
);
Dbprintf(" [p] Polling loop annotation....... %s %*D",
Dbprintf(" [p] Polling loop annotation.... %s %*D",
(hf14aconfig.polling_loop_annotation.frame_length <= 0) ? _YELLOW_("disabled") : _GREEN_("enabled"),
hf14aconfig.polling_loop_annotation.frame_length,
hf14aconfig.polling_loop_annotation.frame,
@ -805,12 +805,12 @@ void RAMFUNC SniffIso14443a(uint8_t param) {
set_tracing(true);
// The command (reader -> tag) that we're receiving.
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE);
uint8_t *receivedCmdPar = BigBuf_calloc(MAX_PARITY_SIZE);
// The response (tag -> reader) that we're receiving.
uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
uint8_t *receivedResp = BigBuf_calloc(MAX_FRAME_SIZE);
uint8_t *receivedRespPar = BigBuf_calloc(MAX_PARITY_SIZE);
uint8_t previous_data = 0;
int maxDataLen = 0, dataLen;
@ -2683,9 +2683,9 @@ void iso14443a_antifuzz(uint32_t flags) {
int len = 0;
// allocate buffers:
uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
uint8_t *resp = BigBuf_malloc(20);
uint8_t *received = BigBuf_calloc(MAX_FRAME_SIZE);
uint8_t *receivedPar = BigBuf_calloc(MAX_PARITY_SIZE);
uint8_t *resp = BigBuf_calloc(20);
memset(received, 0x00, MAX_FRAME_SIZE);
memset(received, 0x00, MAX_PARITY_SIZE);
@ -4070,9 +4070,7 @@ void DetectNACKbug(void) {
// i = number of authentications sent. Not always 256, since we are trying to sync but close to it.
FpgaDisableTracing();
uint8_t *data = BigBuf_malloc(4);
data[0] = isOK;
data[1] = num_nacks;
uint8_t data[4] = {isOK, num_nacks, 0, 0};
num_to_bytes(i, 2, data + 2);
reply_ng(CMD_HF_MIFARE_NACK_DETECT, status, data, 4);

View file

@ -221,10 +221,11 @@ out:
int sam_get_version(void) {
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("start sam_get_version");
}
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
uint16_t response_len = ISO7816_MAX_FRAME;
uint8_t payload[] = {
@ -252,8 +253,9 @@ int sam_get_version(void) {
// 82 01
// 01
// 90 00
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("end sam_get_version");
}
if (response[5] != 0xbd) {
Dbprintf("Invalid SAM response");
@ -289,8 +291,9 @@ error:
out:
BigBuf_free();
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("end sam_get_version");
}
return res;
}
@ -350,12 +353,10 @@ void sam_append_asn1_node(const uint8_t *root, const uint8_t *node, uint8_t type
}
void sam_send_ack(void) {
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
uint16_t response_len = ISO7816_MAX_FRAME;
uint8_t payload[] = {
0xa0, 0
};
uint8_t payload[] = { 0xa0, 0 };
uint16_t payload_len = sizeof(payload);
sam_send_payload(

View file

@ -46,11 +46,12 @@
*/
static int sam_send_request_iso15(const uint8_t *const request, const uint8_t request_len, uint8_t *response, uint8_t *response_len, const bool shallow_mod, const bool break_on_nr_mac, const bool prevent_epurse_update) {
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("start sam_send_request_iso14a");
}
uint8_t *buf1 = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *buf2 = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *buf1 = BigBuf_calloc(ISO7816_MAX_FRAME);
uint8_t *buf2 = BigBuf_calloc(ISO7816_MAX_FRAME);
if (buf1 == NULL || buf2 == NULL) {
res = PM3_EMALLOC;
goto out;
@ -255,10 +256,10 @@ out:
*/
static int sam_set_card_detected_picopass(const picopass_hdr_t *card_select) {
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("start sam_set_card_detected");
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
}
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
uint16_t response_len = ISO7816_MAX_FRAME;
// a0 12
@ -314,8 +315,9 @@ error:
out:
BigBuf_free();
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("end sam_set_card_detected");
}
return res;
}

View file

@ -51,13 +51,14 @@
*/
static int sam_set_card_detected_seos(iso14a_card_select_t *card_select) {
int res = PM3_SUCCESS;
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("start sam_set_card_detected");
}
uint8_t *request = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *request = BigBuf_calloc(ISO7816_MAX_FRAME);
uint16_t request_len = ISO7816_MAX_FRAME;
uint8_t *response = BigBuf_malloc(ISO7816_MAX_FRAME);
uint8_t *response = BigBuf_calloc(ISO7816_MAX_FRAME);
uint16_t response_len = ISO7816_MAX_FRAME;
const uint8_t payload[] = {
@ -107,8 +108,9 @@ error:
out:
BigBuf_free();
if (g_dbglevel >= DBG_DEBUG)
if (g_dbglevel >= DBG_DEBUG) {
DbpString("end sam_set_card_detected");
}
return res;
}

View file

@ -312,7 +312,7 @@ static int is_valid_filename(const char *filename) {
*/
static void copy_in_spiffs(const char *src, const char *dst) {
uint32_t size = size_in_spiffs(src);
uint8_t *mem = BigBuf_malloc(size);
uint8_t *mem = BigBuf_calloc(size);
read_from_spiffs(src, (uint8_t *)mem, size);
write_to_spiffs(dst, (uint8_t *)mem, size);
}

View file

@ -914,7 +914,7 @@ int CmdHF14ASim(const char *Cmd) {
bool keypress = kbd_enter_pressed();
while (keypress == false) {
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == false)
continue;
if (resp.status != PM3_SUCCESS)
@ -4037,7 +4037,7 @@ int CmdHF14AAIDSim(const char *Cmd) {
bool keypress = kbd_enter_pressed();
while (keypress == false) {
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) {
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == false) {
continue;
}

View file

@ -1411,7 +1411,7 @@ static bool HF14B_ask_ct_reader(bool verbose) {
return false;
}
bool HF14B_picopass_reader(bool verbose, bool info) {
static bool HF14B_picopass_reader(bool verbose) {
iso14b_raw_cmd_t packet = {
.flags = (ISO14B_CONNECT | ISO14B_SELECT_PICOPASS | ISO14B_DISCONNECT),
@ -1437,10 +1437,8 @@ bool HF14B_picopass_reader(bool verbose, bool info) {
return false;
}
memcpy(card, resp.data.asBytes, sizeof(picopass_hdr_t));
if (info) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn)));
}
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn)));
free(card);
return true;
}
@ -3038,7 +3036,6 @@ int infoHF14B(bool verbose, bool do_aid_search) {
// get and print general info about all known 14b chips
int readHF14B(bool loop, bool verbose, bool read_plot) {
bool found = false;
bool info = true;
int res = PM3_SUCCESS;
do {
found = false;
@ -3054,7 +3051,7 @@ int readHF14B(bool loop, bool verbose, bool read_plot) {
goto plot;
// Picopass
found |= HF14B_picopass_reader(verbose, info);
found |= HF14B_picopass_reader(verbose);
if (found)
goto plot;

View file

@ -31,6 +31,5 @@ int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card);
int infoHF14B(bool verbose, bool do_aid_search);
int readHF14B(bool loop, bool verbose, bool read_plot);
bool HF14B_picopass_reader(bool verbose, bool info);
#endif

View file

@ -40,7 +40,6 @@
#include "crypto/asn1utils.h" // ASN1 decoder
#include "preferences.h"
#include "generator.h"
#include "cmdhf14b.h"
#include "cmdhw.h"
#include "hidsio.h"
@ -584,14 +583,14 @@ static void fuse_config(const picopass_hdr_t *hdr) {
uint16_t otp = (hdr->conf.otp[1] << 8 | hdr->conf.otp[0]);
PrintAndLogEx(INFO, " Raw... " _YELLOW_("%s"), sprint_hex((uint8_t *)&hdr->conf, 8));
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " ( %3u )............. app limit", hdr->conf.app_limit, hdr->conf.app_limit);
PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ block write lock", hdr->conf.block_writelock);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... chip", hdr->conf.chip_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... mem", hdr->conf.mem_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " fuses", hdr->conf.fuses);
PrintAndLogEx(INFO, " Raw: " _YELLOW_("%s"), sprint_hex((uint8_t *)&hdr->conf, 8));
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " ( %3u )............. app limit", hdr->conf.app_limit, hdr->conf.app_limit);
PrintAndLogEx(INFO, " " _YELLOW_("%04X") " ( %5u )...... OTP", otp, otp);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ block write lock", hdr->conf.block_writelock);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... chip", hdr->conf.chip_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... mem", hdr->conf.mem_config);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... EAS", hdr->conf.eas);
PrintAndLogEx(INFO, " " _YELLOW_("%02X") " fuses", hdr->conf.fuses);
uint8_t fuses = hdr->conf.fuses;
@ -1467,8 +1466,9 @@ static void iclass_decode_credentials(uint8_t *data) {
bool has_values = (memcmp(b7, empty, PICOPASS_BLOCK_SIZE) != 0) && (memcmp(b7, zeros, PICOPASS_BLOCK_SIZE) != 0);
if (has_values && encryption == None) {
// todo: remove preamble/sentinel
PrintAndLogEx(INFO, "------------------------ " _CYAN_("Block 7 decoder") " --------------------------");
// todo: remove preamble/sentinel
if (has_new_pacs) {
iclass_decode_credentials_new_pacs(b7);
} else {
@ -1487,9 +1487,6 @@ static void iclass_decode_credentials(uint8_t *data) {
PrintAndLogEx(NORMAL, "");
decode_wiegand(top, mid, bot, 0);
}
} else {
PrintAndLogEx(INFO, "No unencrypted legacy credential found");
}
}
@ -1950,7 +1947,7 @@ static int CmdHFiClassDump(const char *Cmd) {
return PM3_EINVARG;
}
}
if (credit_key_len > 0 && credit_key_nr >= 0) {
PrintAndLogEx(ERR, "Please specify credit key or index, not both");
return PM3_EINVARG;
@ -2267,7 +2264,7 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *macdata
SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 2000) == 0) {
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 2000) == false) {
if (verbose) PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
@ -2401,14 +2398,13 @@ static int CmdHFiClassCreditEpurse(const char *Cmd) {
"Credit the epurse on an iCLASS tag. The provided key must be the credit key.\n"
"The first two bytes of the epurse are the debit value (big endian) and may be any value except FFFF.\n"
"The remaining two bytes of the epurse are the credit value and must be smaller than the previous value.",
"hf iclass creditepurse -d FEFFFFFF -k 001122334455667B\n"
"hf iclass creditepurse -d FEFFFFFF --ki 0");
"hf iclass creditepurse --ki 0 -d FEFFFEFF");
void *argtable[] = {
arg_param_begin,
arg_str0("k", "key", "<hex>", "Credit key as 8 hex bytes"),
arg_int0(NULL, "ki", "<dec>", "Key index to select key from memory 'hf iclass managekeys'"),
arg_str1("d", "data", "<hex>", "data to write as 8 hex bytes"),
arg_str1("d", "data", "<hex>", "data to write as 4 hex bytes"),
arg_lit0(NULL, "elite", "elite computations applied to key"),
arg_lit0(NULL, "raw", "no computations applied to key"),
arg_lit0("v", "verbose", "verbose output"),
@ -2493,7 +2489,7 @@ static int CmdHFiClassCreditEpurse(const char *Cmd) {
PacketResponseNG resp;
int isok;
if (WaitForResponseTimeout(CMD_HF_ICLASS_CREDIT_EPURSE, &resp, 2000) == 0) {
if (WaitForResponseTimeout(CMD_HF_ICLASS_CREDIT_EPURSE, &resp, 2000) == false) {
if (verbose) PrintAndLogEx(WARNING, "command execution time out");
isok = PM3_ETIMEOUT;
} else if (resp.status != PM3_SUCCESS) {
@ -2675,7 +2671,7 @@ static int CmdHFiClassRestore(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_RESTORE, (uint8_t *)payload, payload_size);
if (WaitForResponseTimeout(CMD_HF_ICLASS_RESTORE, &resp, 2500) == 0) {
if (WaitForResponseTimeout(CMD_HF_ICLASS_RESTORE, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "command execution time out");
DropField();
free(payload);
@ -2921,7 +2917,7 @@ static void iclass_cmp_print(uint8_t *b1, uint8_t *b2, const char *header1, cons
strcat(line1, header1);
strcat(line2, header2);
for (uint8_t i = 0; i < PICOPASS_BLOCK_SIZE; i++ ) {
for (uint8_t i = 0; i < PICOPASS_BLOCK_SIZE; i++) {
int l1 = strlen(line1);
int l2 = strlen(line2);
@ -2961,7 +2957,8 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
CLIParserInit(&ctx, "hf iclass tear",
"Tear off an iCLASS tag block\n"
"e-purse usually 300-500us to trigger the erase phase\n"
"also seen 1800-2100us on some cards\n",
"also seen 1800-2100us on some cards\n"
"Make sure you know the target card credit key. Typical `--ki 1` or `--ki 3`\n",
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B -s 300 -e 600\n"
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA --ki 0 -s 300 -e 600\n"
"hf iclass tear --blk 2 -d fdffffffffffffff --ki 1 --credit -s 400 -e 500"
@ -3011,7 +3008,8 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
bool verbose = arg_get_lit(ctx, 10);
bool shallow_mod = arg_get_lit(ctx, 11);
int tearoff_start = arg_get_int_def(ctx, 12, 5000);
int tearoff_start = arg_get_int_def(ctx, 12, 100);
int tearoff_original_start = tearoff_start; // save original start value for later use
int tearoff_increment = arg_get_int_def(ctx, 13, 10);
int tearoff_end = arg_get_int_def(ctx, 14, tearoff_start + tearoff_increment + 500);
int tearoff_loop = arg_get_int_def(ctx, 15, 1);
@ -3034,18 +3032,19 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
PrintAndLogEx(ERR, "Key is incorrect length");
return PM3_EINVARG;
}
PrintAndLogEx(NORMAL, "");
}
} else if (key_nr >= 0) {
if (key_nr >= 0) {
if (key_nr < ICLASS_KEYS_MAX) {
auth = true;
memcpy(key, iClass_Key_Table[key_nr], 8);
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex(iClass_Key_Table[key_nr], 8));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Using key[%d] " _GREEN_("%s"), key_nr, sprint_hex_inrow(iClass_Key_Table[key_nr], 8));
} else {
PrintAndLogEx(ERR, "Key number is invalid");
return PM3_EINVARG;
}
}
if (data_len != 8) {
@ -3059,17 +3058,22 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
}
if (tearoff_end <= tearoff_start) {
PrintAndLogEx(ERR, "Tearoff end delay must be bigger than the start delay.");
PrintAndLogEx(ERR, "Tearoff end delay must be larger than the start delay");
return PM3_EINVARG;
}
if (tearoff_start < 0 || tearoff_end <= 0) {
PrintAndLogEx(ERR, "Tearoff start/end delays should be bigger than 0.");
if (tearoff_start <= 0) {
PrintAndLogEx(ERR, "Tearoff_start delays must be larger than 0");
return PM3_EINVARG;
}
if (tearoff_end <= 0) {
PrintAndLogEx(ERR, "Tearoff_end delays must be larger than 0");
return PM3_EINVARG;
}
if ((use_replay + rawkey + elite) > 1) {
PrintAndLogEx(ERR, "Can not use a combo of 'elite', 'raw', 'nr'");
PrintAndLogEx(ERR, "Can not use a combo of `--elite`, `--raw`, `--nr`");
return PM3_EINVARG;
}
@ -3087,6 +3091,10 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
PrintAndLogEx(SUCCESS, "No key supplied. Trying no authentication read/writes");
}
if (tearoff_loop > 1) {
PrintAndLogEx(SUCCESS, _YELLOW_("%u") " attempts / tearoff", tearoff_loop);
}
if (tearoff_sleep) {
PrintAndLogEx(SUCCESS, "Using " _YELLOW_("%u") " ms delay between attempts", tearoff_sleep);
}
@ -3129,7 +3137,14 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
auth = false;
}
//perform initial read here, repeat if failed or 00s
if (pagemap == 0x0) {
PrintAndLogEx(WARNING, _RED_("No auth possible. Read only if RA is enabled"));
goto out;
}
bool read_auth = auth;
// perform initial read here, repeat if failed or 00s
uint8_t data_read_orig[8] = {0};
uint8_t ff_data[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
bool first_read = false;
@ -3149,6 +3164,9 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
reread = false;
}
PrintAndLogEx(SUCCESS, "Original block data... " _CYAN_("%s"), sprint_hex_inrow(data_read_orig, sizeof(data_read_orig)));
PrintAndLogEx(SUCCESS, "New data to write..... " _YELLOW_("%s"), sprint_hex_inrow(data, sizeof(data)));
PrintAndLogEx(SUCCESS, "Target block.......... " _YELLOW_("%u") " / " _YELLOW_("0x%02x"), blockno, blockno);
// turn off Device side debug messages
uint8_t dbg_curr = DBG_NONE;
if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
@ -3159,11 +3177,16 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
return PM3_EFAILED;
}
PrintAndLogEx(INFO, "Starting tear off against block " _YELLOW_("%u") " / " _YELLOW_("0x%02x"), blockno, blockno);
PrintAndLogEx(INFO, "");
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to abort");
// clear trace log
SendCommandNG(CMD_BUFF_CLEAR, NULL, 0);
while (tearoff_start <= tearoff_end && read_ok == false) {
PrintAndLogEx(INFO, "---------------------------------------");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------\n");
// Main loop
while ((tearoff_start <= tearoff_end) && (read_ok == false)) {
if (kbd_enter_pressed()) {
PrintAndLogEx(WARNING, "\naborted via keyboard.");
@ -3174,7 +3197,7 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
// set tear off trigger
clearCommandBuffer();
tearoff_params_t params = {
.delay_us = tearoff_start,
.delay_us = (tearoff_start & 0xFFFF),
.on = true,
.off = false
};
@ -3186,18 +3209,22 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
goto out;
}
// write
// don't check the return value. As a tear-off occurred, the write failed.
//PrintAndLogEx(NORMAL, "\r" NOLF);
PrintAndLogEx(INPLACE, " Tear off delay "_YELLOW_("%d")" / "_YELLOW_("%d")" us", tearoff_start, tearoff_end);
iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, verbose, auth, shallow_mod);
if (tearoff_loop > 1) {
PrintAndLogEx(INPLACE, " Tear off delay "_YELLOW_("%u")" / "_YELLOW_("%d")" us - "_YELLOW_("%3u")" loops", params.delay_us, (tearoff_end & 0xFFFF), loop_count + 1);
} else {
PrintAndLogEx(INPLACE, " Tear off delay "_YELLOW_("%u")" / "_YELLOW_("%d")" us", params.delay_us, (tearoff_end & 0xFFFF));
}
//read the data back
// write block - don't check the return value. As a tear-off occurred, the write failed.
// when tear off is enabled, the return code will always be PM3_ETEAROFF
iclass_write_block(blockno, data, mac, key, use_credit_key, elite, rawkey, use_replay, false, auth, shallow_mod);
// read the data back
uint8_t data_read[8] = {0};
first_read = false;
reread = false;
bool decrease = false;
int readcount = 0;
while (first_read == false) {
if (kbd_enter_pressed()) {
@ -3206,7 +3233,12 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
goto out;
}
res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, auth, shallow_mod, data_read, false);
// skip authentication for config and e-purse blocks (1,2)
if (blockno < 3) {
read_auth = false;
}
res = iclass_read_block_ex(key, blockno, keyType, elite, rawkey, use_replay, verbose, read_auth, shallow_mod, data_read, false);
if (res == PM3_SUCCESS && !reread) {
if (memcmp(data_read, zeros, 8) == 0) {
reread = true;
@ -3220,10 +3252,21 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
} else if (res != PM3_SUCCESS) {
decrease = true;
}
if (readcount >= 10){
PrintAndLogEx(WARNING, "\n"_RED_("Read failed too many times, giving up"));
isok = PM3_EFAILED;
goto out;
}
readcount++;
}
if (decrease && tearoff_start > 0) { // if there was an error reading repeat the tearoff with the same delay
// if there was an error reading repeat the tearoff with the same delay
if (decrease && (tearoff_start > tearoff_increment) && (tearoff_start >= tearoff_original_start)) {
tearoff_start -= tearoff_increment;
if(verbose){
PrintAndLogEx(INFO, " -> Read failed, retearing with "_CYAN_("%u")" us", tearoff_start);
}
}
bool tear_success = true;
@ -3233,46 +3276,86 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
tear_success = false;
}
if ((tear_success == false) && (memcmp(data_read, zeros, 8) != 0) && (memcmp(data_read, data_read_orig, 8) != 0)) { // tearoff succeeded (partially)
if ((tear_success == false) && (memcmp(data_read, zeros, 8) != 0) && (memcmp(data_read, data_read_orig, 8) != 0)) {
// tearoff succeeded (partially)
expected_values = false;
if (memcmp(data_read, ff_data, 8) == 0 && memcmp(data_read_orig, ff_data, 8) != 0) {
erase_phase = true;
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _BLUE_("Erase phase hit: ALL ONES"));
PrintAndLogEx(SUCCESS, _CYAN_("Erase phase hit... ALL ONES"));
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
} else {
if (erase_phase) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _MAGENTA_("Tearing! Write Phase (post erase)"));
PrintAndLogEx(SUCCESS, _MAGENTA_("Tearing! Write phase (post erase)"));
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
} else {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, _CYAN_("Tearing! (unknown phase)"));
PrintAndLogEx(SUCCESS, _CYAN_("Tearing! unknown phase"));
iclass_cmp_print(data_read_orig, data_read, "Original: ", "Read: ");
}
}
bool goto_out = false;
if (blockno == 2) {
if (memcmp(data_read, ff_data, 8) == 0 && memcmp(data_read_orig, ff_data, 8) != 0) {
PrintAndLogEx(SUCCESS, "E-purse has been teared ( %s )", _GREEN_("ok"));
PrintAndLogEx(HINT, "Hint: try `hf iclass creditepurse -d FEFFFEFF --ki 1`");
PrintAndLogEx(HINT, "Hint: try `hf iclass wrbl -d 'FFFFFFFF FFFF FEFF' --blk 2 --ki 1 --credit`");
isok = PM3_SUCCESS;
goto_out = true;
}
}
if (blockno == 1) {
if (data_read[0] != data_read_orig[0]) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Application limit changed, from %u to %u", data_read_orig[0], data_read[0]);
PrintAndLogEx(SUCCESS, "Application limit changed, from "_YELLOW_("%u")" to "_YELLOW_("%u"), data_read_orig[0], data_read[0]);
isok = PM3_SUCCESS;
goto out;
goto_out = true;
}
if (data_read[7] != data_read_orig[7]) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(SUCCESS, "Fuse changed, from %02x to %02x", data_read_orig[7], data_read[7]);
PrintAndLogEx(SUCCESS, "Fuse changed, from "_YELLOW_("%02x")" to "_YELLOW_("%02x"), data_read_orig[7], data_read[7]);
const char *flag_names[8] = {
"RA",
"Fprod0",
"Fprod1",
"Crypt0 (*1)",
"Crypt1 (*0)",
"Coding0",
"Coding1",
"Fpers (*1)"
};
PrintAndLogEx(INFO, _YELLOW_("%-10s %-10s %-10s"), "Fuse", "Original", "Changed");
PrintAndLogEx(INFO, "---------------------------------------");
for (int i = 7; i >= 0; --i) {
int bit1 = (data_read_orig[7] >> i) & 1;
int bit2 = (data_read[7] >> i) & 1;
PrintAndLogEx(INFO, "%-11s %-10d %-10d", flag_names[i], bit1, bit2);
}
isok = PM3_SUCCESS;
goto_out = true;
}
// if more OTP bits set..
if (data_read[1] > data_read_orig[1] ||
data_read[2] > data_read_orig[2]) {
PrintAndLogEx(SUCCESS, "More OTP bits got set!!!");
isok = PM3_SUCCESS;
goto out;
}
}
} else { // tearoff did not succeed
// PrintAndLogEx(INFO, "Expected: %s", sprint_hex_inrow(data, sizeof(data)));
// PrintAndLogEx(INFO, "Read: %s", sprint_hex_inrow(data_read, sizeof(data_read)));
if (goto_out) {
goto out;
}
}
if (tear_success) { // tearoff succeeded with expected values
@ -3282,9 +3365,9 @@ static int CmdHFiClass_TearBlock(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Read: " _GREEN_("%s") " %s"
, sprint_hex_inrow(data_read, sizeof(data_read)),
(expected_values) ? _GREEN_(" -> Expected values!") : ""
);
, sprint_hex_inrow(data_read, sizeof(data_read)),
(expected_values) ? _GREEN_(" -> Expected values!") : ""
);
}
loop_count++;
@ -3315,6 +3398,8 @@ out:
};
handle_tearoff(&params, false);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Done!");
PrintAndLogEx(NORMAL, "");
clearCommandBuffer();
return isok;
}
@ -5842,7 +5927,7 @@ int info_iclass(bool shallow_mod) {
} else {
if ((r->status & FLAG_ICLASS_CC) == FLAG_ICLASS_CC) {
PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
PrintAndLogEx(SUCCESS, "E-purse: %s card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
}
if (memcmp(hdr->key_d, zeros, sizeof(zeros))) {
@ -5899,10 +5984,10 @@ int info_iclass(bool shallow_mod) {
uint8_t cardtype = get_mem_config(hdr);
PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
if (HF14B_picopass_reader(false, false)) {
PrintAndLogEx(SUCCESS, " Card chip.... "_YELLOW_("Old Silicon (14b support)"));
} else {
if (memcmp(hdr->csn + 4, "\xFE\xFF\x12\xE0", 4) == 0) {
PrintAndLogEx(SUCCESS, " Card chip.... "_YELLOW_("NEW Silicon (No 14b support)"));
} else {
PrintAndLogEx(SUCCESS, " Card chip.... "_YELLOW_("Old Silicon (14b support)"));
}
if (legacy) {
@ -5941,5 +6026,6 @@ int info_iclass(bool shallow_mod) {
}
}
PrintAndLogEx(NORMAL, "");
return PM3_SUCCESS;
}

View file

@ -131,7 +131,7 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16
SendCommandMIX(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply");
return PM3_ETIMEOUT;
}

View file

@ -48,6 +48,301 @@
#include "mifare/mifarehost.h"
#include "crypto/originality.h"
// Defines for Saflok parsing
#define SAFLOK_YEAR_OFFSET 1980
#define SAFLOK_BASIC_ACCESS_BYTE_NUM 17
#define SAFLOK_KEY_LENGTH 6
#define SAFLOK_UID_LENGTH 4 // Matches Mifare 4-byte UID
#define SAFLOK_MAGIC_TABLE_SIZE 192
#define SAFLOK_CHECK_SECTOR 1
typedef struct {
uint64_t a;
uint64_t b;
} MfClassicKeyPair;
// Structure for Saflok key levels
typedef struct {
uint8_t level_num;
const char *level_name;
} SaflokKeyLevel;
// Static array for Saflok key levels
static const SaflokKeyLevel saflok_key_levels[] = {
{1, "Guest Key"},
{2, "Connectors"},
{3, "Suite"},
{4, "Limited Use"},
{5, "Failsafe"},
{6, "Inhibit"},
{7, "Pool/Meeting Master"},
{8, "Housekeeping"},
{9, "Floor Key"},
{10, "Section Key"},
{11, "Rooms Master"},
{12, "Grand Master"},
{13, "Emergency"},
{14, "Electronic Lockout"},
{15, "Secondary Programming Key (SPK)"},
{16, "Primary Programming Key (PPK)"},
};
// Lookup table for Saflok decryption
static const uint8_t saflok_c_aDecode[256] = {
0xEA, 0x0D, 0xD9, 0x74, 0x4E, 0x28, 0xFD, 0xBA, 0x7B, 0x98, 0x87, 0x78, 0xDD, 0x8D, 0xB5,
0x1A, 0x0E, 0x30, 0xF3, 0x2F, 0x6A, 0x3B, 0xAC, 0x09, 0xB9, 0x20, 0x6E, 0x5B, 0x2B, 0xB6,
0x21, 0xAA, 0x17, 0x44, 0x5A, 0x54, 0x57, 0xBE, 0x0A, 0x52, 0x67, 0xC9, 0x50, 0x35, 0xF5,
0x41, 0xA0, 0x94, 0x60, 0xFE, 0x24, 0xA2, 0x36, 0xEF, 0x1E, 0x6B, 0xF7, 0x9C, 0x69, 0xDA,
0x9B, 0x6F, 0xAD, 0xD8, 0xFB, 0x97, 0x62, 0x5F, 0x1F, 0x38, 0xC2, 0xD7, 0x71, 0x31, 0xF0,
0x13, 0xEE, 0x0F, 0xA3, 0xA7, 0x1C, 0xD5, 0x11, 0x4C, 0x45, 0x2C, 0x04, 0xDB, 0xA6, 0x2E,
0xF8, 0x64, 0x9A, 0xB8, 0x53, 0x66, 0xDC, 0x7A, 0x5D, 0x03, 0x07, 0x80, 0x37, 0xFF, 0xFC,
0x06, 0xBC, 0x26, 0xC0, 0x95, 0x4A, 0xF1, 0x51, 0x2D, 0x22, 0x18, 0x01, 0x79, 0x5E, 0x76,
0x1D, 0x7F, 0x14, 0xE3, 0x9E, 0x8A, 0xBB, 0x34, 0xBF, 0xF4, 0xAB, 0x48, 0x63, 0x55, 0x3E,
0x56, 0x8C, 0xD1, 0x12, 0xED, 0xC3, 0x49, 0x8E, 0x92, 0x9D, 0xCA, 0xB1, 0xE5, 0xCE, 0x4D,
0x3F, 0xFA, 0x73, 0x05, 0xE0, 0x4B, 0x93, 0xB2, 0xCB, 0x08, 0xE1, 0x96, 0x19, 0x3D, 0x83,
0x39, 0x75, 0xEC, 0xD6, 0x3C, 0xD0, 0x70, 0x81, 0x16, 0x29, 0x15, 0x6C, 0xC7, 0xE7, 0xE2,
0xF6, 0xB7, 0xE8, 0x25, 0x6D, 0x3A, 0xE6, 0xC8, 0x99, 0x46, 0xB0, 0x85, 0x02, 0x61, 0x1B,
0x8B, 0xB3, 0x9F, 0x0B, 0x2A, 0xA8, 0x77, 0x10, 0xC1, 0x88, 0xCC, 0xA4, 0xDE, 0x43, 0x58,
0x23, 0xB4, 0xA1, 0xA5, 0x5C, 0xAE, 0xA9, 0x7E, 0x42, 0x40, 0x90, 0xD2, 0xE9, 0x84, 0xCF,
0xE4, 0xEB, 0x47, 0x4F, 0x82, 0xD4, 0xC5, 0x8F, 0xCD, 0xD3, 0x86, 0x00, 0x59, 0xDF, 0xF2,
0x0C, 0x7C, 0xC6, 0xBD, 0xF9, 0x7D, 0xC4, 0x91, 0x27, 0x89, 0x32, 0x72, 0x33, 0x65, 0x68,
0xAF
};
// Function to decrypt Saflok card data
static void DecryptSaflokCardData(
const uint8_t strCard[SAFLOK_BASIC_ACCESS_BYTE_NUM],
// int length, // length is always SAFLOK_BASIC_ACCESS_BYTE_NUM
uint8_t decryptedCard[SAFLOK_BASIC_ACCESS_BYTE_NUM]) {
int i;
int num;
int num2;
int num3;
int num4;
int b = 0;
int b2 = 0;
for (i = 0; i < SAFLOK_BASIC_ACCESS_BYTE_NUM; i++) {
num = saflok_c_aDecode[strCard[i]] - (i + 1);
if (num < 0) num += 256;
decryptedCard[i] = num;
}
b = decryptedCard[10];
b2 = b & 1;
for (num2 = SAFLOK_BASIC_ACCESS_BYTE_NUM; num2 > 0; num2--) {
b = decryptedCard[num2 - 1];
for (num3 = 8; num3 > 0; num3--) {
num4 = num2 + num3;
if (num4 > SAFLOK_BASIC_ACCESS_BYTE_NUM) num4 -= SAFLOK_BASIC_ACCESS_BYTE_NUM;
int b3 = decryptedCard[num4 - 1];
int b4 = (b3 & 0x80) >> 7;
b3 = ((b3 << 1) & 0xFF) | b2;
b2 = (b & 0x80) >> 7;
b = ((b << 1) & 0xFF) | b4;
decryptedCard[num4 - 1] = b3;
}
decryptedCard[num2 - 1] = b;
}
}
// Function to calculate Saflok checksum
static uint8_t CalculateCheckSum(uint8_t data[SAFLOK_BASIC_ACCESS_BYTE_NUM]) {
int sum = 0;
for (int i = 0; i < SAFLOK_BASIC_ACCESS_BYTE_NUM - 1; i++) {
sum += data[i];
}
sum = 255 - (sum & 0xFF);
return sum & 0xFF;
}
// Function to parse and print Saflok data
static void ParseAndPrintSaflokData(const sector_t* sector0_info, const sector_t* sector1_info) {
(void)sector1_info; // Not directly used for payload parsing currently
if (!sector0_info) {
PrintAndLogEx(WARNING, "Saflok: Sector 0 information not available for parsing.");
return;
}
uint8_t key_bytes_for_s0[MIFARE_KEY_SIZE];
uint8_t key_type_for_s0; // CORRECTED: Was MifareKeyType, now uint8_t
bool s0_key_found = false;
// Prioritize Key A for Sector 0 if available
if (sector0_info->foundKey[MF_KEY_A]) {
num_to_bytes(sector0_info->Key[MF_KEY_A], MIFARE_KEY_SIZE, key_bytes_for_s0);
key_type_for_s0 = MF_KEY_A; // MF_KEY_A is typically #define'd as 0x60
s0_key_found = true;
PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key A for reading blocks.");
} else if (sector0_info->foundKey[MF_KEY_B]) { // Fallback to Key B for Sector 0
num_to_bytes(sector0_info->Key[MF_KEY_B], MIFARE_KEY_SIZE, key_bytes_for_s0);
key_type_for_s0 = MF_KEY_B; // MF_KEY_B is typically #define'd as 0x61
s0_key_found = true;
PrintAndLogEx(DEBUG, "Saflok: Using Sector 0 Key B for reading blocks.");
}
if (!s0_key_found) {
PrintAndLogEx(WARNING, "Saflok: No known keys for Sector 0. Cannot read blocks 1 & 2 for parsing.");
return;
}
uint8_t block1_content[MFBLOCK_SIZE];
uint8_t block2_content[MFBLOCK_SIZE];
// Read absolute block 1 (data block within sector 0)
if (mf_read_block(1, key_type_for_s0, key_bytes_for_s0, block1_content) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 1 using Sector 0 %s key.", (key_type_for_s0 == MF_KEY_A) ? "A" : "B");
return;
}
PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 1.");
// Read absolute block 2 (data block within sector 0)
if (mf_read_block(2, key_type_for_s0, key_bytes_for_s0, block2_content) != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "Saflok: Failed to read card Block 2 using Sector 0 %s key.", (key_type_for_s0 == MF_KEY_A) ? "A" : "B");
return;
}
PrintAndLogEx(DEBUG, "Saflok: Successfully read card Block 2.");
uint8_t basicAccess[SAFLOK_BASIC_ACCESS_BYTE_NUM];
uint8_t decodedBA[SAFLOK_BASIC_ACCESS_BYTE_NUM];
memcpy(basicAccess, block1_content, 16); // 16 bytes from Block 1
memcpy(basicAccess + 16, block2_content, 1); // 1 byte from Block 2
DecryptSaflokCardData(basicAccess, decodedBA);
// Byte 0: Key level, LED warning bit, and subgroup functions
uint8_t key_level = (decodedBA[0] & 0xF0) >> 4;
uint8_t led_warning = (decodedBA[0] & 0x08) >> 3;
// Byte 1: Key ID
uint8_t key_id = decodedBA[1];
// Byte 2 & 3: KeyRecord, including OpeningKey flag
uint8_t key_record_high = decodedBA[2] & 0x7F;
uint8_t opening_key = (decodedBA[2] & 0x80) >> 7;
uint16_t key_record = (key_record_high << 8) | decodedBA[3];
// Byte 5 & 6: EncryptSequence + Combination
uint16_t sequence_combination_number = ((decodedBA[5] & 0x0F) << 8) | decodedBA[6];
// Byte 7: OverrideDeadbolt and Days
uint8_t override_deadbolt = (decodedBA[7] & 0x80) >> 7;
uint8_t restricted_weekday = decodedBA[7] & 0x7F;
// Weekday names array
static const char *weekdays[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
// Buffer to store the resulting string (sufficient size for all weekdays)
char restricted_weekday_string[128] = {0};
int restricted_count = 0;
// Check each bit from Monday to Sunday
for (int i = 0; i < 7; i++) {
if (restricted_weekday & (0b01000000 >> i)) {
// If the bit is set, append the corresponding weekday to the buffer
if (restricted_count > 0) {
strcat(restricted_weekday_string, ", ");
}
strcat(restricted_weekday_string, weekdays[i]);
restricted_count++;
}
}
// Determine if all weekdays are restricted
if (restricted_weekday == 0b01111100) {
strcpy(restricted_weekday_string, "weekdays");
}
// If there are specific restricted days
else if (restricted_weekday == 0b00000011) {
strcpy(restricted_weekday_string, "weekends");
}
// If no weekdays are restricted
else if (restricted_weekday == 0) {
strcpy(restricted_weekday_string, "none");
}
// Bytes 14-15: Property number and part of creation year
uint8_t creation_year_high_bits = (decodedBA[14] & 0xF0);
uint16_t property_id = ((decodedBA[14] & 0x0F) << 8) | decodedBA[15];
// Bytes 11-13: Creation date since SAFLOK_YEAR_OFFSET Jan 1st
uint16_t creation_year = (((decodedBA[11] & 0xF0) >> 4) + SAFLOK_YEAR_OFFSET) | creation_year_high_bits;
uint8_t creation_month = decodedBA[11] & 0x0F;
uint8_t creation_day = (decodedBA[12] >> 3) & 0x1F;
uint8_t creation_hour = ((decodedBA[12] & 0x07) << 2) | ((decodedBA[13] & 0xC0) >> 6);
uint8_t creation_minute = decodedBA[13] & 0x3F;
// Bytes 8-10: Expiry interval / absolute time components
uint8_t interval_year_val = (decodedBA[8] >> 4);
uint8_t interval_month_val = decodedBA[8] & 0x0F;
uint8_t interval_day_val = (decodedBA[9] >> 3) & 0x1F;
uint8_t expiry_hour = ((decodedBA[9] & 0x07) << 2) | ((decodedBA[10] & 0xC0) >> 6);
uint8_t expiry_minute = decodedBA[10] & 0x3F;
uint16_t expire_year = creation_year + interval_year_val;
uint8_t expire_month = creation_month + interval_month_val;
uint8_t expire_day = creation_day + interval_day_val;
// Handle month rollover for expiration
while (expire_month > 12) {
expire_month -= 12;
expire_year++;
}
// Handle day rollover for expiration
static const uint8_t days_in_month_lookup[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 1-indexed month
if (expire_month > 0 && expire_month <= 12) {
while (true) {
uint8_t max_days = days_in_month_lookup[expire_month];
if (expire_month == 2 && (expire_year % 4 == 0 && (expire_year % 100 != 0 || expire_year % 400 == 0))) {
max_days = 29; // Leap year
}
if (expire_day <= max_days) {
break;
}
if (max_days == 0) { // Should not happen with valid month
PrintAndLogEx(WARNING, "Saflok: Invalid day/month for expiration rollover calculation.");
break;
}
expire_day -= max_days;
expire_month++;
if (expire_month > 12) {
expire_month = 1;
expire_year++;
}
}
} else if (expire_month != 0) { // Allow 0 if it signifies no expiration or error
PrintAndLogEx(WARNING, "Saflok: Invalid expiration month (%u) before day rollover.", expire_month);
}
uint8_t checksum = decodedBA[16];
uint8_t checksum_calculated = CalculateCheckSum(decodedBA);
bool checksum_valid = (checksum_calculated == checksum);
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--- " _CYAN_("Saflok Details"));
PrintAndLogEx(SUCCESS, "Key Level: %u (%s)", saflok_key_levels[key_level].level_num, saflok_key_levels[key_level].level_name);
PrintAndLogEx(SUCCESS, "LED Warning: %s", led_warning ? "Yes" : "No");
PrintAndLogEx(SUCCESS, "Key ID: %u (0x%02X)", key_id, key_id);
PrintAndLogEx(SUCCESS, "Key Record: %u (0x%04X)", key_record, key_record);
PrintAndLogEx(SUCCESS, "Opening Key: %s", opening_key ? "Yes" : "No");
PrintAndLogEx(SUCCESS, "Sequence Number & Combination: %u (0x%02X)", sequence_combination_number, sequence_combination_number);
PrintAndLogEx(SUCCESS, "Override Deadbolt: %s", override_deadbolt ? "Yes" : "No");
PrintAndLogEx(SUCCESS, "Restricted Weekdays: %s", restricted_weekday_string);
PrintAndLogEx(SUCCESS, "Property ID: %u (0x%04X)", property_id, property_id);
PrintAndLogEx(SUCCESS, "Creation Date: %04u-%02u-%02u %02u:%02u", creation_year, creation_month, creation_day, creation_hour, creation_minute);
PrintAndLogEx(SUCCESS, "Expiration Date: %04u-%02u-%02u %02u:%02u", expire_year, expire_month, expire_day, expiry_hour, expiry_minute);
PrintAndLogEx(SUCCESS, "Checksum Valid: %s", checksum_valid ? "Yes" : "No");
}
static int CmdHelp(const char *Cmd);
/*
@ -1915,9 +2210,13 @@ static int CmdHF14AMfNested(const char *Cmd) { //TODO: single mode broken? can't
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) {
continue;
}
if (resp.status != PM3_SUCCESS) continue;
if (resp.status != PM3_SUCCESS) {
continue;
}
uint8_t *data = resp.data.asBytes;
key64 = bytes_to_num(data + 10, 6);
@ -4005,9 +4304,13 @@ static int CmdHF14AMfChk(const char *Cmd) {
SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue;
if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500) == false) {
continue;
}
if (resp.status != PM3_SUCCESS) continue;
if (resp.status != PM3_SUCCESS) {
continue;
}
uint8_t *data = resp.data.asBytes;
key64 = bytes_to_num(data + 10, MIFARE_KEY_SIZE);
@ -4070,7 +4373,7 @@ out:
// Disable fast mode and send a dummy command to make it effective
g_conn.block_after_ACK = false;
SendCommandNG(CMD_PING, NULL, 0);
if (!WaitForResponseTimeout(CMD_PING, NULL, 1000)) {
if (WaitForResponseTimeout(CMD_PING, NULL, 1000) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
@ -6176,7 +6479,9 @@ static int CmdHF14AMfice(const char *Cmd) {
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_ACQ_NONCES, blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out;
if (WaitForResponseTimeout(CMD_ACK, &resp, 3000) == false) {
goto out;
}
if (resp.oldarg[0]) goto out;
uint32_t items = resp.oldarg[2];
@ -9879,8 +10184,9 @@ static int CmdHF14AMfInfo(const char *Cmd) {
PrintAndLogEx(SUCCESS, "unknown");
}
if (e_sector[1].foundKey[MF_KEY_A] && (e_sector[1].Key[MF_KEY_A] == 0x2A2C13CC242A)) {
if (keycnt > 1 && e_sector != NULL && e_sector[1].foundKey[MF_KEY_A] && (e_sector[1].Key[MF_KEY_A] == 0x2A2C13CC242A)) {
PrintAndLogEx(SUCCESS, "dormakaba Saflok detected");
ParseAndPrintSaflokData(&e_sector[0], &e_sector[1]);
}
} else {

View file

@ -4628,7 +4628,7 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
// we be getting ACK that we are silently ignoring here..
if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "Failed");
return PM3_ESOFT;
}
@ -4649,11 +4649,13 @@ static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
got_post = true;
}
}
if (! got_post) {
if (!got_post) {
PrintAndLogEx(FAILED, "Failed to read block BEFORE");
error_retries++;
continue; // try again
}
error_retries = 0;
char prestr[20] = {0};
snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
@ -4936,7 +4938,7 @@ static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
clearCommandBuffer();
PacketResponseNG resp;
SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "\ntear off command failed");
continue;
}

View file

@ -664,7 +664,7 @@ static int CmdHFTexkomReader(const char *Cmd) {
SendCommandNG(CMD_HF_ACQ_RAW_ADC, (uint8_t *)&samplesCount, sizeof(uint32_t));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_HF_ACQ_RAW_ADC, &resp, 2500)) {
if (WaitForResponseTimeout(CMD_HF_ACQ_RAW_ADC, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}

View file

@ -187,7 +187,7 @@ int CmdHfThinFilmSim(const char *Cmd) {
int ret;
while (!(ret = kbd_enter_pressed())) {
if (WaitForResponseTimeout(CMD_HF_THINFILM_SIMULATE, &resp, 500) == 0) {
if (WaitForResponseTimeout(CMD_HF_THINFILM_SIMULATE, &resp, 500) == false) {
continue;
}

View file

@ -928,15 +928,19 @@ static int CmdTune(const char *Cmd) {
SendCommandNG(CMD_MEASURE_ANTENNA_TUNING, NULL, 0);
PacketResponseNG resp;
PrintAndLogEx(INPLACE, "% 3i", timeout_max - timeout);
while (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING, &resp, 500)) {
while (WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING, &resp, 500) == false) {
fflush(stdout);
if (timeout >= timeout_max) {
PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting...");
return PM3_ETIMEOUT;
}
timeout++;
PrintAndLogEx(INPLACE, "% 3i", timeout_max - timeout);
}
PrintAndLogEx(NORMAL, "");
if (resp.status != PM3_SUCCESS) {
@ -1607,7 +1611,7 @@ void pm3_version_short(void) {
if (ptr != NULL) {
char *ptr_end = strstr(ptr, "\n");
if (ptr_end != NULL) {
uint8_t len = ptr_end - 19 - ptr;
uint8_t len = ptr_end - 12 - ptr;
PrintAndLogEx(NORMAL, " Bootrom... %.*s", len, ptr + 12);
}
}
@ -1617,7 +1621,7 @@ void pm3_version_short(void) {
if (ptr != NULL) {
char *ptr_end = strstr(ptr, "\n");
if (ptr_end != NULL) {
uint8_t len = ptr_end - 14 - ptr;
uint8_t len = ptr_end - 12 - ptr;
PrintAndLogEx(NORMAL, " OS........ %.*s", len, ptr + 12);
}
}

View file

@ -435,15 +435,17 @@ int CmdLFCommandRead(const char *Cmd) {
i = 10;
// 20sec wait loop
while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
while (WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) == false && i != 0) {
if (verbose) {
PrintAndLogEx(NORMAL, "." NOLF);
}
i--;
}
if (verbose) {
PrintAndLogEx(NORMAL, "");
}
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(WARNING, "command failed.");
return PM3_ESOFT;
@ -595,7 +597,7 @@ int lf_getconfig(sample_config *config) {
SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
@ -797,10 +799,12 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) {
payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples;
SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (is_trigger_threshold_set) {
WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
} else {
if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
if (WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "(lf_read) command execution time out");
return PM3_ETIMEOUT;
}

View file

@ -2013,7 +2013,7 @@ int CmdEM4x05Unlock(const char *Cmd) {
PrintAndLogEx(INFO, "----------------------------------------------------------------------------\n");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>'") " to exit");
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "--------------- " _CYAN_("start") " -----------------------\n");

View file

@ -466,7 +466,7 @@ int clone_t55xx_tag(uint32_t *blockdata, uint8_t numblocks) {
ng.flags = 0;
SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng));
if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT)) {
if (WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, T55XX_WRITE_TIMEOUT) == false) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
}
@ -664,7 +664,7 @@ int t55xxWrite(uint8_t block, bool page1, bool usepwd, bool testMode, uint32_t p
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_T55XX_WRITEBL, (uint8_t *)&ng, sizeof(ng));
if (!WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_LF_T55XX_WRITEBL, &resp, 2000) == false) {
PrintAndLogEx(ERR, "Error occurred, device did not ACK write operation.");
return PM3_ETIMEOUT;
}
@ -1992,7 +1992,7 @@ static int CmdT55xxDangerousRaw(const char *Cmd) {
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_LF_T55XX_DANGERRAW, (uint8_t *)&ng, sizeof(ng));
if (!WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_LF_T55XX_DANGERRAW, &resp, 2000) == false) {
PrintAndLogEx(ERR, "Error occurred, device did not ACK write operation.");
return PM3_ETIMEOUT;
}
@ -2840,7 +2840,7 @@ bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, u
clearCommandBuffer();
SendCommandNG(CMD_LF_T55XX_READBL, (uint8_t *)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_LF_T55XX_READBL, NULL, 2500)) {
if (WaitForResponseTimeout(CMD_LF_T55XX_READBL, NULL, 2500) == false) {
PrintAndLogEx(WARNING, "command execution time out");
return false;
}
@ -3435,7 +3435,7 @@ static int CmdT55xxChkPwds(const char *Cmd) {
PacketResponseNG resp;
uint8_t timeout = 0;
while (!WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000)) {
while (WaitForResponseTimeout(CMD_LF_T55XX_CHK_PWDS, &resp, 2000) == false) {
timeout++;
PrintAndLogEx(NORMAL, "." NOLF);
if (timeout > 180) {

View file

@ -172,7 +172,7 @@ static int CmdVikingClone(const char *Cmd) {
SendCommandNG(CMD_LF_VIKING_CLONE, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_LF_VIKING_CLONE, &resp, T55XX_WRITE_TIMEOUT)) {
if (WaitForResponseTimeout(CMD_LF_VIKING_CLONE, &resp, T55XX_WRITE_TIMEOUT) == false) {
PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
return PM3_ETIMEOUT;
}

View file

@ -663,7 +663,7 @@ static int CmdSmartUpgrade(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_SMART_UPLOAD, (uint8_t *)&upload, sizeof(upload));
if (!WaitForResponseTimeout(CMD_SMART_UPLOAD, &resp, 2000)) {
if (WaitForResponseTimeout(CMD_SMART_UPLOAD, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
free(firmware);
return PM3_ETIMEOUT;
@ -695,7 +695,7 @@ static int CmdSmartUpgrade(const char *Cmd) {
free(firmware);
SendCommandNG(CMD_SMART_UPGRADE, (uint8_t *)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_SMART_UPGRADE, &resp, 2500)) {
if (WaitForResponseTimeout(CMD_SMART_UPGRADE, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
return PM3_ETIMEOUT;
}
@ -876,7 +876,7 @@ static int CmdSmartSetClock(const char *Cmd) {
clearCommandBuffer();
SendCommandNG(CMD_SMART_SETCLOCK, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500)) {
if (WaitForResponseTimeout(CMD_SMART_SETCLOCK, &resp, 2500) == false) {
PrintAndLogEx(WARNING, "smart card select failed");
return PM3_ETIMEOUT;
}

View file

@ -35,7 +35,7 @@ static int usart_tx(uint8_t *data, size_t len) {
clearCommandBuffer();
SendCommandNG(CMD_USART_TX, data, len);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_USART_TX, &resp, 1000)) {
if (WaitForResponseTimeout(CMD_USART_TX, &resp, 1000) == false) {
return PM3_ETIMEOUT;
}
return resp.status;
@ -49,7 +49,7 @@ static int usart_rx(uint8_t *data, size_t *len, uint32_t waittime) {
payload.waittime = waittime;
SendCommandNG(CMD_USART_RX, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_USART_RX, &resp, waittime + 500)) {
if (WaitForResponseTimeout(CMD_USART_RX, &resp, waittime + 500) == false) {
return PM3_ETIMEOUT;
}
if (resp.status == PM3_SUCCESS) {
@ -99,7 +99,7 @@ static int set_usart_config(uint32_t baudrate, uint8_t parity) {
payload.parity = parity;
SendCommandNG(CMD_USART_CONFIG, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_USART_CONFIG, &resp, 1000)) {
if (WaitForResponseTimeout(CMD_USART_CONFIG, &resp, 1000) == false) {
return PM3_ETIMEOUT;
}
return resp.status;

View file

@ -871,7 +871,7 @@ int TestProxmark(pm3_device_t *dev) {
#endif
PacketResponseNG resp;
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == 0) {
if (WaitForResponseTimeoutW(CMD_PING, &resp, timeout, false) == false) {
return PM3_ETIMEOUT;
}
@ -881,7 +881,7 @@ int TestProxmark(pm3_device_t *dev) {
}
SendCommandNG(CMD_CAPABILITIES, NULL, 0);
if (WaitForResponseTimeoutW(CMD_CAPABILITIES, &resp, 1000, false) == 0) {
if (WaitForResponseTimeoutW(CMD_CAPABILITIES, &resp, 1000, false) == false) {
return PM3_ETIMEOUT;
}

View file

@ -303,7 +303,7 @@ static int l_GetFromFlashMemSpiffs(lua_State *L) {
// get size from spiffs itself !
SendCommandNG(CMD_SPIFFS_STAT, (uint8_t *)destfilename, 32);
PacketResponseNG resp;
if (!WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000))
if (WaitForResponseTimeout(CMD_SPIFFS_STAT, &resp, 2000) == false)
return returnToLuaWithError(L, "No response from the device");
len = resp.data.asDwords[0];

View file

@ -3285,15 +3285,14 @@
"command": "hf iclass creditepurse",
"description": "Credit the epurse on an iCLASS tag. The provided key must be the credit key. The first two bytes of the epurse are the debit value (big endian) and may be any value except FFFF. The remaining two bytes of the epurse are the credit value and must be smaller than the previous value.",
"notes": [
"hf iclass creditepurse -d FEFFFFFF -k 001122334455667B",
"hf iclass creditepurse -d FEFFFFFF --ki 0"
"hf iclass creditepurse --ki 0 -d FEFFFEFF"
],
"offline": false,
"options": [
"-h, --help This help",
"-k, --key <hex> Credit key as 8 hex bytes",
"--ki <dec> Key index to select key from memory 'hf iclass managekeys'",
"-d, --data <hex> data to write as 8 hex bytes",
"-d, --data <hex> data to write as 4 hex bytes",
"--elite elite computations applied to key",
"--raw no computations applied to key",
"-v, --verbose verbose output",
@ -3719,7 +3718,7 @@
},
"hf iclass tear": {
"command": "hf iclass tear",
"description": "Tear off an iCLASS tag block e-purse usually 300-500us to trigger the erase phase also seen 1800-2100us on some cards",
"description": "Tear off an iCLASS tag block e-purse usually 300-500us to trigger the erase phase also seen 1800-2100us on some cards Make sure you know the target card credit key. Typical `--ki 1` or `--ki 3`",
"notes": [
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA -k 001122334455667B -s 300 -e 600",
"hf iclass tear --blk 10 -d AAAAAAAAAAAAAAAA --ki 0 -s 300 -e 600",
@ -3739,12 +3738,13 @@
"--nr replay of NR/MAC",
"-v, --verbose verbose output",
"--shallow use shallow (ASK) reader modulation instead of OOK",
"-s <dec> tearoff delay start (in us) must be between 1 and 43000 (43ms). Precision is about 1/3us.",
"-i <dec> tearoff delay increment (in us) - default 10.",
"-e <dec> tearoff delay end (in us) must be a higher value than the start delay.",
"--loop <dec> number of times to loop per tearoff time."
"-s <dec> tearoff delay start (in us) must be between 1 and 43000 (43ms). Precision is about 1/3 us",
"-i <dec> tearoff delay increment (in us) - default 10",
"-e <dec> tearoff delay end (in us) must be a higher value than the start delay",
"--loop <dec> number of times to loop per tearoff time",
"--sleep <ms> Sleep between each tear"
],
"usage": "hf iclass tear [-hv] [-k <hex>] [--ki <dec>] --blk <dec> -d <hex> [-m <hex>] [--credit] [--elite] [--raw] [--nr] [--shallow] -s <dec> [-i <dec>] [-e <dec>] [--loop <dec>]"
"usage": "hf iclass tear [-hv] [-k <hex>] [--ki <dec>] --blk <dec> -d <hex> [-m <hex>] [--credit] [--elite] [--raw] [--nr] [--shallow] -s <dec> [-i <dec>] [-e <dec>] [--loop <dec>] [--sleep <ms>]"
},
"hf iclass unhash": {
"command": "hf iclass unhash",
@ -13371,6 +13371,6 @@
"metadata": {
"commands_extracted": 768,
"extracted_by": "PM3Help2JSON v1.00",
"extracted_on": "2025-05-24T14:16:42"
"extracted_on": "2025-05-27T08:11:15"
}
}