gave 14b commands some serious love and overhaul. package handling for APDU and different selects is improved. return codes now consequent

This commit is contained in:
iceman1001 2024-01-08 21:17:42 +01:00
parent 5709d8959d
commit 82aa6ac08c
11 changed files with 350 additions and 337 deletions

View file

@ -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: {

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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

View file

@ -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'

View file

@ -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"},

View file

@ -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;
}

View file

@ -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);
}
}
}

View file

@ -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) )

View file

@ -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