mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-09-12 17:46:37 +00:00
fixed timings, T=1 <> T=0 swaps when emv card doesn't support T=0,
This commit is contained in:
+122
-30
@@ -37,20 +37,22 @@
|
||||
|
||||
#define I2C_ERROR "I2C_WaitAck Error"
|
||||
|
||||
// delay=1 is about 200kbps
|
||||
// I2CSpinDelayClk(4) about 12us
|
||||
// I2CSpinDelayClk(1) about 3us
|
||||
// static void I2CSpinDelayClk(const uint16_t delay) {
|
||||
// for (uint16_t i = 0; i < delay; i++) {
|
||||
// SpinDelayUsPrecision(2);
|
||||
// }
|
||||
// }
|
||||
// Bus timing lives in i2c.h alongside the timeouts derived from it, so the two
|
||||
// cannot drift apart.
|
||||
#define I2C_DELAY_1CLK SpinDelayUsPrecision(I2C_DELAY_1CLK_US)
|
||||
#define I2C_DELAY_2CLK SpinDelayUsPrecision(I2C_DELAY_2CLK_US)
|
||||
|
||||
// TODO DXL 修改了速度到比较慢的情况,测完需要改回来,原先是2和4
|
||||
#define SC_PROTO_T0 (1 << 0)
|
||||
#define SC_PROTO_T1 (1 << 1)
|
||||
|
||||
#define I2C_DELAY_1CLK SpinDelayUsPrecision(20)
|
||||
#define I2C_DELAY_2CLK SpinDelayUsPrecision(22)
|
||||
// #define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x))
|
||||
// Protocols the last ATR offered, as a bit mask of (1 << T). Zero means we do
|
||||
// not know - no ATR has been read since the module was last reset.
|
||||
static uint8_t s_card_protocols = 0;
|
||||
|
||||
// Whether the protocol choice has already been reported this session. These
|
||||
// messages are worth seeing once; sc_raw_device_cmd() runs per APDU, and an
|
||||
// EMV AID sweep is 150 of them.
|
||||
static bool s_proto_announced = false;
|
||||
|
||||
// try i2c bus recovery at 100kHz = 5us high, 5us low
|
||||
void I2C_recovery(void) {
|
||||
@@ -120,6 +122,9 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
|
||||
// Reset the SIM_Adapter, then enter the main program
|
||||
// Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
|
||||
void I2C_Reset_EnterMainProgram(void) {
|
||||
// whatever we knew about the card is no longer trustworthy
|
||||
s_card_protocols = 0;
|
||||
s_proto_announced = false;
|
||||
StartTicks();
|
||||
I2C_init(true);
|
||||
I2C_SetResetStatus(0, 0, 0);
|
||||
@@ -152,10 +157,8 @@ static bool WaitSCL_H_delay(uint32_t delay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5000 * 3.07us = 15350 us = 15.35 ms
|
||||
// 15000 * 3.07us = 46050 us = 46.05 ms
|
||||
static bool WaitSCL_H(void) {
|
||||
return WaitSCL_H_delay(5000);
|
||||
return WaitSCL_H_delay(I2C_ITERS_FOR_MS(I2C_STRETCH_TIMEOUT_MS));
|
||||
}
|
||||
|
||||
static bool WaitSCL_L_delay(uint32_t delay) {
|
||||
@@ -168,10 +171,8 @@ static bool WaitSCL_L_delay(uint32_t delay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5000 * 3.07us = 15350us. 15.35ms
|
||||
// 15000 * 3.07us = 46050us. 46.05ms
|
||||
static bool WaitSCL_L(void) {
|
||||
return WaitSCL_L_delay(5000);
|
||||
return WaitSCL_L_delay(I2C_ITERS_FOR_MS(I2C_STRETCH_TIMEOUT_MS));
|
||||
}
|
||||
|
||||
// How long to allow the SIM module to *start* an operation, i.e. to pull SCL
|
||||
@@ -235,14 +236,7 @@ static bool I2C_WaitForSim(uint32_t wait) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 8051 speaks with smart card.
|
||||
// 1000*50*3.07 = 153.5ms
|
||||
// 1000*110*3.07 = 337.7ms (337700)
|
||||
// 4 560 000 * 3.07 = 13999,2ms (13999200)
|
||||
// 1byte transfer == 1ms with max frame being 256bytes
|
||||
|
||||
// fct WaitSCL_H_delay uses a I2C_DELAY_1CLK in the loop with "wait" as number of iterations.
|
||||
// I2C_DELAY_1CLK == I2CSpinDelayClk(1) = 3.07us
|
||||
// wait is an iteration count; build it with I2C_ITERS_FOR_MS().
|
||||
return WaitSCL_H_delay(wait);
|
||||
}
|
||||
|
||||
@@ -854,13 +848,97 @@ bool sc_rx_bytes(uint8_t *dest, uint16_t *destlen, uint32_t wait) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* ISO/IEC 7816-3 clause 8: the protocols on offer are the low nibbles of the
|
||||
* TDi bytes. With no TD1 at all, only T=0 is offered. T=15 carries global
|
||||
* interface bytes rather than a transmission protocol and is ignored here.
|
||||
*/
|
||||
static uint8_t atr_protocols(const uint8_t *atr, uint8_t len) {
|
||||
|
||||
if (len < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t y = (uint8_t)(atr[1] >> 4); // T0
|
||||
uint8_t i = 2;
|
||||
uint8_t mask = 0;
|
||||
|
||||
while (y) {
|
||||
|
||||
if (y & 0x01) i++; // TA(i)
|
||||
if (y & 0x02) i++; // TB(i)
|
||||
if (y & 0x04) i++; // TC(i)
|
||||
|
||||
if ((y & 0x08) == 0) {
|
||||
break; // no TD(i), nothing further named
|
||||
}
|
||||
if (i >= len) {
|
||||
break; // truncated ATR
|
||||
}
|
||||
|
||||
uint8_t td = atr[i++];
|
||||
uint8_t t = (uint8_t)(td & 0x0F);
|
||||
if (t < 8) {
|
||||
mask |= (uint8_t)(1u << t);
|
||||
}
|
||||
y = (uint8_t)(td >> 4);
|
||||
}
|
||||
|
||||
if (mask == 0) {
|
||||
mask = SC_PROTO_T0; // clause 8.2.3
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
uint8_t sc_raw_device_cmd(smartcard_command_t flags) {
|
||||
|
||||
// An explicit T=1 request is always honoured as asked - it is an override,
|
||||
// and a card that supports T=1 without advertising it is a real thing. But
|
||||
// say so when the ATR disagrees, because the alternative is silence from
|
||||
// the card and no clue why.
|
||||
if ((flags & SC_RAW_T1) == SC_RAW_T1) {
|
||||
|
||||
if ((s_card_protocols != 0) && ((s_card_protocols & SC_PROTO_T1) == 0)) {
|
||||
if ((g_dbglevel >= DBG_ERROR) && (s_proto_announced == false)) {
|
||||
s_proto_announced = true;
|
||||
DbpString("SC: " _YELLOW_("card offers no T=1") ", sending it anyway");
|
||||
}
|
||||
}
|
||||
return I2C_DEVICE_CMD_SEND_T1;
|
||||
}
|
||||
|
||||
if ((flags & SC_RAW_T0) == SC_RAW_T0) {
|
||||
|
||||
/*
|
||||
* A T=0 request to a card whose ATR offers no T=0 cannot work - the
|
||||
* card will not hear it at all, which shows up as silence rather than
|
||||
* an error. Most modern EMV and JCOP cards are T=1 only, and callers
|
||||
* like ExchangeAPDUSC() ask for T=0 unconditionally.
|
||||
*
|
||||
* Only this one case is redirected, and only once an ATR has actually
|
||||
* been read. A card that does offer T=0 is left alone even if it also
|
||||
* offers T=1, because there the caller's choice is a real one - use
|
||||
* SC_RAW_T1 to say otherwise.
|
||||
*
|
||||
* Note this cannot make anything worse even against a SIM module too
|
||||
* old to know SEND_T1: in the exact case it fires, the request as given
|
||||
* was already guaranteed to fail.
|
||||
*/
|
||||
if ((s_card_protocols != 0) &&
|
||||
((s_card_protocols & SC_PROTO_T0) == 0) &&
|
||||
((s_card_protocols & SC_PROTO_T1) == SC_PROTO_T1)) {
|
||||
|
||||
if ((g_dbglevel >= DBG_INFO) && (s_proto_announced == false)) {
|
||||
s_proto_announced = true;
|
||||
DbpString("SC: card offers no T=0, sending as T=1");
|
||||
}
|
||||
return I2C_DEVICE_CMD_SEND_T1;
|
||||
}
|
||||
|
||||
return I2C_DEVICE_CMD_SEND_T0;
|
||||
}
|
||||
|
||||
// Raw pass through: the host owns the framing, so never second guess it.
|
||||
return I2C_DEVICE_CMD_SEND;
|
||||
}
|
||||
|
||||
@@ -918,6 +996,16 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
||||
}
|
||||
|
||||
card_ptr->atr_len = (uint8_t)(len & 0xff);
|
||||
|
||||
s_card_protocols = atr_protocols(card_ptr->atr, card_ptr->atr_len);
|
||||
s_proto_announced = false;
|
||||
if (g_dbglevel >= DBG_INFO) {
|
||||
Dbprintf("SC: card offers%s%s"
|
||||
, (s_card_protocols & SC_PROTO_T0) ? " T=0" : ""
|
||||
, (s_card_protocols & SC_PROTO_T1) ? " T=1" : ""
|
||||
);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
|
||||
}
|
||||
@@ -981,10 +1069,14 @@ void SmartCardRaw(const smart_card_raw_t *p) {
|
||||
|
||||
uint32_t wait = SIM_WAIT_DELAY;
|
||||
if ((flags & SC_WAIT) == SC_WAIT) {
|
||||
// wait_delay is in ms; one WaitSCL_H_delay iteration is ~3.07us.
|
||||
// Integer-only conversion via uint64_t to avoid soft-float and avoid
|
||||
// overflow at large wait_delay values: (ms * 100000 + 153) / 307.
|
||||
wait = (uint32_t)(((uint64_t)p->wait_delay * 100000U + 153U) / 307U);
|
||||
// Asking for N ms now actually waits N ms. The old conversion
|
||||
// assumed 3.07 us per iteration while the delay had been changed to
|
||||
// 20 us, so `--timeout 1000` sat there for six and a half seconds.
|
||||
uint32_t ms = p->wait_delay;
|
||||
if (ms > I2C_WAIT_MAX_MS) {
|
||||
ms = I2C_WAIT_MAX_MS;
|
||||
}
|
||||
wait = I2C_ITERS_FOR_MS(ms);
|
||||
}
|
||||
|
||||
LogTrace(p->data, p->len, 0, 0, NULL, true);
|
||||
|
||||
+89
-6
@@ -50,12 +50,95 @@
|
||||
// The SIM module v4 supports up to 384 bytes for the length.
|
||||
#define ISO7816_MAX_FRAME 270
|
||||
|
||||
// 8051 speaks with smart card.
|
||||
// 1 byte transfer == 1ms with max frame being 256 bytes.
|
||||
// SIM_WAIT_DELAY is the iteration count passed to WaitSCL_H_delay(); each iter
|
||||
// is ~3.07us, so 150000 * 3.07us = ~460ms - the upper bound we wait for the
|
||||
// SIM module to assert SCL after a SIM-side operation.
|
||||
#define SIM_WAIT_DELAY 150000 // ~460ms total wait via WaitSCL_H_delay
|
||||
/*
|
||||
* Bit banged bus timing.
|
||||
*
|
||||
* I2C_DELAY_1CLK is spent twice per bit and I2C_DELAY_2CLK once, so the bit
|
||||
* period is 2 * 1CLK + 2CLK. At 2/4 us that is ~125 kHz nominal; expect nearer
|
||||
* 90 kHz once SpinDelayUsPrecision()'s own overhead at these short durations is
|
||||
* counted.
|
||||
*
|
||||
* TODO DXL 修改了速度到比较慢的情况,测完需要改回来,原先是2和4
|
||||
*
|
||||
* ("the speed was changed to a slower setting; change it back after testing,
|
||||
* originally 2 and 4")
|
||||
*
|
||||
* That TODO belongs to the HAL refactoring for the Proxmark5 (Artery
|
||||
* AT32F435/437), where SpinDelayUsPrecision() is a different implementation
|
||||
* whose overhead at a two microsecond request has not been measured. The
|
||||
* 20/22 us it was raised to is kept for that platform rather than thrown away.
|
||||
*
|
||||
* Nothing depends on it yet: smartcard support is not built for PM5 - see the
|
||||
* "暂时不要编译i2c" note beside its PLATFORM_DEFS in common_arm/Makefile.hal -
|
||||
* so the AT32 branch below is an unvalidated starting point, not a measurement.
|
||||
* When that bring-up happens, measure the AT32 delay and set it here; every
|
||||
* timeout in this file is derived from these two numbers, so that is the only
|
||||
* place it needs to change.
|
||||
*/
|
||||
/*
|
||||
* 20/22 on both platforms for now.
|
||||
*
|
||||
* Dropping this to 2/4 was tried and the bus stopped working entirely - no ATR,
|
||||
* no answer to anything - even with the delay primitive's overshoot bug fixed
|
||||
* (see SpinDelayUsPrecision in common_arm/ticks/ticks_hw_at91.c). 8 us per bit
|
||||
* is about 125 kHz, and something in the path will not carry it: rise time
|
||||
* through the pull ups is the obvious candidate, but it was not measured.
|
||||
*
|
||||
* Worth revisiting with a scope on SCL and SDA rather than by trial. Every
|
||||
* timeout below is derived from these two numbers, so changing them is a
|
||||
* two line edit once someone knows what the bus can actually do.
|
||||
*/
|
||||
#define I2C_DELAY_1CLK_US 20
|
||||
#define I2C_DELAY_2CLK_US 22
|
||||
|
||||
/*
|
||||
* Every SCL wait loop spends one I2C_DELAY_1CLK per iteration, so the timeouts
|
||||
* below are iteration counts rather than times - which is why changing the
|
||||
* delay used to silently rescale every one of them, and why the constants had
|
||||
* drifted to roughly 6.5x their documented length.
|
||||
*
|
||||
* They are written in milliseconds now and converted in one place, so the two
|
||||
* cannot come apart again. The conversion uses the nominal delay rather than a
|
||||
* measured one on purpose: with the real per-iteration cost being a little
|
||||
* higher, a timeout always lasts at least as long as it asks for.
|
||||
*/
|
||||
#define I2C_ITERS_PER_MS (1000U / I2C_DELAY_1CLK_US)
|
||||
#define I2C_ITERS_FOR_MS(ms) ((uint32_t)(ms) * (uint32_t)I2C_ITERS_PER_MS)
|
||||
|
||||
// How long the master tolerates the slave stretching SCL inside a transfer.
|
||||
#define I2C_STRETCH_TIMEOUT_MS 100
|
||||
|
||||
/*
|
||||
* How long to wait for the SIM module to finish an operation and release SCL.
|
||||
*
|
||||
* This has to cover the card's own thinking time. A T=1 card's block waiting
|
||||
* time is 1.4 s at the default BWI = 4, and a HID iCLASS SE SAM asks for
|
||||
* BWI = 5, i.e. 2.9 s - so 3 s is the smallest value that clears both.
|
||||
*/
|
||||
// Upper bound on a host supplied SC_WAIT, so the conversion cannot overflow.
|
||||
#define I2C_WAIT_MAX_MS 60000
|
||||
|
||||
#define SIM_WAIT_MS 3000
|
||||
#define SIM_WAIT_DELAY I2C_ITERS_FOR_MS(SIM_WAIT_MS)
|
||||
|
||||
/*
|
||||
* Compile time guards on the two numbers above. The build is -std=c99 so this
|
||||
* is the negative array size trick rather than _Static_assert.
|
||||
*/
|
||||
#define I2C_BUILD_ASSERT(cond, name) typedef char i2c_assert_##name[(cond) ? 1 : -1]
|
||||
|
||||
// A delay that does not divide 1000 makes I2C_ITERS_PER_MS silently lose
|
||||
// precision, and every timeout with it.
|
||||
I2C_BUILD_ASSERT((1000U % I2C_DELAY_1CLK_US) == 0, clk_divides_ms);
|
||||
|
||||
// A T=1 card may sit quiet for its whole block waiting time before answering:
|
||||
// 1.4 s at the default BWI = 4, and 2.9 s at the BWI = 5 a HID iCLASS SE SAM
|
||||
// asks for. Shorten this and T=1 starts timing out on slow cards with nothing
|
||||
// to show for it but an empty response.
|
||||
I2C_BUILD_ASSERT(SIM_WAIT_MS >= 3000, sim_wait_covers_bwt);
|
||||
|
||||
// The largest host supplied wait must still fit the iteration counter.
|
||||
I2C_BUILD_ASSERT((uint64_t)I2C_WAIT_MAX_MS * I2C_ITERS_PER_MS <= 0xFFFFFFFFULL, wait_fits_u32);
|
||||
|
||||
|
||||
void I2C_recovery(void);
|
||||
|
||||
+6
-4
@@ -85,10 +85,12 @@ static void SmartCardDirectSend(uint8_t prepend, const smart_card_raw_t *p, uint
|
||||
((flags & SC_RAW_T1) == SC_RAW_T1)) {
|
||||
|
||||
if ((flags & SC_WAIT) == SC_WAIT) {
|
||||
// wait_delay is in ms; one WaitSCL_H_delay iteration is ~3.07us.
|
||||
// Integer-only conversion via uint64_t to avoid soft-float and
|
||||
// avoid overflow at large wait_delay values.
|
||||
wait = (uint32_t)(((uint64_t)p->wait_delay * 100000U + 153U) / 307U);
|
||||
// see the same conversion in SmartCardRaw()
|
||||
uint32_t ms = p->wait_delay;
|
||||
if (ms > I2C_WAIT_MAX_MS) {
|
||||
ms = I2C_WAIT_MAX_MS;
|
||||
}
|
||||
wait = I2C_ITERS_FOR_MS(ms);
|
||||
}
|
||||
|
||||
LogTrace(p->data, p->len, 0, 0, NULL, true);
|
||||
|
||||
@@ -442,8 +442,23 @@ static int smart_responseEx(uint8_t *out, int maxoutlen, bool verbose, uint8_t c
|
||||
goto out;
|
||||
}
|
||||
|
||||
// data wo ACK
|
||||
if (datalen != len + 2) {
|
||||
/*
|
||||
* Two shapes are valid here, depending on how the GET RESPONSE went out:
|
||||
*
|
||||
* len + 2 the data and its status word. This is what SEND_T0
|
||||
* gives, because the module runs the procedure byte
|
||||
* exchange itself and strips the echoed INS.
|
||||
* len + 2 + 1 the same with that procedure byte still in front,
|
||||
* which is what the raw pass through leaves behind.
|
||||
*
|
||||
* Only the second needs unwrapping - but the first used to fall through
|
||||
* both branches without ever adding to totallen, so the caller got zero
|
||||
* bytes and reported "result length = 0" while the card had answered
|
||||
* perfectly. It went unnoticed while GET RESPONSE was always sent raw.
|
||||
*/
|
||||
if (datalen == len + 2) {
|
||||
totallen += datalen;
|
||||
} else {
|
||||
// data with ACK
|
||||
if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK
|
||||
if (out[ofs] != ISO7816_GET_RESPONSE) {
|
||||
@@ -1638,6 +1653,24 @@ int CmdSmartcard(const char *Cmd) {
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Which protocol the contact exchanges below ask for.
|
||||
*
|
||||
* T=0 by default, which is what this has always sent. The ARM side already
|
||||
* redirects a T=0 request to T=1 when the card's ATR offers no T=0 at all - a
|
||||
* request that could not have worked as asked. This is for the other case: a
|
||||
* card that offers both, where T=0 would work but you want T=1 anyway.
|
||||
*/
|
||||
static smartcard_command_t s_sc_protocol = SC_RAW_T0;
|
||||
|
||||
void SetSmartcardProtocolT1(bool use_t1) {
|
||||
s_sc_protocol = use_t1 ? SC_RAW_T1 : SC_RAW_T0;
|
||||
}
|
||||
|
||||
bool GetSmartcardProtocolT1(void) {
|
||||
return (s_sc_protocol == SC_RAW_T1);
|
||||
}
|
||||
|
||||
int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
|
||||
|
||||
*dataoutlen = 0;
|
||||
@@ -1647,7 +1680,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
payload->flags = (SC_RAW_T0 | SC_LOG);
|
||||
payload->flags = (s_sc_protocol | SC_LOG);
|
||||
if (activateCard) {
|
||||
payload->flags |= (SC_SELECT | SC_CONNECT);
|
||||
}
|
||||
@@ -1658,7 +1691,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + datainlen);
|
||||
|
||||
int len = smart_responseEx(dataout, maxdataoutlen, verbose, (datainlen > 0) ? datain[0] : 0x00, SC_RAW);
|
||||
int len = smart_responseEx(dataout, maxdataoutlen, verbose, (datainlen > 0) ? datain[0] : 0x00, s_sc_protocol);
|
||||
if (len < 0) {
|
||||
free(payload);
|
||||
return PM3_ESOFT;
|
||||
@@ -1667,7 +1700,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa
|
||||
// retry
|
||||
if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) {
|
||||
|
||||
payload->flags = SC_RAW_T0;
|
||||
payload->flags = s_sc_protocol;
|
||||
payload->len = 5;
|
||||
// transfer length via T=0
|
||||
datain[4] = dataout[len - 1];
|
||||
@@ -1675,7 +1708,7 @@ int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCa
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_SMART_RAW, (uint8_t *)payload, sizeof(smart_card_raw_t) + 5);
|
||||
datain[4] = 0;
|
||||
len = smart_responseEx(dataout, maxdataoutlen, verbose, datain[0], SC_RAW);
|
||||
len = smart_responseEx(dataout, maxdataoutlen, verbose, datain[0], s_sc_protocol);
|
||||
if (len < 0) {
|
||||
free(payload);
|
||||
return PM3_ESOFT;
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
int CmdSmartcard(const char *Cmd);
|
||||
|
||||
bool smart_select(bool verbose, smart_card_atr_t *atr);
|
||||
// Ask the contact exchanges for T=1 rather than the default T=0. Only needed
|
||||
// for a card that offers both - the ARM redirects a T=1 only card by itself.
|
||||
void SetSmartcardProtocolT1(bool use_t1);
|
||||
bool GetSmartcardProtocolT1(void);
|
||||
|
||||
int ExchangeAPDUSC(bool verbose, uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
||||
|
||||
#endif
|
||||
|
||||
+23
-3
@@ -2776,11 +2776,15 @@ static int CmdEMVReader(const char *Cmd) {
|
||||
"In `verbose` mode it will also try to extract and decode the transaction logs stored on card in either channel.\n",
|
||||
"emv reader\n"
|
||||
"emv reader -v\n"
|
||||
"emv reader -@ -> Continuous mode\n"
|
||||
"emv reader -w -> contact interface\n"
|
||||
"emv reader -w -1 -> contact interface, protocol T=1\n"
|
||||
"emv reader -@ -> Continuous mode\n"
|
||||
);
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("w", "wired", "Send data via contact (iso7816) interface. (def: Contactless interface)"),
|
||||
arg_lit0("0", NULL, "use protocol T=0 (default)"),
|
||||
arg_lit0("1", NULL, "use protocol T=1"),
|
||||
arg_lit0("v", "verbose", "Verbose output"),
|
||||
arg_lit0("@", NULL, "continuous reader mode"),
|
||||
arg_param_end
|
||||
@@ -2792,11 +2796,27 @@ static int CmdEMVReader(const char *Cmd) {
|
||||
channel = CC_CONTACT;
|
||||
}
|
||||
|
||||
bool use_t0 = arg_get_lit(ctx, 2);
|
||||
bool use_t1 = arg_get_lit(ctx, 3);
|
||||
uint8_t psenum = (channel == CC_CONTACT) ? 1 : 2;
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
bool continuous = arg_get_lit(ctx, 3);
|
||||
bool verbose = arg_get_lit(ctx, 4);
|
||||
bool continuous = arg_get_lit(ctx, 5);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
if (use_t0 && use_t1) {
|
||||
PrintAndLogEx(FAILED, "Choose either -0 or -1, not both");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if ((use_t0 || use_t1) && channel != CC_CONTACT) {
|
||||
PrintAndLogEx(FAILED, "-0 and -1 only apply to the contact interface, add -w");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// A card whose ATR offers no T=0 is switched over by the ARM on its own;
|
||||
// this is for one that offers both and would otherwise be driven as T=0.
|
||||
SetSmartcardProtocolT1(use_t1);
|
||||
|
||||
if (continuous) {
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
}
|
||||
|
||||
@@ -329,6 +329,12 @@ static int EMVSelectWithRetry(Iso7816CommandChannel channel, bool ActivateField,
|
||||
|
||||
// retry if error and not returned sw error
|
||||
if (res && res != 5) {
|
||||
|
||||
// a PM3_E* transport failure will not be fixed by asking again
|
||||
if (res < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (++retrycnt < 3) {
|
||||
continue;
|
||||
} else {
|
||||
@@ -379,7 +385,9 @@ static int EMVCheckAID(Iso7816CommandChannel channel, bool decodeTLV, struct tlv
|
||||
return res;
|
||||
}
|
||||
|
||||
int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) {
|
||||
// quiet: the caller has a fallback lined up, so a failure here is a probe
|
||||
// rather than a problem and should not be reported as one.
|
||||
int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv, bool quiet) {
|
||||
uint8_t data[APDU_RES_LEN] = {0};
|
||||
size_t datalen = 0;
|
||||
uint16_t sw = 0;
|
||||
@@ -391,7 +399,9 @@ int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFi
|
||||
|
||||
if (!res) {
|
||||
if (sw != ISO7816_OK) {
|
||||
PrintAndLogEx(FAILED, "Select PSE error. APDU error: %04x.", sw);
|
||||
if (quiet == false) {
|
||||
PrintAndLogEx(FAILED, "Select PSE error. APDU error: %04x.", sw);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -463,7 +473,7 @@ int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFi
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "%s ERROR: Can't get TLV from response.", PSE_or_PPSE);
|
||||
}
|
||||
} else {
|
||||
} else if (quiet == false) {
|
||||
PrintAndLogEx(ERR, "%s ERROR: Can't select PPSE AID. Error: %d", PSE_or_PPSE, res);
|
||||
}
|
||||
|
||||
@@ -492,6 +502,23 @@ int EMVSearch(Iso7816CommandChannel channel, bool ActivateField, bool LeaveField
|
||||
int res = EMVSelect(channel, (i == 0) ? ActivateField : false, true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv);
|
||||
// retry if error and not returned sw error
|
||||
if (res && res != 5) {
|
||||
|
||||
// A negative result is a PM3_E* transport failure rather than
|
||||
// anything the card said - PM3_EIO when the field has gone
|
||||
// inactive, for instance. Retrying the same AID cannot fix that,
|
||||
// and neither can the ~150 AIDs still to come: without this it
|
||||
// retries each of them three times and prints a failure for every
|
||||
// attempt.
|
||||
if (res < 0) {
|
||||
if (LeaveFieldON == false) {
|
||||
DropFieldEx(channel);
|
||||
}
|
||||
if (verbose) {
|
||||
PrintAndLogEx(WARNING, "exiting...");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (++retrycnt < 3) {
|
||||
i--;
|
||||
} else {
|
||||
|
||||
@@ -62,7 +62,7 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2);
|
||||
int EMVExchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU_t apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
|
||||
// search application
|
||||
int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv);
|
||||
int EMVSearchPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv, bool quiet);
|
||||
int EMVSearch(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv, bool verbose);
|
||||
int EMVSelectPSE(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);
|
||||
int EMVSelect(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv);
|
||||
|
||||
@@ -208,9 +208,9 @@ int Iso7816Exchange(Iso7816CommandChannel channel, bool leave_field_on, sAPDU_t
|
||||
int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave_field_on, uint8_t *aid, size_t aid_len,
|
||||
uint8_t *result, size_t max_result_len, size_t *result_len, uint16_t *sw) {
|
||||
|
||||
return Iso7816ExchangeEx(channel
|
||||
, activate_field
|
||||
, leave_field_on
|
||||
int res = Iso7816ExchangeEx(channel
|
||||
, activate_field
|
||||
, leave_field_on
|
||||
, (sAPDU_t) {0x00, 0xa4, 0x04, 0x00, aid_len, aid}
|
||||
, (channel == CC_CONTACTLESS)
|
||||
, 0
|
||||
@@ -218,5 +218,42 @@ int Iso7816Select(Iso7816CommandChannel channel, bool activate_field, bool leave
|
||||
, max_result_len
|
||||
, result_len
|
||||
, sw
|
||||
);
|
||||
);
|
||||
|
||||
/*
|
||||
* A contact card running T=1 needs the Le that a T=0 card must not be
|
||||
* given. T=0 answers a case 4 command with 61xx and hands the data over
|
||||
* through GET RESPONSE, so the Le is left off; T=1 carries the whole APDU
|
||||
* in one block and has no such step, so the command has to ask for its
|
||||
* length up front. Send one without and a strict card answers 6700.
|
||||
*
|
||||
* Rather than work out which protocol the link ended up on - the ARM may
|
||||
* have switched to T=1 on its own, off the ATR, without the client being
|
||||
* told - let the card say so and reissue. EMVReadRecord() and
|
||||
* EMVGenerateChallenge() already do the mirror image of this.
|
||||
*
|
||||
* Only on 6700/6F00, and only on contact: a T=0 card has no reason to
|
||||
* answer a SELECT that way, and if one did the retry costs a single extra
|
||||
* APDU that it will reject just as it rejected the first.
|
||||
*/
|
||||
if ((channel == CC_CONTACT) && (sw != NULL) && ((*sw == 0x6700) || (*sw == 0x6F00))) {
|
||||
|
||||
if (APDULogging) {
|
||||
PrintAndLogEx(INFO, ">>> wrong length, reissuing SELECT with Le...");
|
||||
}
|
||||
|
||||
res = Iso7816ExchangeEx(channel
|
||||
, false
|
||||
, leave_field_on
|
||||
, (sAPDU_t) {0x00, 0xa4, 0x04, 0x00, aid_len, aid}
|
||||
, true
|
||||
, 0
|
||||
, result
|
||||
, max_result_len
|
||||
, result_len
|
||||
, sw
|
||||
);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user