mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
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:
parent
5709d8959d
commit
82aa6ac08c
|
@ -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: {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) )
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue