From 70b4bee761e2d20c014f442a383167b1cbc18511 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 16 Jan 2024 11:37:13 +0100 Subject: [PATCH] reworked the 14B comms. Uses NG packets now. Most raw / apdu / write / rd got some love --- CHANGELOG.md | 1 + armsrc/appmain.c | 2 +- armsrc/iso14443b.c | 185 ++++----- armsrc/iso14443b.h | 5 +- client/src/cmdhf14b.c | 677 ++++++++++++++++--------------- client/src/cmdhfemrtd.c | 8 +- client/src/iso7816/iso7816core.c | 44 +- 7 files changed, 458 insertions(+), 464 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6263aca2..4a53be3e8 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] + - Changed `hf 14b *` - worked apdu and comms. Improved output. Uses NG packets (@iceman1001) - Fixed `data manrawdecode` - now copy to demodbuf even if em4100 decode fails (@iceman1001) - Changed `nfc decode` - now supports Android Managed Provision NDEF message decoding (@iceman1001) - Changed `hf_cardhopper` - Allow button presses to break, handle non-zero CID from reader by relaying RATS and improving PPS and WTX handling, more reliably cook ATS, ignore client packets on serial line (@nvx) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ff96d95a2..1e4a1ca15 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1455,7 +1455,7 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_HF_ISO14443B_COMMAND: { iso14b_raw_cmd_t *payload = (iso14b_raw_cmd_t *)packet->data.asBytes; - SendRawCommand14443B_Ex(payload); + SendRawCommand14443B(payload); break; } case CMD_HF_CRYPTORF_SIM : { diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 49d4320b8..ad2cff161 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -111,9 +111,6 @@ * */ - - - #ifndef MAX_14B_TIMEOUT // FWT(max) = 4949 ms or 4.95 seconds. // SSP_CLK = 4949000 * 3.39 = 16777120 @@ -195,9 +192,9 @@ static void iso14b_set_maxframesize(uint16_t size); static void iso14b_set_fwt(uint8_t fwt); // the block number for the ISO14443-4 PCB (used with APDUs) -static uint8_t iso14b_pcb_blocknum = 0; -static uint8_t iso14b_fwt = 9; -static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; +static uint8_t s_iso14b_pcb_blocknum = 0; +static uint8_t s_iso14b_fwt = 9; +static uint32_t s_iso14b_timeout = MAX_14B_TIMEOUT; /* * ISO 14443-B communications @@ -350,7 +347,6 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; // them yet, just leaves them ready to send in ToSend[]. //----------------------------------------------------------------------------- static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { - int i; tosend_reset(); @@ -362,6 +358,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // 80/fs < TR1 < 200/fs // 10 ETU < TR1 < 24 ETU + int i; // Send TR1. // 10-11 ETU * 4times samples ONES for (i = 0; i < 10; i++) { @@ -458,15 +455,18 @@ static void iso14b_set_timeout(uint32_t timeout_etu) { ssp = MAX_14B_TIMEOUT; } - iso14b_timeout = ssp; + s_iso14b_timeout = ssp; if (g_dbglevel >= DBG_DEBUG) { - Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout); + Dbprintf("ISO14443B Timeout set to %ld fwt", s_iso14b_timeout); } } // keep track of FWT, also updates the timeout static void iso14b_set_fwt(uint8_t fwt) { - iso14b_fwt = fwt; + s_iso14b_fwt = fwt; + if (g_dbglevel >= DBG_DEBUG) { + Dbprintf("ISO14443B FWT Timeout set to %ld fwt", s_iso14b_fwt); + } iso14b_set_timeout(32 << fwt); } @@ -1323,6 +1323,9 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t // The DMA buffer, used to stream samples from the FPGA dmabuf16_t *dma = get_dma16(); + if (dma == NULL) { + return PM3_EMALLOC; + } if (FpgaSetupSscDma((uint8_t *) dma->buf, DMA_BUFFER_SIZE) == false) { if (g_dbglevel > DBG_ERROR) Dbprintf("FpgaSetupSscDma failed. Exiting"); @@ -1407,9 +1410,10 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t if (Demod.len > 0) { uint32_t sof_time = *eof_time - HF14_ETU_TO_SSP( (Demod.len * (8 + 2)) // time for byte transfers -// + (10) // time for TR1 + (10 + 2) // time for SOF transfer - + (10)); // time for EOF transfer + + (10) // time for EOF transfer + ) + ; LogTrace(Demod.output, Demod.len, sof_time, *eof_time, NULL, false); } @@ -1583,7 +1587,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len, uint32_t /* Sends an APDU to the tag * TODO: check CRC and preamble */ -int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res, int *reponselen) { +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 *reponselen) { uint8_t real_cmd[msg_len + 4]; @@ -1596,12 +1600,12 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void } // put block number into the PCB - real_cmd[0] |= iso14b_pcb_blocknum; + real_cmd[0] |= s_iso14b_pcb_blocknum; memcpy(real_cmd + 1, msg, msg_len); } else { // R-block. ACK real_cmd[0] = 0xA2; // r-block + ACK - real_cmd[0] |= iso14b_pcb_blocknum; + real_cmd[0] |= s_iso14b_pcb_blocknum; } AddCrc14B(real_cmd, msg_len + 1); @@ -1618,26 +1622,25 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void // SSP_CLK = 4833 µS * 3.39 = 16384 uint16_t len = 0; - if (Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time, &len) != PM3_SUCCESS) { - return PM3_ECARDEXCHANGE; + int status = Get14443bAnswerFromTag(rxdata, rxmaxlen, s_iso14b_timeout, &eof_time, &len); + if (status != PM3_SUCCESS) { + return status; } - FpgaDisableTracing(); - uint8_t *data_bytes = (uint8_t *) rxdata; if (len) { // S-Block WTX while (len && ((data_bytes[0] & 0xF2) == 0xF2)) { - uint32_t save_iso14b_timeout_spp = iso14b_timeout; + uint32_t save_iso14b_timeout_spp = s_iso14b_timeout; // 2 high bits mandatory set to 0b // byte1 - WTXM [1..59]. uint8_t wtxm = data_bytes[1] & 0x3F; // command FWT = FWT * WTXM - uint32_t fwt_temp = iso14b_fwt * wtxm; + uint32_t fwt_temp = (s_iso14b_fwt * wtxm); // temporarily increase timeout iso14b_set_timeout((32 << fwt_temp)); @@ -1654,16 +1657,14 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void // retrieve the result again (with increased timeout) eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time, &len) != PM3_SUCCESS) { - FpgaDisableTracing(); + if (Get14443bAnswerFromTag(rxdata, rxmaxlen, s_iso14b_timeout, &eof_time, &len) != PM3_SUCCESS) { return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); data_bytes = rxdata; // restore timeout - iso14b_timeout = save_iso14b_timeout_spp; + s_iso14b_timeout = save_iso14b_timeout_spp; } // if we received an I- or R(ACK)-Block with a block number equal to the @@ -1671,23 +1672,25 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void if ((len >= 3) && // PCB + CRC = 3 bytes (((data_bytes[0] & 0xC0) == 0) || (data_bytes[0] & 0xD0) == 0x80) && // I-Block OR R-Block with ACK bit set to 0 - ((data_bytes[0] & 0x01) == iso14b_pcb_blocknum)) { // equal block numbers + ((data_bytes[0] & 0x01) == s_iso14b_pcb_blocknum)) { // equal block numbers - iso14b_pcb_blocknum ^= 1; + s_iso14b_pcb_blocknum ^= 1; } // if we received I-block with chaining we need to send ACK and receive another block of data - if (res) { - *res = data_bytes[0]; + if (response_byte) { + *response_byte = data_bytes[0]; } // crc check if (len >= 3 && (check_crc(CRC_14443_B, data_bytes, len) == false)) { return PM3_ECRC; } + } // cut frame byte + if (len) { len -= 1; for (int i = 0; i < len; i++) { @@ -1722,12 +1725,10 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; uint16_t retlen = 0; - if (Get14443bAnswerFromTag(r, sizeof(r), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r, sizeof(r), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); - if (retlen != 4) { return PM3_ELENGTH; } @@ -1745,10 +1746,9 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { CodeAndTransmit14443bAsReader(cmdMSBUID, sizeof(cmdMSBUID), &start_time, &eof_time, true); eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(r, sizeof(r), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r, sizeof(r), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); if (retlen != 4) { return PM3_ELENGTH; @@ -1765,10 +1765,9 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { CodeAndTransmit14443bAsReader(cmdLSBUID, sizeof(cmdLSBUID), &start_time, &eof_time, true); eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(r, sizeof(r), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r, sizeof(r), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); if (retlen != 4) { return PM3_ELENGTH; @@ -1782,9 +1781,6 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { } return PM3_SUCCESS; -out: - FpgaDisableTracing(); - return PM3_ECARDEXCHANGE; } /** * SRx Initialise. @@ -1802,11 +1798,9 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) { eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; uint16_t retlen = 0; - if (Get14443bAnswerFromTag(r_init, sizeof(r_init), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - FpgaDisableTracing(); + if (Get14443bAnswerFromTag(r_init, sizeof(r_init), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); // Randomly generated Chip ID if (card) { @@ -1823,12 +1817,10 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx), &start_time, &eof_time, true); eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(r_select, sizeof(r_select), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r_select, sizeof(r_select), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); - if (retlen != 3) { return PM3_ELENGTH; } @@ -1850,12 +1842,10 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(select_srx, 3, &start_time, &eof_time, true); // Only first three bytes for this one eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(r_papid, sizeof(r_papid), iso14b_timeout, &eof_time, & retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r_papid, sizeof(r_papid), s_iso14b_timeout, &eof_time, & retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); - if (retlen != 10) { return PM3_ELENGTH; } @@ -1869,9 +1859,6 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) { memcpy(card->uid, r_papid, 8); } return PM3_SUCCESS; -out: - FpgaDisableTracing(); - return PM3_ECARDEXCHANGE; } // Xerox tag connect function: wup, anticoll, attrib, password @@ -1907,12 +1894,11 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { for (slot = 0; slot < 4; slot++) { start_time = eof_time + HF14_ETU_TO_SSP(30); //(24); // next slot after 24 ETU - if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { if (retlen > 0) { Dbprintf("unexpected data %d", retlen); - Dbprintf("crc %s", check_crc(CRC_14443_B, x_atqb, retlen) ? "OK" : "BAD"); } - goto out; + return PM3_ECARDEXCHANGE; } // tx unframed slot-marker @@ -1930,8 +1916,6 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { } if (4 == slot) { - FpgaDisableTracing(); - if (g_dbglevel >= DBG_DEBUG) { DbpString("no answer to anticollision"); } @@ -1939,8 +1923,8 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { } } - if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } if (g_dbglevel >= DBG_DEBUG) { @@ -1984,10 +1968,9 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(txbuf + 1, 15, &start_time, &eof_time, true); eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); if (retlen < 3) { return PM3_ELENGTH; @@ -2018,8 +2001,8 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(txbuf, 17, &start_time, &eof_time, true); eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } if (retlen < 4) { @@ -2035,10 +2018,6 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { } return PM3_SUCCESS; - -out: - FpgaDisableTracing(); - return PM3_ECARDEXCHANGE; } /* Perform the ISO 14443 B Card Selection procedure @@ -2066,12 +2045,10 @@ int iso14443b_select_card(iso14b_card_select_t *card) { eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; uint16_t retlen = 0; - if (Get14443bAnswerFromTag(r_pupid, sizeof(r_pupid), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r_pupid, sizeof(r_pupid), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); - // ATQB too short? if (retlen < 14) { return PM3_ELENGTH; @@ -2098,10 +2075,9 @@ int iso14443b_select_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(attrib, sizeof(attrib), &start_time, &eof_time, true); eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; - if (Get14443bAnswerFromTag(r_attrib, sizeof(r_attrib), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - goto out; + if (Get14443bAnswerFromTag(r_attrib, sizeof(r_attrib), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { + return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); // Answer to ATTRIB too short? if (retlen < 3) { @@ -2135,12 +2111,8 @@ int iso14443b_select_card(iso14b_card_select_t *card) { } } // reset PCB block number - iso14b_pcb_blocknum = 0; + s_iso14b_pcb_blocknum = 0; return PM3_SUCCESS; - -out: - FpgaDisableTracing(); - return PM3_ECARDEXCHANGE; } // Set up ISO 14443 Type B communication (similar to iso14443a_setup) @@ -2194,7 +2166,6 @@ void iso14443b_setup(void) { //----------------------------------------------------------------------------- static int read_14b_srx_block(uint8_t blocknr, uint8_t *block) { -// iceman: todo add static CRC uint8_t cmd[] = {ISO14443B_READ_BLK, blocknr, 0x00, 0x00}; AddCrc14B(cmd, 2); @@ -2206,20 +2177,16 @@ static int read_14b_srx_block(uint8_t blocknr, uint8_t *block) { eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; uint16_t retlen = 0; - if (Get14443bAnswerFromTag(r_block, sizeof(r_block), iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { - FpgaDisableTracing(); + if (Get14443bAnswerFromTag(r_block, sizeof(r_block), s_iso14b_timeout, &eof_time, &retlen) != PM3_SUCCESS) { return PM3_ECARDEXCHANGE; } - FpgaDisableTracing(); // Check if we got an answer from the tag if (retlen != 6) { - Dbprintf("expected 6 bytes from tag, got %u", retlen); return PM3_EWRONGANSWER; } // The check the CRC of the answer if (check_crc(CRC_14443_B, r_block, retlen) == false) { - DbpString("CRC fail"); return PM3_ECRC; } @@ -2227,14 +2194,6 @@ static int read_14b_srx_block(uint8_t blocknr, uint8_t *block) { memcpy(block, r_block, ISO14B_BLOCK_SIZE); } - if (g_dbglevel >= DBG_DEBUG) { - Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", - blocknr, - (r_block[3] << 24) + (r_block[2] << 16) + (r_block[1] << 8) + r_block[0], - (r_block[4] << 8) + r_block[5] - ); - } - return PM3_SUCCESS; } @@ -2457,7 +2416,7 @@ static void iso14b_set_trigger(bool enable) { g_trigger = enable; } -void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) { +void SendRawCommand14443B(iso14b_raw_cmd_t *p) { // turn on trigger (LED_A) if ((p->flags & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) { @@ -2517,46 +2476,42 @@ void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) { if ((p->flags & ISO14B_APDU) == ISO14B_APDU) { - int responselen = 0; + uint16_t responselen = 0; uint8_t response_byte = 0; - status = iso14443b_apdu(p->raw, p->rawlen, (p->flags & ISO14B_SEND_CHAINING), buf, sizeof(buf), &response_byte, &responselen); + bool chaining = ((p->flags & ISO14B_SEND_CHAINING) == ISO14B_SEND_CHAINING); + status = iso14443b_apdu(p->raw, p->rawlen, chaining, buf, sizeof(buf), &response_byte, &responselen); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred reply_ng(CMD_HF_ISO14443B_COMMAND, PM3_ETEAROFF, NULL, 0); } else { - responselen = MIN(responselen, PM3_CMD_DATA_SIZE); - - iso14b_raw_apdu_response_t *payload = (iso14b_raw_apdu_response_t *)BigBuf_calloc(sizeof(iso14b_raw_apdu_response_t) + responselen); + 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, (uint8_t *)payload, sizeof(iso14b_raw_apdu_response_t) + responselen); - BigBuf_free_keep_EM(); + reply_ng(CMD_HF_ISO14443B_COMMAND, status, packet, sizeof(packet)); } } if ((p->flags & ISO14B_RAW) == ISO14B_RAW) { - uint8_t *raw = BigBuf_calloc(p->rawlen + 2); - memcpy(raw, p->raw, p->rawlen); - if ( - ((p->flags & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) && (p->rawlen)) { - AddCrc14B(raw, p->rawlen); + if (((p->flags & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) && (p->rawlen)) { + AddCrc14B(p->raw, p->rawlen); p->rawlen += 2; } uint32_t start_time = 0; uint32_t eof_time = 0; - CodeAndTransmit14443bAsReader(raw, p->rawlen, &start_time, &eof_time, true); + CodeAndTransmit14443bAsReader(p->raw, p->rawlen, &start_time, &eof_time, true); - FpgaDisableTracing(); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred reply_ng(CMD_HF_ISO14443B_COMMAND, PM3_ETEAROFF, NULL, 0); } else { + eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; + uint16_t retlen = 0; - status = Get14443bAnswerFromTag(buf, sizeof(buf), iso14b_timeout, &eof_time, &retlen); + status = Get14443bAnswerFromTag(buf, sizeof(buf), 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/iso14443b.h b/armsrc/iso14443b.h index fab9c3455..c737a369d 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -35,7 +35,7 @@ #endif void iso14443b_setup(void); -int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res, int *responselen); +int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res, uint16_t * responselen); int iso14443b_select_card(iso14b_card_select_t *card); @@ -43,8 +43,7 @@ void SimulateIso14443bTag(const uint8_t *pupi); void AcquireRawAdcSamplesIso14443b(uint32_t parameter); void read_14b_st_block(uint8_t blocknr); void SniffIso14443b(void); -void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); -void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p); +void SendRawCommand14443B(iso14b_raw_cmd_t *p); // States for 14B SIM command #define SIM_NOFIELD 0 diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 473e4f5cd..04a34ee63 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -295,226 +295,6 @@ static bool wait_cmd_14b(bool verbose, bool is_select, uint32_t timeout) { return true; } -static int CmdHF14BList(const char *Cmd) { - return CmdTraceListAlias(Cmd, "hf 14b", "14b -c"); -} - -static int CmdHF14BSim(const char *Cmd) { - - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf 14b sim", - "Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI", - "hf 14b sim -u 11AA33BB" - ); - - void *argtable[] = { - arg_param_begin, - arg_str1("u", "uid", "hex", "4byte UID/PUPI"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - - uint8_t pupi[4]; - int n = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n); - CLIParserFree(ctx); - - if (res) { - PrintAndLogEx(FAILED, "failed to read pupi"); - return PM3_EINVARG; - } - - PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi))); - PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation"); - clearCommandBuffer(); - SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi)); - return PM3_SUCCESS; -} - -static int CmdHF14BSniff(const char *Cmd) { - - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf 14b sniff", - "Sniff the communication reader and tag", - "hf 14b sniff" - ); - - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - - PacketResponseNG resp; - clearCommandBuffer(); - SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); - - WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp); - - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing"); - return PM3_SUCCESS; -} - -static int CmdHF14BCmdRaw(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf 14b raw", - "Sends raw bytes to card", - "hf 14b raw -cks --data 0200a40400 -> standard select, apdu 0200a4000 (7816)\n" - "hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n" - "hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n" - ); - - void *argtable[] = { - arg_param_begin, - arg_lit0("k", "keep", "leave the signal field ON after receive response"), - arg_lit0("s", "std", "activate field, use ISO14B select"), - arg_lit0(NULL, "sr", "activate field, use SRx ST select"), - arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"), - arg_lit0(NULL, "xrx", "activate field, use Fuji/Xerox select"), - arg_lit0("c", "crc", "calculate and append CRC"), - arg_lit0("r", NULL, "do not read response from card"), - arg_int0("t", "timeout", "", "timeout in ms"), - arg_lit0("v", "verbose", "verbose output"), - arg_str0("d", "data", "", "data, bytes to send"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - - bool keep_field_on = arg_get_lit(ctx, 1); - bool select_std = arg_get_lit(ctx, 2); - bool select_sr = arg_get_lit(ctx, 3); - bool select_cts = arg_get_lit(ctx, 4); - bool select_xrx = arg_get_lit(ctx, 5); - bool add_crc = arg_get_lit(ctx, 6); - bool read_reply = (arg_get_lit(ctx, 7) == false); - int user_timeout = arg_get_int_def(ctx, 8, -1); - bool verbose = arg_get_lit(ctx, 9); - - uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; - int datalen = 0; - int res = CLIParamHexToBuf(arg_get_str(ctx, 10), data, sizeof(data), &datalen); - if (res && verbose) { - PrintAndLogEx(INFO, "called with no raw bytes"); - } - CLIParserFree(ctx); - - // FLAGS for device side - uint32_t flags = ISO14B_CONNECT; - if (add_crc) { - flags |= ISO14B_APPEND_CRC; - } - - if (select_std) { - flags |= (ISO14B_SELECT_STD | ISO14B_CLEARTRACE); - if (verbose) { - PrintAndLogEx(INFO, "using ISO14443-B select"); - } - } else if (select_sr) { - flags |= (ISO14B_SELECT_SR | ISO14B_CLEARTRACE); - if (verbose) { - PrintAndLogEx(INFO, "using ST/SRx select"); - } - } else if (select_cts) { - flags |= (ISO14B_SELECT_CTS | ISO14B_CLEARTRACE); - if (verbose) { - PrintAndLogEx(INFO, "using ASK/C-ticket select"); - } - } else if (select_xrx) { - flags |= (ISO14B_SELECT_XRX | ISO14B_CLEARTRACE); - if (verbose) { - PrintAndLogEx(INFO, "using Fuji/Xerox select"); - } - } - - uint32_t time_wait = 0; - if (user_timeout > 0) { - - flags |= ISO14B_SET_TIMEOUT; - - if (user_timeout > MAX_14B_TIMEOUT_MS) { - user_timeout = MAX_14B_TIMEOUT_MS; - PrintAndLogEx(INFO, "set timeout to 4.9 seconds. The max we can wait for response"); - } - - // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) - time_wait = (uint32_t)((13560 / 128) * user_timeout); - if (verbose) - PrintAndLogEx(INFO, " new raw timeout : %u ETU ( %u ms )", time_wait, user_timeout); - } - - if (keep_field_on == false) { - flags |= ISO14B_DISCONNECT; - } - - if (datalen > 0) { - flags |= ISO14B_RAW; - } - - // Max buffer is PM3_CMD_DATA_SIZE - datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; - - - iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + datalen); - if (packet == NULL) { - PrintAndLogEx(FAILED, "failed to allocate memory"); - return PM3_EMALLOC; - } - - packet->flags = flags; - packet->timeout = time_wait; - packet->rawlen = datalen; - memcpy(packet->raw, data, datalen); - - clearCommandBuffer(); - SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); - free(packet); - - if (read_reply == false) { - clearCommandBuffer(); - return PM3_SUCCESS; - } - - bool success = true; - - // Select, device will send back iso14b_card_select_t, don't print it. - if (select_std) { - success = wait_cmd_14b(verbose, true, user_timeout); - if (verbose && success) { - PrintAndLogEx(SUCCESS, "Got response for standard select"); - } - } - - if (select_sr) { - success = wait_cmd_14b(verbose, true, user_timeout); - if (verbose && success) { - PrintAndLogEx(SUCCESS, "Got response for ST/SRx select"); - } - } - - if (select_cts) { - success = wait_cmd_14b(verbose, true, user_timeout); - if (verbose && success) { - PrintAndLogEx(SUCCESS, "Got response for ASK/C-ticket select"); - } - } - - if (select_xrx) { - success = wait_cmd_14b(verbose, true, user_timeout); - if (verbose && success) { - PrintAndLogEx(SUCCESS, "Got response for Fuji/Xerox select"); - } - } - - // get back response from the raw bytes you sent. - if (success && datalen > 0) { - wait_cmd_14b(true, false, user_timeout); - } - - return PM3_SUCCESS; -} - static bool get_14b_UID(uint8_t *d, iso14b_type_t *found_type) { // sanity checks @@ -579,6 +359,30 @@ static bool get_14b_UID(uint8_t *d, iso14b_type_t *found_type) { return false; } +/* extract uid from filename + * filename must match '^hf-14b-[0-9A-F]{16}' + */ +uint8_t *get_uid_from_filename(const char *filename) { + static uint8_t uid[8] ; + memset(uid, 0, 8) ; + char uidinhex[17] ; + if (strlen(filename) < 23 || strncmp(filename, "hf-14b-", 7)) { + PrintAndLogEx(ERR, "can't get uid from filename '%s'. Expected format is hf-14b-...", filename); + return uid ; + } + // extract uid part from filename + strncpy(uidinhex, filename + 7, 16) ; + uidinhex[16] = '\0' ; + int len = hex_to_bytes(uidinhex, uid, 8); + if (len == 8) + return SwapEndian64(uid, 8, 8); + else { + PrintAndLogEx(ERR, "get_uid_from_filename failed: hex_to_bytes returned %d", len); + memset(uid, 0, 8); + } + return uid ; +} + // print full atqb info // bytes // 0,1,2,3 = application data @@ -979,6 +783,225 @@ static void print_sr_blocks(uint8_t *data, size_t len, const uint8_t *uid) { // 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c]) // 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c]) +static int CmdHF14BList(const char *Cmd) { + return CmdTraceListAlias(Cmd, "hf 14b", "14b -c"); +} + +static int CmdHF14BSim(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14b sim", + "Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI", + "hf 14b sim -u 11AA33BB" + ); + + void *argtable[] = { + arg_param_begin, + arg_str1("u", "uid", "hex", "4byte UID/PUPI"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + uint8_t pupi[4]; + int n = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 1), pupi, sizeof(pupi), &n); + CLIParserFree(ctx); + + if (res) { + PrintAndLogEx(FAILED, "failed to read pupi"); + return PM3_EINVARG; + } + + PrintAndLogEx(INFO, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi, sizeof(pupi))); + PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation"); + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO14443B_SIMULATE, pupi, sizeof(pupi)); + return PM3_SUCCESS; +} + +static int CmdHF14BSniff(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14b sniff", + "Sniff the communication reader and tag", + "hf 14b sniff" + ); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); + + WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp); + + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing"); + return PM3_SUCCESS; +} + +static int CmdHF14BCmdRaw(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14b raw", + "Sends raw bytes to card", + "hf 14b raw -cks --data 0200a40400 -> standard select, apdu 0200a4000 (7816)\n" + "hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n" + "hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("k", "keep", "leave the signal field ON after receive response"), + arg_lit0("s", "std", "activate field, use ISO14B select"), + arg_lit0(NULL, "sr", "activate field, use SRx ST select"), + arg_lit0(NULL, "cts", "activate field, use ASK C-ticket select"), + arg_lit0(NULL, "xrx", "activate field, use Fuji/Xerox select"), + arg_lit0("c", "crc", "calculate and append CRC"), + arg_lit0("r", NULL, "do not read response from card"), + arg_int0("t", "timeout", "", "timeout in ms"), + arg_lit0("v", "verbose", "verbose output"), + arg_str0("d", "data", "", "data, bytes to send"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool keep_field_on = arg_get_lit(ctx, 1); + bool select_std = arg_get_lit(ctx, 2); + bool select_sr = arg_get_lit(ctx, 3); + bool select_cts = arg_get_lit(ctx, 4); + bool select_xrx = arg_get_lit(ctx, 5); + bool add_crc = arg_get_lit(ctx, 6); + bool read_reply = (arg_get_lit(ctx, 7) == false); + int user_timeout = arg_get_int_def(ctx, 8, -1); + bool verbose = arg_get_lit(ctx, 9); + + uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; + int datalen = 0; + int res = CLIParamHexToBuf(arg_get_str(ctx, 10), data, sizeof(data), &datalen); + if (res && verbose) { + PrintAndLogEx(INFO, "called with no raw bytes"); + } + CLIParserFree(ctx); + + // FLAGS for device side + uint32_t flags = ISO14B_CONNECT; + if (add_crc) { + flags |= ISO14B_APPEND_CRC; + } + + if (select_std) { + flags |= (ISO14B_SELECT_STD | ISO14B_CLEARTRACE); + if (verbose) { + PrintAndLogEx(INFO, "using ISO14443-B select"); + } + } else if (select_sr) { + flags |= (ISO14B_SELECT_SR | ISO14B_CLEARTRACE); + if (verbose) { + PrintAndLogEx(INFO, "using ST/SRx select"); + } + } else if (select_cts) { + flags |= (ISO14B_SELECT_CTS | ISO14B_CLEARTRACE); + if (verbose) { + PrintAndLogEx(INFO, "using ASK/C-ticket select"); + } + } else if (select_xrx) { + flags |= (ISO14B_SELECT_XRX | ISO14B_CLEARTRACE); + if (verbose) { + PrintAndLogEx(INFO, "using Fuji/Xerox select"); + } + } + + uint32_t time_wait = 0; + if (user_timeout > 0) { + + flags |= ISO14B_SET_TIMEOUT; + + if (user_timeout > MAX_14B_TIMEOUT_MS) { + user_timeout = MAX_14B_TIMEOUT_MS; + PrintAndLogEx(INFO, "set timeout to 4.9 seconds. The max we can wait for response"); + } + + // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + time_wait = (uint32_t)((13560 / 128) * user_timeout); + if (verbose) + PrintAndLogEx(INFO, " new raw timeout : %u ETU ( %u ms )", time_wait, user_timeout); + } + + if (keep_field_on == false) { + flags |= ISO14B_DISCONNECT; + } + + if (datalen > 0) { + flags |= ISO14B_RAW; + } + + // Max buffer is PM3_CMD_DATA_SIZE + datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; + + iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + datalen); + if (packet == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + + packet->flags = flags; + packet->timeout = time_wait; + packet->rawlen = datalen; + memcpy(packet->raw, data, datalen); + + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); + free(packet); + + if (read_reply == false) { + clearCommandBuffer(); + return PM3_SUCCESS; + } + + bool success = true; + + // Select, device will send back iso14b_card_select_t, don't print it. + if (select_std) { + success = wait_cmd_14b(verbose, true, user_timeout); + if (verbose && success) { + PrintAndLogEx(SUCCESS, "Got response for standard select"); + } + } + + if (select_sr) { + success = wait_cmd_14b(verbose, true, user_timeout); + if (verbose && success) { + PrintAndLogEx(SUCCESS, "Got response for ST/SRx select"); + } + } + + if (select_cts) { + success = wait_cmd_14b(verbose, true, user_timeout); + if (verbose && success) { + PrintAndLogEx(SUCCESS, "Got response for ASK/C-ticket select"); + } + } + + if (select_xrx) { + success = wait_cmd_14b(verbose, true, user_timeout); + if (verbose && success) { + PrintAndLogEx(SUCCESS, "Got response for Fuji/Xerox select"); + } + } + + // get back response from the raw bytes you sent. + if (success && datalen > 0) { + wait_cmd_14b(true, false, user_timeout); + } + + return PM3_SUCCESS; +} + // 14b get and print Full Info (as much as we know) static bool HF14B_Std_Info(bool verbose, bool do_aid_search) { // 14b get and print UID only (general info) @@ -1419,13 +1442,14 @@ static int CmdHF14BWriteSri(const char *Cmd) { */ CLIParserContext *ctx; - CLIParserInit(&ctx, "hf 14b sriwrite", + CLIParserInit(&ctx, "hf 14b wrbl", "Write data to a SRI512 or SRIX4K block\n" - "If writing to a block out-of-range, use --force to override checks", - "hf 14b sriwrite --4k -b 100 -d 11223344\n" - "hf 14b sriwrite --4k --sb -d 11223344 --> special block write\n" - "hf 14b sriwrite --512 -b 15 -d 11223344\n" - "hf 14b sriwrite --512 --sb -d 11223344 --> special block write\n" + "If writing to a block out-of-range, use `--force` to override checks\n" + "Special block at end denots OTP and lock bits among others", + "hf 14b wrbl --4k -b 100 -d 11223344\n" + "hf 14b wrbl --4k --sb -d 11223344 --> special block write\n" + "hf 14b wrbl --512 -b 15 -d 11223344\n" + "hf 14b wrbl --512 --sb -d 11223344 --> special block write\n" ); void *argtable[] = { @@ -1713,16 +1737,38 @@ static uint32_t srix4kEncode(uint32_t value) { uint8_t block = (value & 0xFF); uint8_t i = 0; uint8_t valuebytes[] = {0, 0, 0}; + Uint3byteToMemBe(valuebytes, value >> 8); - num_to_bytes(value, 3, valuebytes); + uint32_t value_x = (value >> 8); + PrintAndLogEx(INFO, "value...... %08x %06x", value, value_x); + PrintAndLogEx(INFO, "3b value... %s", sprint_hex_inrow(valuebytes, sizeof(valuebytes))); + PrintAndLogEx(INFO, "block no... %02x", block); // Scrambled part // Crumb swapping of value. - uint8_t temp[] = {0, 0}; - temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14) << 2 | CRUMB(value, 6)) << 4; - temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12) << 2 | CRUMB(value, 4); - temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10) << 2 | CRUMB(value, 2)) << 4; - temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8) << 2 | CRUMB(value, 0); + uint32_t foo = 0; + foo |= CRUMB(value_x, 22) << 28; + foo |= CRUMB(value_x, 14) << 26; + foo |= CRUMB(value_x, 6) << 24; + + foo |= CRUMB(value_x, 20) << 20; + foo |= CRUMB(value_x, 12) << 18; + foo |= CRUMB(value_x, 4) << 16; + + foo |= CRUMB(value_x, 18) << 12; + foo |= CRUMB(value_x, 10) << 10; + foo |= CRUMB(value_x, 2) << 8; + + foo |= CRUMB(value_x, 16) << 4; + foo |= CRUMB(value_x, 8) << 2; + foo |= CRUMB(value_x, 0) << 0; + + PrintAndLogEx(INFO, "hex........ %02x %02x %02x", CRUMB(value_x, 22), CRUMB(value_x, 14), CRUMB(value_x, 6)); + PrintAndLogEx(INFO, "hex........ %02x %02x %02x", CRUMB(value_x, 20), CRUMB(value_x, 12), CRUMB(value_x, 4)); + PrintAndLogEx(INFO, "hex........ %02x %02x %02x", CRUMB(value_x, 18), CRUMB(value_x, 10), CRUMB(value_x, 2)); + PrintAndLogEx(INFO, "hex........ %02x %02x %02x", CRUMB(value_x, 16), CRUMB(value_x, 8), CRUMB(value_x, 0)); + + PrintAndLogEx(INFO, "hex........ %08x", foo); // chksum part uint32_t chksum = 0xFF - block; @@ -1740,9 +1786,11 @@ static uint32_t srix4kEncode(uint32_t value) { base4[i--] = (chksum % 4 << 2); chksum /= 4; } + PrintAndLogEx(INFO, "%s", sprint_hex_inrow(base4, sizeof(base4))); // merge scambled and chksum parts - uint32_t encvalue = + uint32_t encvalue = 0; + (NIBBLE_LOW(base4[0]) << 28) | (NIBBLE_HIGH(temp[0]) << 24) | @@ -1758,7 +1806,14 @@ static uint32_t srix4kEncode(uint32_t value) { PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue); return encvalue; } +*/ +static uint32_t srix4k_decode_counter(uint32_t num) { + uint32_t value = ~num; + ++value; + return value; +} +/* static uint32_t srix4kDecode(uint32_t value) { switch (value) { case 0xC04F42C5: @@ -1770,19 +1825,16 @@ static uint32_t srix4kDecode(uint32_t value) { } return 0; } +*/ -static uint32_t srix4kDecodeCounter(uint32_t num) { - uint32_t value = ~num; - ++value; - return value; -} - -static uint32_t srix4kGetMagicbytes(uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19) { +static uint32_t srix4k_get_magicbytes(uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19) { #define MASK 0xFFFFFFFF; uint32_t uid32 = uid & MASK; - uint32_t counter = srix4kDecodeCounter(block6); - uint32_t decodedBlock18 = srix4kDecode(block18); - uint32_t decodedBlock19 = srix4kDecode(block19); + uint32_t counter = srix4k_decode_counter(block6); + uint32_t decodedBlock18 = 0; + uint32_t decodedBlock19 = 0; +// uint32_t decodedBlock18 = srix4kDecode(block18); +// uint32_t decodedBlock19 = srix4kDecode(block19); uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1; uint32_t result = (uid32 * doubleBlock * counter) & MASK; @@ -1790,8 +1842,19 @@ static uint32_t srix4kGetMagicbytes(uint64_t uid, uint32_t block6, uint32_t bloc return result; } -static int srix4kValid(const char *Cmd) { - (void)Cmd; // Cmd is not used so far +static int CmdSRIX4kValid(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14b valid", + "SRIX checksum test", + "hf 14b valid\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + CLIParserFree(ctx); uint64_t uid = 0xD00202501A4532F9; uint32_t block6 = 0xFFFFFFFF; @@ -1799,23 +1862,22 @@ static int srix4kValid(const char *Cmd) { uint32_t block19 = 0xC1484807; uint32_t block21 = 0xD1BCABA4; - uint32_t test_b18 = 0x00313918; - uint32_t test_b18_enc = srix4kEncode(test_b18); - //uint32_t test_b18_dec = srix4kDecode(test_b18_enc); + uint32_t test_b18 = 0x001A2001; // 0x00313918; + uint32_t test_b18_enc = 0; + // uint32_t test_b18_enc = srix4kEncode(test_b18); + // uint32_t test_b18_dec = srix4kDecode(test_b18_enc); PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc, ""); - uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19); + uint32_t magic = srix4k_get_magicbytes(uid, block6, block18, block19); PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21); - return 0; + return PM3_SUCCESS; } -*/ int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) { if (card) { memset(card, 0, sizeof(iso14b_card_select_t)); } - SetAPDULogging(true); switch_off_field_14b(); iso14b_raw_cmd_t packet = { @@ -1891,7 +1953,7 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, PrintAndLogEx(FAILED, "APDU: failed to allocate memory"); return PM3_EMALLOC; } - packet->flags = (ISO14B_CONNECT | ISO14B_APDU); + packet->flags = (ISO14B_APDU); packet->timeout = 0; packet->rawlen = 0; @@ -1982,6 +2044,7 @@ int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, if (apdu_in_framing_enable && ((apdu_frame_length && (datainlen > apdu_frame_length - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) { + PrintAndLogEx(INFO, "ONE"); int clen = 0; bool v_activate_field = activate_field; @@ -2020,7 +2083,6 @@ int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, } while (clen < datainlen); } else { - res = handle_14b_apdu(false, datain, datainlen, activate_field, dataout, maxdataoutlen, dataoutlen, &chaining, user_timeout); if (res != PM3_SUCCESS) { if (leave_signal_on == false) { @@ -2050,18 +2112,6 @@ int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, // ISO14443-4. 7. Half-duplex block transmission protocol static int CmdHF14BAPDU(const char *Cmd) { - uint8_t data[PM3_CMD_DATA_SIZE]; - int datalen = 0; - uint8_t header[PM3_CMD_DATA_SIZE]; - int headerlen = 0; - bool activate_field = false; - bool leave_signal_on = false; - bool decode_TLV = false; - bool decode_APDU = false; - bool make_APDU = false; - bool extended_APDU = false; - int le = 0; - CLIParserContext *ctx; CLIParserInit(&ctx, "hf 14b apdu", "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL).\n" @@ -2087,21 +2137,27 @@ static int CmdHF14BAPDU(const char *Cmd) { }; CLIExecWithReturn(ctx, Cmd, argtable, false); - activate_field = arg_get_lit(ctx, 1); - leave_signal_on = arg_get_lit(ctx, 2); - decode_TLV = arg_get_lit(ctx, 3); - decode_APDU = arg_get_lit(ctx, 4); + bool activate_field = arg_get_lit(ctx, 1); + bool leave_signal_on = arg_get_lit(ctx, 2); + bool decode_TLV = arg_get_lit(ctx, 3); + bool decode_APDU = arg_get_lit(ctx, 4); + uint8_t header[PM3_CMD_DATA_SIZE] = {0x00}; + int headerlen = 0; CLIGetHexWithReturn(ctx, 5, header, &headerlen); - make_APDU = headerlen > 0; + + bool make_APDU = (headerlen > 0); if (make_APDU && headerlen != 4) { - PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen); + PrintAndLogEx(ERR, "header length must be 4 bytes, got " _RED_("%d"), headerlen); CLIParserFree(ctx); return PM3_EINVARG; } - extended_APDU = arg_get_lit(ctx, 6); - le = arg_get_int_def(ctx, 7, 0); + bool extended_APDU = arg_get_lit(ctx, 6); + int le = arg_get_int_def(ctx, 7, 0); + + uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; + int datalen = 0; if (make_APDU) { uint8_t apdudata[PM3_CMD_DATA_SIZE] = {0}; @@ -2145,10 +2201,10 @@ static int CmdHF14BAPDU(const char *Cmd) { int user_timeout = arg_get_int_def(ctx, 9, -1); CLIParserFree(ctx); - PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", + PrintAndLogEx(INFO, ">>>> %s%s%s >>>> " _YELLOW_("%s"), activate_field ? "sel" : "", - leave_signal_on ? " keep" : "", - decode_TLV ? " TLV" : "", + leave_signal_on ? "| keep" : "", + decode_TLV ? "| TLV" : "", sprint_hex(data, datalen) ); @@ -2165,8 +2221,12 @@ static int CmdHF14BAPDU(const char *Cmd) { return res; } - PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); - PrintAndLogEx(SUCCESS, "APDU response: " _YELLOW_("%02x %02x") " - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + PrintAndLogEx(INFO, "<<<< %s", sprint_hex(data, datalen)); + PrintAndLogEx(SUCCESS, "APDU response: " _YELLOW_("%02x %02x") " - %s" + , data[datalen - 2] + , data[datalen - 1] + , GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1]) + ); // TLV decoder if (decode_TLV && datalen > 4) { @@ -2293,30 +2353,6 @@ out: return res; } -/* extract uid from filename - * filename must match '^hf-14b-[0-9A-F]{16}' - */ -uint8_t *get_uid_from_filename(const char *filename) { - static uint8_t uid[8] ; - memset(uid, 0, 8) ; - char uidinhex[17] ; - if (strlen(filename) < 23 || strncmp(filename, "hf-14b-", 7)) { - PrintAndLogEx(ERR, "can't get uid from filename '%s'. Expected format is hf-14b-...", filename); - return uid ; - } - // extract uid part from filename - strncpy(uidinhex, filename + 7, 16) ; - uidinhex[16] = '\0' ; - int len = hex_to_bytes(uidinhex, uid, 8); - if (len == 8) - return SwapEndian64(uid, 8, 8); - else { - PrintAndLogEx(ERR, "get_uid_from_filename failed: hex_to_bytes returned %d", len); - memset(uid, 0, 8); - } - return uid ; -} - static int CmdHF14BView(const char *Cmd) { CLIParserContext *ctx; @@ -2342,8 +2378,8 @@ static int CmdHF14BView(const char *Cmd) { // read dump file uint8_t *dump = NULL; - size_t bytes_read = 0; - int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (ST25TB_SR_BLOCK_SIZE * 0xFF)); + size_t bytes_read = (ST25TB_SR_BLOCK_SIZE * 0x100); + int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (ST25TB_SR_BLOCK_SIZE * 0x100)); if (res != PM3_SUCCESS) { return res; } @@ -2351,7 +2387,6 @@ static int CmdHF14BView(const char *Cmd) { uint16_t block_cnt = bytes_read / ST25TB_SR_BLOCK_SIZE; if (verbose) { - PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename); PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt); } @@ -2366,21 +2401,23 @@ static int CmdHF14BView(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"apdu", CmdHF14BAPDU, IfPm3Iso14443b, "Send ISO 14443-4 APDU to tag"}, - {"dump", CmdHF14BDump, IfPm3Iso14443b, "Read all memory pages of an ISO-14443-B tag, save to file"}, - {"info", CmdHF14Binfo, IfPm3Iso14443b, "Tag information"}, - {"list", CmdHF14BList, AlwaysAvailable, "List ISO-14443-B history"}, - {"ndefread", CmdHF14BNdefRead, IfPm3Iso14443b, "Read NDEF file on tag"}, - {"raw", CmdHF14BCmdRaw, IfPm3Iso14443b, "Send raw hex data to tag"}, - {"reader", CmdHF14BReader, IfPm3Iso14443b, "Act as a ISO-14443-B reader to identify a tag"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"list", CmdHF14BList, AlwaysAvailable, "List ISO-14443-B history"}, + {"---------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("general") " -----------------------"}, + {"apdu", CmdHF14BAPDU, IfPm3Iso14443b, "Send ISO 14443-4 APDU to tag"}, + {"dump", CmdHF14BDump, IfPm3Iso14443b, "Read all memory pages of an ISO-14443-B tag, save to file"}, + {"info", CmdHF14Binfo, IfPm3Iso14443b, "Tag information"}, + {"ndefread", CmdHF14BNdefRead, IfPm3Iso14443b, "Read NDEF file on tag"}, + {"raw", CmdHF14BCmdRaw, IfPm3Iso14443b, "Send raw hex data to tag"}, + {"reader", CmdHF14BReader, IfPm3Iso14443b, "Act as a ISO-14443-B reader to identify a tag"}, + {"view", CmdHF14BView, AlwaysAvailable, "Display content from tag dump file"}, // {"restore", CmdHF14BRestore, IfPm3Iso14443b, "Restore from file to all memory pages of an ISO-14443-B tag"}, - {"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO ISO-14443-B tag"}, - {"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO-14443-B"}, - {"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"}, - {"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"}, - {"view", CmdHF14BView, AlwaysAvailable, "Display content from tag dump file"}, -// {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"}, + {"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO ISO-14443-B tag"}, + {"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO-14443-B"}, + {"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"}, + {"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"}, + {"view", CmdHF14BView, AlwaysAvailable, "Display content from tag dump file"}, + {"valid", CmdSRIX4kValid, AlwaysAvailable, "SRIX4k checksum test"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 66a34f9cf..94623de5e 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -986,7 +986,8 @@ static bool emrtd_do_auth(char *documentnumber, char *dob, char *expiry, bool BA // Select EF_COM if (emrtd_select_file_by_ef(dg_table[EF_COM].fileid) == false) { *BAC = true; - PrintAndLogEx(INFO, "Authentication is enforced. Will attempt external authentication."); + PrintAndLogEx(INFO, "Authentication is enforced"); + PrintAndLogEx(INFO, "Switching to external authentication..."); } else { *BAC = false; // Select EF_DG1 @@ -996,7 +997,8 @@ static bool emrtd_do_auth(char *documentnumber, char *dob, char *expiry, bool BA uint8_t response[EMRTD_MAX_FILE_SIZE] = { 0x00 }; if (emrtd_read_file(response, &resplen, NULL, NULL, NULL, false) == false) { *BAC = true; - PrintAndLogEx(INFO, "Authentication is enforced. Will attempt external authentication."); + PrintAndLogEx(INFO, "Authentication is enforced"); + PrintAndLogEx(INFO, "Switching to external authentication..."); } else { *BAC = false; } @@ -1007,7 +1009,7 @@ static bool emrtd_do_auth(char *documentnumber, char *dob, char *expiry, bool BA // If BAC isn't available, exit out and warn user. if (BAC_available == false) { PrintAndLogEx(ERR, "This eMRTD enforces authentication, but you didn't supply MRZ data. Cannot proceed."); - PrintAndLogEx(HINT, "Check out hf emrtd info/dump --help, supply data with -n -d and -e."); + PrintAndLogEx(HINT, "Check out `hf emrtd info/dump --h`, supply data with `-n` `-d` and `-e`"); return false; } diff --git a/client/src/iso7816/iso7816core.c b/client/src/iso7816/iso7816core.c index f2af8ff47..24e5964a1 100644 --- a/client/src/iso7816/iso7816core.c +++ b/client/src/iso7816/iso7816core.c @@ -177,9 +177,9 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool l if (isw != ISO7816_OK) { if (APDULogging) { if (*sw >> 8 == 0x61) { - PrintAndLogEx(ERR, "APDU chaining len %02x", *sw & 0xFF); + PrintAndLogEx(ERR, "APDU chaining len " _RED_("%02x"), *sw & 0xFF); } else { - PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xFF)); + PrintAndLogEx(ERR, "APDU (%02x%02x) ERROR... " _RED_("%4X") " - %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xFF)); return 5; } } @@ -189,30 +189,30 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool activate_field, bool l int Iso7816Exchange(Iso7816CommandChannel channel, bool leave_field_on, sAPDU_t apdu, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { return Iso7816ExchangeEx(channel - , false - , leave_field_on - , apdu - , false - , 0 - , result - , max_result_len - , result_len - , sw - ); + , false + , leave_field_on + , apdu + , false + , 0 + , result + , max_result_len + , result_len + , sw + ); } int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, uint8_t *aid, size_t aid_len, uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) { return Iso7816ExchangeEx(channel - , activate_field - , leave_field_on - , (sAPDU_t) {0x00, 0xa4, 0x04, 0x00, aid_len, aid} - , (channel == CC_CONTACTLESS) - , 0 - , result - , max_result_len - , result_len - , sw - ); + , activate_field + , leave_field_on + , (sAPDU_t) {0x00, 0xa4, 0x04, 0x00, aid_len, aid} + , (channel == CC_CONTACTLESS) + , 0 + , result + , max_result_len + , result_len + , sw + ); }