diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 1256afc9d..520b445d6 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1429,7 +1429,7 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t blockno; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - ReadSTBlock(payload->blockno); + read_14b_st_block(payload->blockno); break; } case CMD_HF_ISO14443B_SNIFF: { diff --git a/armsrc/epa.c b/armsrc/epa.c index 4e4113d45..8406f6168 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -155,7 +155,7 @@ static int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response, uint16_t re #endif case 'b': #ifdef WITH_ISO14443b - return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL); + return iso14443b_apdu(apdu, length, false, response, respmaxlen, NULL, NULL); #else (void) apdu; (void) length; diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 7bb470e66..332fc1da7 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -183,6 +183,10 @@ # define ISO14B_TR2 HF14_ETU_TO_SSP(14) #endif +#ifndef ISO14B_BLOCK_SIZE +# define ISO14B_BLOCK_SIZE 4 +#endif + // 4sample #define SEND4STUFFBIT(x) tosend_stuffbit(x);tosend_stuffbit(x);tosend_stuffbit(x);tosend_stuffbit(x); @@ -472,7 +476,9 @@ static void iso14b_set_maxframesize(uint16_t size) { } Uart.byteCntMax = size; - if (g_dbglevel >= DBG_DEBUG) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); + if (g_dbglevel >= DBG_DEBUG) { + Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); + } } //----------------------------------------------------------------------------- @@ -662,7 +668,7 @@ static RAMFUNC int Handle14443bSampleFromReader(uint8_t bit) { // Assume that we're called with the SSC (to the FPGA) and ADC path set // correctly. //----------------------------------------------------------------------------- -static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { +static bool GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED @@ -764,7 +770,7 @@ void SimulateIso14443bTag(const uint8_t *pupi) { tosend_t *ts = get_tosend(); - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmd = BigBuf_calloc(MAX_FRAME_SIZE); // prepare "ATQB" tag answer (encoded): CodeIso14443bAsTag(respATQB, sizeof(respATQB)); @@ -797,10 +803,13 @@ void SimulateIso14443bTag(const uint8_t *pupi) { LED_A_ON(); } } - if (cardSTATE == SIM_NOFIELD) continue; + + if (cardSTATE == SIM_NOFIELD) { + continue; + } // Get reader command - if (!GetIso14443bCommandFromReader(receivedCmd, &len)) { + if (GetIso14443bCommandFromReader(receivedCmd, &len) == false) { Dbprintf("button pressed, received %d commands", cmdsReceived); break; } @@ -810,9 +819,11 @@ void SimulateIso14443bTag(const uint8_t *pupi) { // WUP in HALTED state if (len == 5) { if ((receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8) == 0x8 && cardSTATE == SIM_HALTED) || - receivedCmd[0] == ISO14443B_REQB) { + receivedCmd[0] == ISO14443B_REQB) { + LogTrace(receivedCmd, len, 0, 0, NULL, true); cardSTATE = SIM_SELECTING; + } } @@ -861,13 +872,14 @@ void SimulateIso14443bTag(const uint8_t *pupi) { // - SLOT MARKER // - ISO7816 // - emulate with a memory dump - if (g_dbglevel >= DBG_DEBUG) + if (g_dbglevel >= DBG_DEBUG) { Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); + } - // CRC Check - if (len >= 3) { // if crc exists + // CRC Check, if long enough + if (len >= 3) { - if (!check_crc(CRC_14443_B, receivedCmd, len)) { + if (check_crc(CRC_14443_B, receivedCmd, len) == false) { if (g_dbglevel >= DBG_DEBUG) { DbpString("CRC fail"); } @@ -1000,7 +1012,7 @@ void Simulate_iso14443b_srx_tag(uint8_t *uid) { if (cardSTATE == SIM_NOFIELD) continue; // Get reader command - if (!GetIso14443bCommandFromReader(receivedCmd, &len)) { + if (GetIso14443bCommandFromReader(receivedCmd, &len) == false) { Dbprintf("button pressed, received %d commands", cmdsReceived); break; } @@ -1067,7 +1079,7 @@ void Simulate_iso14443b_srx_tag(uint8_t *uid) { // CRC Check if (len >= 3) { // if crc exists - if (!check_crc(CRC_14443_B, receivedCmd, len)) { + if (check_crc(CRC_14443_B, receivedCmd, len) == false) { if (g_dbglevel >= DBG_DEBUG) { DbpString("CRC fail"); } @@ -1314,7 +1326,7 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t if (FpgaSetupSscDma((uint8_t *) dma->buf, DMA_BUFFER_SIZE) == false) { if (g_dbglevel > DBG_ERROR) Dbprintf("FpgaSetupSscDma failed. Exiting"); - return -1; + return PM3_EMALLOC; } uint32_t dma_start_time = 0; @@ -1328,8 +1340,9 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t for (;;) { volatile uint16_t behindBy = ((uint16_t *)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (DMA_BUFFER_SIZE - 1); - if (behindBy == 0) + if (behindBy == 0) { continue; + } samples++; @@ -1375,13 +1388,13 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t *eof_time = GetCountSspClkDelta(dma_start_time) - DELAY_TAG_TO_ARM; // end of EOF if (Demod.len > Demod.max_len) { - ret = -2; // overflow + ret = PM3_EOVFLOW; // overflow } break; } if (((GetCountSspClkDelta(dma_start_time)) > timeout) && Demod.state < DEMOD_PHASE_REF_TRAINING) { - ret = -1; + ret = PM3_ETIMEOUT; break; } } @@ -1399,8 +1412,6 @@ static int Get14443bAnswerFromTag(uint8_t *response, uint16_t max_len, uint32_t + (10)); // time for EOF transfer LogTrace(Demod.output, Demod.len, sof_time, *eof_time, NULL, false); } - - return Demod.len; } @@ -1568,7 +1579,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 iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void *rxdata, uint16_t rxmaxlen, uint8_t *res, int *reponselen) { uint8_t real_cmd[msg_len + 4]; @@ -1598,10 +1609,9 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; -// Activation frame waiting time -// 65536/fc == 4833 µS -// SSP_CLK = 4833 µS * 3.39 = 16384 - + // Activation frame waiting time + // 65536/fc == 4833 µS + // SSP_CLK = 4833 µS * 3.39 = 16384 int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time); FpgaDisableTracing(); @@ -1609,7 +1619,8 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void uint8_t *data_bytes = (uint8_t *) rxdata; if (len <= 0) { - return 0; //DATA LINK ERROR + // DATA LINK ERROR + return PM3_ECARDEXCHANGE; } else { // S-Block WTX while (len && ((data_bytes[0] & 0xF2) == 0xF2)) { @@ -1648,20 +1659,23 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void // if we received an I- or R(ACK)-Block with a block number equal to the // current block number, toggle the current block number - if (len >= 3 // PCB + CRC = 3 bytes - && ((data_bytes[0] & 0xC0) == 0 // I-Block - || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 - && (data_bytes[0] & 0x01) == iso14b_pcb_blocknum) { // equal block numbers + + 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 + iso14b_pcb_blocknum ^= 1; + } // if we received I-block with chaining we need to send ACK and receive another block of data - if (res) + if (res) { *res = data_bytes[0]; + } // crc check - if (len >= 3 && !check_crc(CRC_14443_B, data_bytes, len)) { - return -1; + if (len >= 3 && (check_crc(CRC_14443_B, data_bytes, len) == false)) { + return PM3_ECRC; } } @@ -1674,7 +1688,10 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void } } - return len; + if (reponselen) { + *reponselen = len; + } + return PM3_SUCCESS; } /** @@ -1686,10 +1703,11 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { uint8_t cmdMSBUID[] = {ASK_SELECT, 0xFF, 0xFF, 0x00, 0x00}; uint8_t cmdLSBUID[] = {0xC4, 0x00, 0x00}; +// iceman: todo static crc AddCrc14B(cmdMSBUID, 3); AddCrc14B(cmdLSBUID, 1); - uint8_t r[8]; + uint8_t r[8] = { 0x00 }; uint32_t start_time = 0; uint32_t eof_time = 0; @@ -1700,10 +1718,10 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { FpgaDisableTracing(); if (retlen != 4) { - return -1; + return PM3_ELENGTH; } if (check_crc(CRC_14443_B, r, retlen) == false) { - return -2; + return PM3_ECRC; } if (card) { @@ -1720,10 +1738,10 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { FpgaDisableTracing(); if (retlen != 4) { - return -1; + return PM3_ELENGTH; } if (check_crc(CRC_14443_B, r, retlen) == false) { - return -2; + return PM3_ECRC; } if (card) { @@ -1738,17 +1756,17 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { FpgaDisableTracing(); if (retlen != 4) { - return -1; + return PM3_ELENGTH; } if (check_crc(CRC_14443_B, r, retlen) == false) { - return -2; + return PM3_ECRC; } if (card) { memcpy(card->uid + 2, r, 2); } - return 0; + return PM3_SUCCESS; } /** * SRx Initialise. @@ -1756,9 +1774,9 @@ static int iso14443b_select_cts_card(iso14b_cts_card_select_t *card) { static int iso14443b_select_srx_card(iso14b_card_select_t *card) { // INITIATE command: wake up the tag using the INITIATE static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b }; - uint8_t r_init[3] = {0x0}; - uint8_t r_select[3] = {0x0}; - uint8_t r_papid[10] = {0x0}; + uint8_t r_init[3] = { 0x00 }; + uint8_t r_select[3] = { 0x00 }; + uint8_t r_papid[10] = { 0x00 }; uint32_t start_time = 0; uint32_t eof_time = 0; @@ -1769,7 +1787,7 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) { FpgaDisableTracing(); if (retlen <= 0) { - return -1; + return PM3_ECARDEXCHANGE; } // Randomly generated Chip ID @@ -1791,42 +1809,43 @@ static int iso14443b_select_srx_card(iso14b_card_select_t *card) { FpgaDisableTracing(); if (retlen != 3) { - return -1; + return PM3_ELENGTH; } if (check_crc(CRC_14443_B, r_select, retlen) == false) { - return -2; + return PM3_ECRC; } // Check response from the tag: should be the same UID as the command we just sent: if (select_srx[1] != r_select[0]) { - return -3; + return PM3_EWRONGANSWER; } // First get the tag's UID: select_srx[0] = ISO14443B_GET_UID; - - AddCrc14B(select_srx, 1); + select_srx[1] = 0xAB; + select_srx[2] = 0x4E; start_time = eof_time + ISO14B_TR2; CodeAndTransmit14443bAsReader(select_srx, 3, &start_time, &eof_time, true); // Only first three bytes for this one eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; retlen = Get14443bAnswerFromTag(r_papid, sizeof(r_papid), iso14b_timeout, &eof_time); + FpgaDisableTracing(); if (retlen != 10) { - return -1; + return PM3_ELENGTH; } - if (!check_crc(CRC_14443_B, r_papid, retlen)) { - return -2; + + if (check_crc(CRC_14443_B, r_papid, retlen) == false) { + return PM3_ECRC; } if (card) { card->uidlen = 8; memcpy(card->uid, r_papid, 8); } - - return 0; + return PM3_SUCCESS; } // Xerox tag connect function: wup, anticoll, attrib, password @@ -1837,9 +1856,8 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { // AFI static const uint8_t x_wup1[] = { 0x0D, 0x37, 0x21, 0x92, 0xf2 }; static const uint8_t x_wup2[] = { 0x5D, 0x37, 0x21, 0x71, 0x71 }; - uint8_t slot_mark[1]; - - uint8_t x_atqb[24] = {0x0}; // ATQB len = 18 + uint8_t slot_mark[1] = { 0x00 }; + uint8_t x_atqb[24] = { 0x00 }; // ATQB len = 18 uint32_t start_time = 0; uint32_t eof_time = 0; @@ -1870,7 +1888,7 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { Dbprintf("unexpected data %d", retlen); Dbprintf("crc %s", check_crc(CRC_14443_B, x_atqb, retlen) ? "OK" : "BAD"); - return 1; + return PM3_ECARDEXCHANGE; } // tx unframed slot-marker @@ -1893,7 +1911,7 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { if (g_dbglevel >= DBG_DEBUG) { DbpString("no answer to anticollision"); } - return 1; + return PM3_ESOFT; } } @@ -1905,16 +1923,16 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { // ATQB too short? if (retlen < 18) { - return 1; + return PM3_ELENGTH; } // VALIDATE CRC if (check_crc(CRC_14443_B, x_atqb, 18) == false) { // use fixed len because unstable EOF catch - return 3; + return PM3_ECRC; } if (x_atqb[0] != 0x50) { - return 1; + return PM3_EWRONGANSWER; } if (card) { @@ -1944,15 +1962,15 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { FpgaDisableTracing(); if (retlen < 3) { - return 2; + return PM3_ELENGTH; } if (check_crc(CRC_14443_B, x_atqb, 3) == false) { - return 3; + return PM3_ECRC; } if (x_atqb[0] != 0) { - return 2; + return PM3_EWRONGANSWER; } // apply PASSWORD command @@ -1975,18 +1993,18 @@ static int iso14443b_select_xrx_card(iso14b_card_select_t *card) { retlen = Get14443bAnswerFromTag(x_atqb, sizeof(x_atqb), iso14b_timeout, &eof_time); if (retlen < 4) { - return 4; + return PM3_ELENGTH; } if (check_crc(CRC_14443_B, x_atqb, 4) == false) { - return 3; + return PM3_ECRC; } if (x_atqb[0] != 2 || x_atqb[1] != 0) { - return 4; + return PM3_EWRONGANSWER; } - return 0; + return PM3_SUCCESS; } /* Perform the ISO 14443 B Card Selection procedure @@ -2003,10 +2021,9 @@ int iso14443b_select_card(iso14b_card_select_t *card) { static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xff }; // ATTRIB command (with space for CRC) - uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; - - uint8_t r_pupid[14] = {0x0}; - uint8_t r_attrib[3] = {0x0}; + uint8_t attrib[11] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; + uint8_t r_pupid[14] = { 0x00 }; + uint8_t r_attrib[3] = { 0x00 }; // first, wake up the tag uint32_t start_time = 0; @@ -2019,12 +2036,12 @@ int iso14443b_select_card(iso14b_card_select_t *card) { // ATQB too short? if (retlen < 14) { - return -1; + return PM3_ELENGTH; } // VALIDATE CRC if (check_crc(CRC_14443_B, r_pupid, retlen) == false) { - return -2; + return PM3_ECRC; } if (card) { @@ -2048,12 +2065,12 @@ int iso14443b_select_card(iso14b_card_select_t *card) { // Answer to ATTRIB too short? if (retlen < 3) { - return -1; + return PM3_ELENGTH; } // VALIDATE CRC if (check_crc(CRC_14443_B, r_attrib, retlen) == false) { - return -2; + return PM3_ECRC; } if (card) { @@ -2079,7 +2096,7 @@ int iso14443b_select_card(iso14b_card_select_t *card) { } // reset PCB block number iso14b_pcb_blocknum = 0; - return 0; + return PM3_SUCCESS; } // Set up ISO 14443 Type B communication (similar to iso14443a_setup) @@ -2128,8 +2145,9 @@ void iso14443b_setup(void) { // // I tried to be systematic and check every answer of the tag, every CRC, etc... //----------------------------------------------------------------------------- -static int read_srx_block(uint8_t blocknr, uint8_t *block) { +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); @@ -2155,7 +2173,7 @@ static int read_srx_block(uint8_t blocknr, uint8_t *block) { } if (block) { - memcpy(block, r_block, 4); + memcpy(block, r_block, ISO14B_BLOCK_SIZE); } if (g_dbglevel >= DBG_DEBUG) { @@ -2169,25 +2187,25 @@ static int read_srx_block(uint8_t blocknr, uint8_t *block) { return PM3_SUCCESS; } -void ReadSTBlock(uint8_t blocknr) { +void read_14b_st_block(uint8_t blocknr) { iso14443b_setup(); - iso14b_card_select_t card; - int res = iso14443b_select_srx_card(&card); + + uint8_t *data = BigBuf_calloc(ISO14B_BLOCK_SIZE); + iso14b_card_select_t *card = (iso14b_card_select_t *) BigBuf_calloc(sizeof(iso14b_card_select_t)); + + int res = iso14443b_select_srx_card(card); // 0: OK -1 wrong len, -2: attrib fail, -3:crc fail, switch (res) { - case -1: - case -3: { - reply_ng(CMD_HF_SRI_READ, PM3_EWRONGANSWER, NULL, 0); - goto out; - } - case -2: { - reply_ng(CMD_HF_SRI_READ, PM3_ECRC, NULL, 0); + case PM3_ELENGTH: + case PM3_EWRONGANSWER: + case PM3_ECRC: { + reply_ng(CMD_HF_SRI_READ, res, NULL, 0); goto out; } } - uint8_t *data = BigBuf_malloc(4); - res = read_srx_block(blocknr, data); - reply_ng(CMD_HF_SRI_READ, res, data, 4); + + res = read_14b_srx_block(blocknr, data); + reply_ng(CMD_HF_SRI_READ, res, data, ISO14B_BLOCK_SIZE); out: BigBuf_free(); @@ -2392,9 +2410,6 @@ static void iso14b_set_trigger(bool enable) { void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) { - // receive buffer - uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00}; - // turn on trigger (LED_A) if ((p->flags & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) { iso14b_set_trigger(true); @@ -2414,68 +2429,76 @@ void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *p) { } set_tracing(true); + // receive buffer + uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00}; + int status = 0; uint32_t sendlen = sizeof(iso14b_card_select_t); iso14b_card_select_t *card = (iso14b_card_select_t *)buf; if ((p->flags & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { status = iso14443b_select_card(card); - reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen); - // 0: OK -1: attrib fail, -2:crc fail, - if (status != 0) goto out; + reply_ng(CMD_HF_ISO14443B_COMMAND, status, (uint8_t *)card, sendlen); + if (status != PM3_SUCCESS) goto out; } if ((p->flags & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { + memset(card, 0, sizeof(iso14b_card_select_t)); status = iso14443b_select_srx_card(card); - reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen); - // 0: OK 2: demod fail, 3:crc fail, - if (status > 0) goto out; + reply_ng(CMD_HF_ISO14443B_COMMAND, status, (uint8_t *)card, sendlen); + if (status != PM3_SUCCESS) goto out; } if ((p->flags & ISO14B_SELECT_XRX) == ISO14B_SELECT_XRX) { + memset(card, 0, sizeof(iso14b_card_select_t)); status = iso14443b_select_xrx_card(card); - reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen); + reply_ng(CMD_HF_ISO14443B_COMMAND, status, (uint8_t *)card, sendlen); // 0: OK, 1: select fail, 2: attrib fail, 3: crc fail, 4: password fail - if (status != 0) goto out; + if (status != PM3_SUCCESS) goto out; } if ((p->flags & ISO14B_SELECT_CTS) == ISO14B_SELECT_CTS) { iso14b_cts_card_select_t *cts = (iso14b_cts_card_select_t *)buf; + memset(cts, 0, sizeof(iso14b_cts_card_select_t)); sendlen = sizeof(iso14b_cts_card_select_t); status = iso14443b_select_cts_card(cts); - reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&cts, sendlen); - // 0: OK 2: demod fail, 3:crc fail, - if (status > 0) goto out; + reply_ng(CMD_HF_ISO14443B_COMMAND, status, (uint8_t *)cts, sendlen); + if (status > PM3_SUCCESS) goto out; } if ((p->flags & ISO14B_APDU) == ISO14B_APDU) { - uint8_t res = 0; - status = iso14443b_apdu(p->raw, p->rawlen, (p->flags & ISO14B_SEND_CHAINING), buf, sizeof(buf), &res); - sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE_MIX); - reply_mix(CMD_HF_ISO14443B_COMMAND, status, res, 0, buf, sendlen); + + iso14b_raw_apdu_response_t packet = { + .response_byte = 0, + .datalen = 0, + }; + + int responselen = 0; + status = iso14443b_apdu(p->raw, p->rawlen, (p->flags & ISO14B_SEND_CHAINING), buf, sizeof(buf), &packet.response_byte, &responselen); + packet.datalen = MIN(responselen, PM3_CMD_DATA_SIZE); + memcpy(packet.data, buf, packet.datalen); + reply_ng(CMD_HF_ISO14443B_COMMAND, status, (uint8_t*)&packet, sizeof(iso14b_raw_apdu_response_t) + packet.datalen); } if ((p->flags & ISO14B_RAW) == ISO14B_RAW) { - if ((p->flags & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { - if (p->rawlen > 0) { - AddCrc14B(p->raw, p->rawlen); - p->rawlen += 2; - } + 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(p->raw, p->rawlen, &start_time, &eof_time, true); + FpgaDisableTracing(); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred - FpgaDisableTracing(); - reply_mix(CMD_HF_ISO14443B_COMMAND, -2, 0, 0, NULL, 0); + reply_ng(CMD_HF_ISO14443B_COMMAND, PM3_ETEAROFF, NULL, 0); } else { eof_time += DELAY_ISO14443B_PCD_TO_PICC_READER; status = Get14443bAnswerFromTag(buf, sizeof(buf), iso14b_timeout, &eof_time); // raw - FpgaDisableTracing(); - - sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE_MIX); - reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, Demod.output, sendlen); + sendlen = MIN(Demod.len, 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 9d5c1d374..14da377d3 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -35,13 +35,13 @@ #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 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_select_card(iso14b_card_select_t *card); void SimulateIso14443bTag(const uint8_t *pupi); void AcquireRawAdcSamplesIso14443b(uint32_t parameter); -void ReadSTBlock(uint8_t blocknr); +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); diff --git a/client/luascripts/hf_14b_calypso.lua b/client/luascripts/hf_14b_calypso.lua index 61aa92dde..e9cc8c8f5 100644 --- a/client/luascripts/hf_14b_calypso.lua +++ b/client/luascripts/hf_14b_calypso.lua @@ -29,6 +29,9 @@ Check there for details about data format and how commands are interpreted on th device-side. ]] +local PM3_SUCCESS = 0 + +-- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t local function calypso_parse(result) if result.Oldarg0 >= 0 then local len = result.Oldarg0 * 2 @@ -112,9 +115,7 @@ end local function calypso_send_cmd_raw(data, ignoreresponse ) local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU --- flags = lib14b.ISO14B_COMMAND.ISO14B_RAW + --- lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC - local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU + data = data or "" -- LEN of data, half the length of the ASCII-string hex string -- 2 bytes flags @@ -129,7 +130,7 @@ local function calypso_send_cmd_raw(data, ignoreresponse ) local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata} local result, err = c:sendNG(ignoreresponse, 2000) if result then - if result.Oldarg0 >= 0 then + if result.status == PM3_SUCCESS then return calypso_parse(result) else err = 'card response failed' @@ -144,7 +145,7 @@ end -- writes it in the tree in decimal format. local function calypso_card_num(card) if not card then return end - local card_num = tonumber( card.uid:sub(1,8),16 ) + local card_num = tonumber( card.uid:sub(1, 8), 16) print('') print('Card UID ' ..ansicolors.green..card.uid:format('%x')..ansicolors.reset) print('Card Number ' ..ansicolors.green..string.format('%u', card_num)..ansicolors.reset) @@ -156,7 +157,7 @@ local function calypso_apdu_status(apdu) -- last two is CRC -- next two is APDU status bytes. local mess = 'FAIL' - local sw = apdu:sub( #apdu-7, #apdu-4) + local sw = apdu:sub( #apdu - 7 , #apdu - 4) desc, err = iso7816.tostring(sw) --print ('SW', sw, desc, err ) local status = ( sw == '9000' ) @@ -250,7 +251,7 @@ function main(args) for i, apdu in spairs(_calypso_cmds) do print('>> '..ansicolors.yellow..i..ansicolors.reset) apdu = apdu:gsub('%s+', '') - data, err = calypso_send_cmd_raw(apdu , false) + data, err = calypso_send_cmd_raw(apdu, false) if err then print('<< '..err) else diff --git a/client/luascripts/hf_14b_mobib.lua b/client/luascripts/hf_14b_mobib.lua index 85cd832a8..e267e7412 100644 --- a/client/luascripts/hf_14b_mobib.lua +++ b/client/luascripts/hf_14b_mobib.lua @@ -30,6 +30,7 @@ Check there for details about data format and how commands are interpreted on th device-side. ]] +-- iceman, todo: return payload from ISO14b APDU is a struct now. iso14b_raw_apdu_response_t local function mobib_parse(result) if result.Oldarg0 >= 0 then local len = result.Oldarg0 * 2 @@ -126,7 +127,7 @@ local function mobib_send_cmd_raw(data, ignoreresponse ) local result, err = c:sendNG(ignoreresponse, 2000) if result then - if result.Oldarg0 >= 0 then + if result.status == PM3_SUCCESS then return mobib_parse(result) else err = 'card response failed' diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 784f8bd2a..67c1c04a0 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -86,8 +86,10 @@ static void hf14b_aid_search(bool verbose) { json_t *data = AIDSearchGetElm(root, elmindx); uint8_t vaid[200] = {0}; int vaidlen = 0; - if (!AIDGetFromElm(data, vaid, sizeof(vaid), &vaidlen) || !vaidlen) + + if ((AIDGetFromElm(data, vaid, sizeof(vaid), &vaidlen) == false) || (vaidlen == 0 )) { continue; + } // COMPUTE APDU @@ -96,7 +98,7 @@ static void hf14b_aid_search(bool verbose) { sAPDU_t apdu = (sAPDU_t) {0x00, 0xa4, 0x04, 0x00, vaidlen, vaid}; if (APDUEncodeS(&apdu, false, 0x00, apdu_data, &apdu_len)) { - PrintAndLogEx(ERR, "APDU encoding error."); + PrintAndLogEx(ERR, "APDU encoding error"); return; } @@ -106,8 +108,9 @@ static void hf14b_aid_search(bool verbose) { uint8_t result[1024] = {0}; int res = exchange_14b_apdu(apdu_data, apdu_len, activate_field, leave_signal_on, result, sizeof(result), &resultlen, -1); activate_field = false; - if (res) + if (res) { continue; + } uint16_t sw = get_sw(result, resultlen); @@ -128,9 +131,13 @@ static void hf14b_aid_search(bool verbose) { if (sw == ISO7816_OK || sw == ISO7816_INVALID_DF || sw == ISO7816_FILE_TERMINATED) { if (sw == ISO7816_OK) { - if (verbose) PrintAndLogEx(SUCCESS, "Application ( " _GREEN_("ok") " )"); + if (verbose) { + PrintAndLogEx(SUCCESS, "Application ( " _GREEN_("ok") " )"); + } } else { - if (verbose) PrintAndLogEx(WARNING, "Application ( " _RED_("blocked") " )"); + if (verbose) { + PrintAndLogEx(WARNING, "Application ( " _RED_("blocked") " )"); + } } PrintAIDDescriptionBuf(root, vaid, vaidlen, verbose); @@ -138,7 +145,9 @@ static void hf14b_aid_search(bool verbose) { if (dfnamelen) { if (dfnamelen == vaidlen) { if (memcmp(dfname, vaid, vaidlen) == 0) { - if (verbose) PrintAndLogEx(INFO, "(DF) Name found and equal to AID"); + if (verbose) { + PrintAndLogEx(INFO, "(DF) Name found and equal to AID"); + } } else { PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen)); PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose); @@ -148,16 +157,21 @@ static void hf14b_aid_search(bool verbose) { PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose); } } else { - if (verbose) PrintAndLogEx(INFO, "(DF) Name not found"); + if (verbose) { + PrintAndLogEx(INFO, "(DF) Name not found"); + } } - if (verbose) PrintAndLogEx(SUCCESS, "----------------------------------------------------"); + if (verbose) { + PrintAndLogEx(SUCCESS, "----------------------------------------------------"); + } found = true; } } switch_off_field_14b(); - if (verbose == false && found) + if (verbose == false && found) { PrintAndLogEx(INFO, "----------------------------------------------------"); + } } static bool wait_cmd_14b(bool verbose, bool is_select, uint32_t timeout) { @@ -168,15 +182,21 @@ static bool wait_cmd_14b(bool verbose, bool is_select, uint32_t timeout) { return false; } - uint16_t len = (resp.oldarg[1] & 0xFFFF); + if (resp.status == PM3_ETEAROFF) { + if (verbose) { + PrintAndLogEx(INFO, "Writing tear off triggered"); + } + return true; + } + + uint16_t len = resp.length; uint8_t *data = resp.data.asBytes; // handle select responses if (is_select) { // 0: OK; -1: attrib fail; -2:crc fail - int status = (int)resp.oldarg[0]; - if (status == 0) { + if (resp.status == PM3_SUCCESS) { if (verbose) { PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len); @@ -210,7 +230,7 @@ static bool wait_cmd_14b(bool verbose, bool is_select, uint32_t timeout) { } static int CmdHF14BList(const char *Cmd) { - return CmdTraceListAlias(Cmd, "hf 14b", "14b"); + return CmdTraceListAlias(Cmd, "hf 14b", "14b -c"); } static int CmdHF14BSim(const char *Cmd) { @@ -306,29 +326,6 @@ static int CmdHF14BCmdRaw(const char *Cmd) { int user_timeout = arg_get_int_def(ctx, 8, -1); bool verbose = arg_get_lit(ctx, 9); - 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"); - } - uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; int datalen = 0; int res = CLIParamHexToBuf(arg_get_str(ctx, 10), data, sizeof(data), &datalen); @@ -337,6 +334,33 @@ static int CmdHF14BCmdRaw(const char *Cmd) { } 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) { @@ -354,11 +378,13 @@ static int CmdHF14BCmdRaw(const char *Cmd) { PrintAndLogEx(INFO, " new raw timeout : %u ETU ( %u ms )", time_wait, user_timeout); } - if (keep_field_on == 0) + if (keep_field_on == false) { flags |= ISO14B_DISCONNECT; + } - if (datalen > 0) + if (datalen > 0) { flags |= ISO14B_RAW; + } // Max buffer is PM3_CMD_DATA_SIZE datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; @@ -369,6 +395,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; } + packet->flags = flags; packet->timeout = time_wait; packet->rawlen = datalen; @@ -388,26 +415,30 @@ static int CmdHF14BCmdRaw(const char *Cmd) { // 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) + if (verbose && success) { PrintAndLogEx(SUCCESS, "Got response for standard select"); + } } if (select_sr) { success = wait_cmd_14b(verbose, true, user_timeout); - if (verbose && success) + 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) + 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) + if (verbose && success) { PrintAndLogEx(SUCCESS, "Got response for Fuji/Xerox select"); + } } // get back response from the raw bytes you sent. @@ -438,7 +469,7 @@ static bool get_14b_UID(uint8_t *d, iso14b_type_t *found_type) { SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (resp.oldarg[0] == 0) { + if (resp.status == PM3_SUCCESS) { memcpy(d, resp.data.asBytes, sizeof(iso14b_card_select_t)); iso14b_card_select_t *card = (iso14b_card_select_t *)d; @@ -457,7 +488,7 @@ static bool get_14b_UID(uint8_t *d, iso14b_type_t *found_type) { SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (resp.oldarg[0] == 0) { + if (resp.status == PM3_SUCCESS) { memcpy(d, resp.data.asBytes, sizeof(iso14b_card_select_t)); *found_type = ISO14B_STANDARD; return true; @@ -470,7 +501,7 @@ static bool get_14b_UID(uint8_t *d, iso14b_type_t *found_type) { SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (resp.oldarg[0] == 0) { + if (resp.status == PM3_SUCCESS) { memcpy(d, resp.data.asBytes, sizeof(iso14b_cts_card_select_t)); *found_type = ISO14B_CT; return true; @@ -860,12 +891,12 @@ static bool HF14B_Std_Info(bool verbose, bool do_aid_search) { return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + switch (resp.status) { + case PM3_SUCCESS: { + + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); - int status = resp.oldarg[0]; - switch (status) { - case 0: { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); @@ -879,10 +910,10 @@ static bool HF14B_Std_Info(bool verbose, bool do_aid_search) { return true; } - case -1: + case PM3_ELENGTH: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 STD ATTRIB fail"); break; - case -2: + case PM3_ECRC: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 STD CRC fail"); break; default: @@ -912,15 +943,15 @@ static bool HF14B_ST_Info(bool verbose, bool do_aid_search) { return false; } + if (resp.status != PM3_SUCCESS) { + return false; + } + iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); - int status = resp.oldarg[0]; - if (status < 0) - return false; - uint8_t empty[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if ((card.uidlen < 8) || (memcmp(card.uid, empty, card.uidlen) == 0)) { + if ((card.uidlen != 8) || (memcmp(card.uid, empty, card.uidlen) == 0)) { return false; } @@ -972,26 +1003,25 @@ static bool HF14B_st_reader(bool verbose) { return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + switch (resp.status) { + case PM3_SUCCESS:{ + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); - uint8_t empty[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if ((card.uidlen < 8) || (memcmp(card.uid, empty, card.uidlen) == 0)) { - return false; - } - - int status = resp.oldarg[0]; - switch (status) { - case 0: + uint8_t empty[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if ((card.uidlen != 8) || (memcmp(card.uid, empty, card.uidlen) == 0)) { + return false; + } print_st_general_info(card.uid, card.uidlen); return true; - case -1: + } + case PM3_ELENGTH: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST ATTRIB fail"); break; - case -2: + case PM3_ECRC: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST CRC fail"); break; - case -3: + case PM3_EWRONGANSWER: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST random chip id fail"); break; default: @@ -1018,18 +1048,16 @@ static bool HF14B_std_reader(bool verbose) { } return false; } - int status = resp.oldarg[0]; - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); + switch (resp.status) { + case PM3_SUCCESS: { + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); - uint8_t empty[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (memcmp(card.uid, empty, card.uidlen) == 0) { - return false; - } - - switch (status) { - case 0: { + uint8_t empty[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + if (memcmp(card.uid, empty, card.uidlen) == 0) { + return false; + } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, " UID : " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); @@ -1037,11 +1065,11 @@ static bool HF14B_std_reader(bool verbose) { print_atqb_resp(card.atqb, card.cid); return true; } - case -1: { + case PM3_ELENGTH: { if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; } - case -2: { + case PM3_ECRC: { if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); break; } @@ -1070,10 +1098,8 @@ static bool HF14B_ask_ct_reader(bool verbose) { return false; } - int status = resp.oldarg[0]; - - switch (status) { - case 0: { + switch (resp.status) { + case PM3_SUCCESS: { print_ct_general_info(resp.data.asBytes); return true; } @@ -1109,29 +1135,11 @@ static bool HF14B_other_reader(bool verbose) { // 14b get and print UID only (general info) clearCommandBuffer(); - PacketResponseNG resp; SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); - if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { - if (verbose) { - PrintAndLogEx(WARNING, "timeout while waiting for reply"); - } - free(packet); - switch_off_field_14b(); - return false; - } - int status = resp.oldarg[0]; - PrintAndLogEx(DEBUG, "status %d", status); - if (status == 0) { + if (wait_cmd_14b(verbose, true, -1)) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); - PrintAndLogEx(SUCCESS, "unknown tag type answered to a " _YELLOW_("0x000b3f80") " command ans:"); - switch_off_field_14b(); - free(packet); - return true; - } else if (status > 0) { - PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); - PrintAndLogEx(SUCCESS, "unknown tag type answered to a " _YELLOW_("0x000b3f80") " command ans:"); - PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp.data.asBytes, status)); + PrintAndLogEx(SUCCESS, "unknown tag type answered to a " _YELLOW_("0x000b3f80") " command"); switch_off_field_14b(); free(packet); return true; @@ -1141,27 +1149,10 @@ static bool HF14B_other_reader(bool verbose) { packet->raw[0] = ISO14443B_AUTHENTICATE; clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); - if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { - if (verbose) { - PrintAndLogEx(WARNING, "timeout while waiting for reply"); - } - switch_off_field_14b(); - free(packet); - return false; - } - status = resp.oldarg[0]; - PrintAndLogEx(DEBUG, "status %d", status); - if (status == 0) { + if (wait_cmd_14b(verbose, false, -1)) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); - PrintAndLogEx(SUCCESS, "Unknown tag type answered to a " _YELLOW_("0x0A") " command ans:"); - switch_off_field_14b(); - free(packet); - return true; - } else if (status > 0) { - PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); - PrintAndLogEx(SUCCESS, "unknown tag type answered to a " _YELLOW_("0x0A") " command ans:"); - PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp.data.asBytes, status)); + PrintAndLogEx(SUCCESS, "Unknown tag type answered to a " _YELLOW_("0x0A") " command"); switch_off_field_14b(); free(packet); return true; @@ -1171,25 +1162,9 @@ static bool HF14B_other_reader(bool verbose) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); free(packet); - if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { - if (verbose) { - PrintAndLogEx(WARNING, "timeout while waiting for reply"); - } - switch_off_field_14b(); - return false; - } - status = resp.oldarg[0]; - PrintAndLogEx(DEBUG, "status %d", status); - - if (status == 0) { + if (wait_cmd_14b(verbose, false, -1)) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); - PrintAndLogEx(SUCCESS, "Unknown tag type answered to a " _YELLOW_("0x0C") " command ans:"); - switch_off_field_14b(); - return true; - } else if (status > 0) { - PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); - PrintAndLogEx(SUCCESS, "unknown tag type answered to a " _YELLOW_("0x0C") " command ans:"); - PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp.data.asBytes, status)); + PrintAndLogEx(SUCCESS, "Unknown tag type answered to a " _YELLOW_("0x0C") " command"); switch_off_field_14b(); return true; } @@ -1362,7 +1337,6 @@ static int CmdHF14BWriteSri(const char *Cmd) { } char str[36] = {0x00}; - memset(str, 0x00, sizeof(str)); snprintf(str, sizeof(str), "--sr -c --data %02x%02x%02x%02x%02x%02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]); return CmdHF14BCmdRaw(str); } @@ -1449,6 +1423,7 @@ static int CmdHF14BDump(const char *Cmd) { // detect blocksize from card :) PrintAndLogEx(INFO, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen)); + iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + 2); if (packet == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); @@ -1465,8 +1440,8 @@ static int CmdHF14BDump(const char *Cmd) { // select SR tag int status; if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { - status = resp.oldarg[0]; - if (status < 0) { + status = resp.status; + if (status != PM3_SUCCESS) { PrintAndLogEx(FAILED, "failed to select arg0[%" PRId64 "]", resp.oldarg[0]); free(packet); return switch_off_field_14b(); @@ -1491,8 +1466,8 @@ static int CmdHF14BDump(const char *Cmd) { SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t) + 2); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { - status = resp.oldarg[0]; - if (status < 0) { + status = resp.status; + if (status != PM3_SUCCESS) { PrintAndLogEx(FAILED, "retrying one more time"); continue; } @@ -1665,8 +1640,9 @@ static int srix4kValid(const char *Cmd) { */ int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) { - if (card) + if (card) { memset(card, 0, sizeof(iso14b_card_select_t)); + } switch_off_field_14b(); @@ -1699,12 +1675,12 @@ int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) { } // check result - int status = resp.oldarg[0]; - if (status < 0) { + if (resp.status != PM3_SUCCESS) { PrintAndLogEx(WARNING, "No ISO14443-B Card in field"); switch_off_field_14b(); return PM3_ESOFT; } + SetISODEPState(ISODEP_NFCB); apdu_frame_length = 0; // get frame length from ATS in card data structure @@ -1733,8 +1709,9 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, if (activateField) { // select with no disconnect and set frameLength int selres = select_card_14443b_4(false, NULL); - if (selres != PM3_SUCCESS) + if (selres != PM3_SUCCESS) { return selres; + } } iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + datainlen); @@ -1746,8 +1723,9 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, packet->timeout = 0; packet->rawlen = 0; - if (chainingin) + if (chainingin) { packet->flags = (ISO14B_SEND_CHAINING | ISO14B_APDU); + } if (user_timeout > 0) { packet->flags |= ISO14B_SET_TIMEOUT; @@ -1777,8 +1755,15 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, return PM3_ETIMEOUT; } - int rlen = resp.oldarg[0]; - int dlen = rlen - 2; + if ( resp.status != PM3_SUCCESS) { + PrintAndLogEx(ERR, "APDU: no APDU response"); + return resp.status; + } + + iso14b_raw_apdu_response_t *apdu = (iso14b_raw_apdu_response_t *)resp.data.asBytes; + + // remove crc bytes + int dlen = apdu->datalen - 2; if (dlen < 0) { dlen = 0; } @@ -1786,33 +1771,28 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, *dataoutlen += dlen; if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "APDU: buffer too small(%d), needs %d bytes", maxdataoutlen, *dataoutlen); + PrintAndLogEx(ERR, "APDU: buffer too small ( " _RED_("%d") " ), needs " _YELLOW_("%d") " bytes", maxdataoutlen, *dataoutlen); return PM3_ESOFT; } // I-block ACK - uint8_t res = resp.oldarg[1]; - if ((res & 0xF2) == 0xA2) { + if ((apdu->response_byte & 0xF2) == 0xA2) { *dataoutlen = 0; *chainingout = true; return PM3_SUCCESS; } - if (rlen < 0) { - PrintAndLogEx(ERR, "APDU: no APDU response"); - return PM3_ESOFT; - } - // check apdu length - if (rlen == 0 || rlen == 1) { - PrintAndLogEx(ERR, "APDU: small APDU response, len %d", rlen); + if (apdu->datalen < 2) { + PrintAndLogEx(ERR, "APDU: small APDU response, len " _RED_("%d"), apdu->datalen); return PM3_ESOFT; } - - memcpy(dataout, resp.data.asBytes, dlen); + + // copy to output array + memcpy(dataout, apdu->data, dlen); // chaining - if ((res & 0x10) != 0) { + if ((apdu->response_byte & 0x10) != 0) { *chainingout = true; } return PM3_SUCCESS; @@ -2208,7 +2188,6 @@ static int CmdHF14BView(const char *Cmd) { return PM3_SUCCESS; } - static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"apdu", CmdHF14BAPDU, IfPm3Iso14443b, "Send ISO 14443-4 APDU to tag"}, diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index ef0979182..55a9802be 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -116,15 +116,16 @@ static bool get_14b_UID(iso14b_card_select_t *card) { SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (resp.oldarg[0] == 0) { + if (resp.status == PM3_SUCCESS) { memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); return true; } } } // retry - if (retry <= 0) + if (retry <= 0) { PrintAndLogEx(FAILED, "command execution timeout"); + } return false; } @@ -148,22 +149,20 @@ static int infoHFCryptoRF(bool verbose) { return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); - - uint64_t status = resp.oldarg[0]; - - switch (status) { - case 0: + switch (resp.status) { + case PM3_SUCCESS: { + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); return PM3_SUCCESS; - case 2: + } + case PM3_ELENGTH: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; - case 3: + case PM3_ECRC: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); break; default: @@ -209,16 +208,16 @@ int readHFCryptoRF(bool loop, bool verbose) { PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t status = resp.oldarg[0] & 0xFF; - if (loop) { - if (status != 0) { + if (resp.status != PM3_SUCCESS) { continue; } } else { // when not in continuous mode - if (status != 0) { - if (verbose) PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed"); + if (resp.status != PM3_SUCCESS) { + if (verbose) { + PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed"); + } res = PM3_EOPABORTED; break; } @@ -322,11 +321,9 @@ static int CmdHFCryptoRFDump(const char *Cmd) { PacketResponseNG resp; // select - int status; if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { - status = resp.oldarg[0]; - if (status < 0) { - PrintAndLogEx(FAILED, "failed to select %" PRId64 "]", resp.oldarg[0]); + if (resp.status != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "failed to select %" PRId64 "]", resp.status); free(packet); return switch_off_field_cryptorf(); } @@ -350,13 +347,12 @@ static int CmdHFCryptoRFDump(const char *Cmd) { SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t) + 2); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { - status = resp.oldarg[0]; - if (status < 0) { + if (resp.status != PM3_SUCCESS) { PrintAndLogEx(FAILED, "retrying one more time"); continue; } - uint16_t len = (resp.oldarg[1] & 0xFFFF); + uint16_t len = resp.length; uint8_t *recv = resp.data.asBytes; if (check_crc(CRC_14443_B, recv, len) == false) { @@ -446,7 +442,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { size_t datalen = CRYPTORF_MEM_SIZE; // set up buffer uint8_t *data = calloc(datalen, sizeof(uint8_t)); - if (!data) { + if (data == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; } @@ -477,7 +473,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { } */ free(data); - PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent); + PrintAndLogEx(SUCCESS, "sent " _YELLOW_("%d") " bytes of data to device emulator memory", bytes_sent); return PM3_SUCCESS; } diff --git a/client/src/cmdhfxerox.c b/client/src/cmdhfxerox.c index 5f6f1e11c..88f910dfa 100644 --- a/client/src/cmdhfxerox.c +++ b/client/src/cmdhfxerox.c @@ -383,8 +383,9 @@ static int switch_off_field(void) { static int findXerox(iso14b_card_select_t *card, bool disconnect) { - if (card == NULL) + if (card == NULL) { return PM3_EINVARG; + } int8_t retry = 3; while (retry--) { @@ -399,10 +400,10 @@ static int findXerox(iso14b_card_select_t *card, bool disconnect) { PacketResponseNG resp; if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (resp.oldarg[0] == 0) { + if (resp.status == PM3_SUCCESS) { memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); } - return resp.oldarg[0]; + return resp.length; } } // retry @@ -513,7 +514,7 @@ static int CmdHFXeroxInfo(const char *Cmd) { if (verbose) { PrintAndLogEx(FAILED, "Fuji/Xerox tag select failed"); } - return PM3_ERFTRANS; + return status; } PrintAndLogEx(NORMAL, ""); @@ -551,7 +552,7 @@ static int CmdHFXeroxInfo(const char *Cmd) { */ // 14b raw command send data_len instead of status - if (/*resp.status != 0 ||*/ resp.length < 7) { + if (resp.length < 7) { PrintAndLogEx(FAILED, "retrying one more time"); continue; } @@ -655,7 +656,8 @@ static int CmdHFXeroxDump(const char *Cmd) { resp.cmd, resp.length, resp.magic, resp.status, resp.crc, resp.oldarg[0], resp.oldarg[1], resp.oldarg[2], resp.data.asBytes[0], resp.data.asBytes[1], resp.data.asBytes[2], resp.ng ? 't' : 'f'); */ - if (/*resp.status != 0 ||*/ resp.length < 7) { // 14b raw command send data_len instead of status + + if (resp.length < 7) { PrintAndLogEx(FAILED, "retrying one more time"); continue; } @@ -689,8 +691,9 @@ static int CmdHFXeroxDump(const char *Cmd) { PrintAndLogEx(NORMAL, ""); - if (blocknum != 0x100) + if (blocknum != 0x100) { PrintAndLogEx(FAILED, "dump failed at block %d", blocknum); + } if (decrypt) { PrintAndLogEx(INFO, "Decrypting secret blocks..."); @@ -744,12 +747,14 @@ static int CmdHFXeroxDump(const char *Cmd) { uint16_t cs, csd; // calc checksum - for (b = 0, cs = 0; b < sizeof(decr) - 2; b += 2) cs += decr[b] | (decr[b + 1] << 8); + for (b = 0, cs = 0; b < sizeof(decr) - 2; b += 2) { + cs += decr[b] | (decr[b + 1] << 8); + } cs = ~cs; csd = (decr[7] << 8) | decr[6]; if (cs != csd) { - PrintAndLogEx(FAILED, "secret block %02X checksum failed.", dadr); + PrintAndLogEx(FAILED, "Secret block %02X checksum " _RED_("failed"), dadr); } } } diff --git a/include/iso14b.h b/include/iso14b.h index e809ef2c0..9089cd3d3 100644 --- a/include/iso14b.h +++ b/include/iso14b.h @@ -64,6 +64,11 @@ typedef struct { uint8_t raw[]; } PACKED iso14b_raw_cmd_t; +typedef struct { + uint8_t response_byte; + uint16_t datalen; + uint8_t data[]; +} PACKED iso14b_raw_apdu_response_t; #define US_TO_SSP(x) ( (int32_t) ((x) * 3.39) ) #define SSP_TO_US(x) ( (int32_t)((x) / 3.39) ) diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index abee08bb2..06dbe057a 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -820,6 +820,9 @@ typedef struct { // No PACS data pm3: when using HID SAM to retried PACS data #define PM3_ENOPACS -26 +// Got wrong length error pm3: when received wrong length of data +#define PM3_ELENGTH -27 + // No data pm3: no data available, no host frame available (not really an error) #define PM3_ENODATA -98 // Quit program client: reserved, order to quit the program