diff --git a/CHANGELOG.md b/CHANGELOG.md index 19799efcd..5a20f8bf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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] +- Added `-t` / `--timeout` option for `hf 15 sim` (@recursivenomad) - Added `--aid` parameter to `hf seos` commands (@kormax) - Added `hf iclass blacktears` command to perform an automated tearoff of block 1 to set non-secure page mode(@antiklesys) - Changed wiegand encoding to use shared helpers and have unified parameters (--raw, --bin, --new, --wiegand, etc.) (@cindersocket) diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 1c3d01f7c..4f61912df 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1643,7 +1643,11 @@ void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t *start_ */ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *response_byte, uint16_t *responselen) { - uint8_t real_cmd[msg_len + 4]; + if (msg_len > PM3_CMD_DATA_SIZE) { + return PM3_EINVARG; + } + + uint8_t real_cmd[PM3_CMD_DATA_SIZE + 4]; if (msg_len) { // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 @@ -3096,8 +3100,10 @@ void SendRawCommand14443B(iso14b_raw_cmd_t *p) { set_tracing(true); - // receive buffer - uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00}; + // receive buffer — sized for APDU response header + max payload, reused for all paths + uint8_t buf[sizeof(iso14b_raw_apdu_response_t) + PM3_CMD_DATA_SIZE]; + memset(buf, 0, sizeof(buf)); + iso14b_raw_apdu_response_t *payload = (iso14b_raw_apdu_response_t *)buf; int status = 0; uint32_t sendlen = sizeof(iso14b_card_select_t); @@ -3159,17 +3165,14 @@ void SendRawCommand14443B(iso14b_raw_cmd_t *p) { uint16_t responselen = 0; uint8_t response_byte = 0; bool chaining = ((p->flags & ISO14B_SEND_CHAINING) == ISO14B_SEND_CHAINING); - status = iso14443b_apdu(p->raw, p->rawlen, chaining, buf, sizeof(buf), &response_byte, &responselen); + status = iso14443b_apdu(p->raw, p->rawlen, chaining, payload->data, PM3_CMD_DATA_SIZE, &response_byte, &responselen); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred reply_ng(CMD_HF_ISO14443B_COMMAND, PM3_ETEAROFF, NULL, 0); } else { - uint8_t packet[responselen + 1 + 2]; - iso14b_raw_apdu_response_t *payload = (iso14b_raw_apdu_response_t *)packet; payload->response_byte = response_byte; payload->datalen = responselen; - memcpy(payload->data, buf, payload->datalen); - reply_ng(CMD_HF_ISO14443B_COMMAND, status, packet, sizeof(packet)); + reply_ng(CMD_HF_ISO14443B_COMMAND, status, buf, sizeof(iso14b_raw_apdu_response_t) + responselen); } } @@ -3198,7 +3201,7 @@ void SendRawCommand14443B(iso14b_raw_cmd_t *p) { eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; uint16_t retlen = 0; - status = Get14443bAnswerFromTag(buf, sizeof(buf), s_iso14b_timeout, &eof_time, &retlen); + status = Get14443bAnswerFromTag(buf, PM3_CMD_DATA_SIZE, s_iso14b_timeout, &eof_time, &retlen); if (status == PM3_SUCCESS) { sendlen = MIN(retlen, PM3_CMD_DATA_SIZE); reply_ng(CMD_HF_ISO14443B_COMMAND, status, Demod.output, sendlen); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index e3bf38d73..a9386a917 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -86,7 +86,11 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { // send X byte basic commands uint16_t mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint16_t answer_len, uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[data_size + 3]; + if (data_size > 32) { + return 0; + } + + uint8_t dcmd[32 + 3]; dcmd[0] = cmd; if (data_size > 0) { memcpy(dcmd + 1, data, data_size); @@ -99,8 +103,9 @@ uint16_t mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t * } uint16_t len = ReaderReceive(answer, answer_len, answer_parity); if (len == 0) { - if (g_dbglevel >= DBG_ERROR) + if (g_dbglevel >= DBG_ERROR) { Dbprintf("%02X Cmd failed. Card timeout.", cmd); + } len = ReaderReceive(answer, answer_len, answer_parity); } return len; @@ -109,7 +114,11 @@ uint16_t mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t * // send X byte basic commands secure channel (UL AES) uint16_t mifare_sendcmd_schann(uint8_t *data, uint8_t data_size, uint8_t *answer, uint16_t answer_len, uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[data_size + 2]; + if (data_size > 16) { + return 0; + } + + uint8_t dcmd[16 + 2]; memset(dcmd, 0, sizeof(dcmd)); if (data_size > 0) { @@ -149,6 +158,7 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t } else { ReaderTransmit(dcmd, sizeof(dcmd), timing); } + if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred return 0; } @@ -160,6 +170,7 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t } if (pcs && (crypted == CRYPT_ALL)) { + if (len == 1) { uint16_t res = 0; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0; @@ -167,7 +178,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; answer[0] = res; + } else { + for (pos = 0; pos < len; pos++) { answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; } diff --git a/armsrc/seos.c b/armsrc/seos.c index 520cf6d65..f56f632df 100644 --- a/armsrc/seos.c +++ b/armsrc/seos.c @@ -795,6 +795,11 @@ void SimulateSeos(seos_emulate_req_t *msg) { } uint8_t cmac_size = recvd_cmac_length; + if (cmac_size > 16) { + Dbprintf(_RED_("Get Data failed") ": CMAC size invalid."); + break; + } + if (!generate_cmac(diver_cmac_key, mac_input, mac_input_idx, cmac, msg->encr_alg)) { Dbprintf(_RED_("Get Data failed") ": Failed to create reply CMAC."); break; diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 2637ce8e7..93d44bffc 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1489,6 +1489,7 @@ static int CmdHF15Sim(const char *Cmd) { arg_param_begin, arg_str0("u", "uid", "", "UID, 8 hex bytes"), arg_int0("b", "blocksize", "", "block size (def 4)"), + arg_int0("t", "timeout", "", "timeout in ms (def -1, ie. until button press)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -1502,6 +1503,7 @@ static int CmdHF15Sim(const char *Cmd) { int uidlen = 0; CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen); payload.block_size = arg_get_int_def(ctx, 2, 4); + size_t timeout = arg_get_int_def(ctx, 3, -1); CLIParserFree(ctx); // sanity checks @@ -1541,7 +1543,10 @@ static int CmdHF15Sim(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_SIMULATE, (uint8_t *)&payload, sizeof(payload)); - WaitForResponse(CMD_HF_ISO15693_SIMULATE, &resp); + WaitForResponseTimeout(CMD_HF_ISO15693_SIMULATE, &resp, timeout); + if (timeout != (size_t) - 1) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + } PrintAndLogEx(INFO, "Done!"); return PM3_SUCCESS; }