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
commit 82aa6ac08c
11 changed files with 350 additions and 337 deletions

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