mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-08-28 11:44:12 +00:00
since it still felt a bit slow, Claude came up with the idea of burst mode transfers. A new sim module firmware 'sim022.bin' and we now can auto-negotiate for TA1 = 0x95 which give us 125 000 bits/s which is almost 10x from the 10752 bits/s we were doing before. Thanks Claude!
This commit is contained in:
@@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added `sim022.bin` - enabled burst mode transfers, which allows us to do TA1=96 in speeds (@iceman1001)
|
||||
- Fixed `hf felica liteauth` - empty long option names for `-c` and `-k` made argtable read past the string (found by ASAN on `--fulltext`) (@Msprg)
|
||||
- Added `sim020.bin` - v4.60 of sim module firmware, better T=0 handling and clock etu handling (@iceman1001)
|
||||
- Fixed `hf seos sam` - now have a invalid pacs guard (@iceman1001)
|
||||
|
||||
+41
-9
@@ -974,11 +974,17 @@ static uint8_t atr_first_proto(const uint8_t *atr, uint8_t len) {
|
||||
// rejected every Fi=768/1024/1536/2048 offer.
|
||||
// - R = Fi / (16 * Di) is the module's UART reload. It has to be a whole
|
||||
// number or the sampling point drifts - that is the +3.2% which makes
|
||||
// Fi=372 unusable beyond Di=1 - and it must not fall below the floor: R=8
|
||||
// (31250 bit/s) transfers cleanly here, R=4 does not.
|
||||
// Fi=372 unusable beyond Di=1 - and it must not fall below the floor.
|
||||
//
|
||||
// The floor is measured, not guessed. It was 8 while the module still waited
|
||||
// out a turnaround guard before listening, which cost it the second byte of
|
||||
// every answer above 31250 bit/s. With that guard applied only before
|
||||
// transmitting (module v4.62), R=2 (125000 bit/s) is clean over repeated runs
|
||||
// and R=1 still is not: at 16 clocks per etu a character is 192 instruction
|
||||
// cycles, and the receive loop does not fit in that.
|
||||
//
|
||||
// A card with no TA1 offers nothing but the default, so nothing is proposed.
|
||||
#define SC_PPS_MIN_RELOAD 8
|
||||
#define SC_PPS_MIN_RELOAD 2
|
||||
|
||||
static uint8_t sc_pps_best_ta1(const uint8_t *atr, uint8_t len) {
|
||||
|
||||
@@ -1112,9 +1118,13 @@ bool GetATR(smart_card_atr_t *card_ptr, bool verbose) {
|
||||
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"
|
||||
// What the ATR advertises, and which of them the card actually runs
|
||||
// until something negotiates otherwise. Saying only "offers T=0 T=1"
|
||||
// reads like a state report when it is a capability list.
|
||||
Dbprintf("SC: ATR offers%s%s, card runs T=%u"
|
||||
, (s_card_protocols & SC_PROTO_T0) ? " T=0" : ""
|
||||
, (s_card_protocols & SC_PROTO_T1) ? " T=1" : ""
|
||||
, atr_first_proto(card_ptr->atr, card_ptr->atr_len)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1385,7 +1395,12 @@ void SmartCardPPS(const smart_card_pps_t *p) {
|
||||
|
||||
uint8_t req[2];
|
||||
uint16_t reqlen = 1;
|
||||
req[0] = (uint8_t)(p->protocol & 0x0F);
|
||||
uint8_t want_proto = p->protocol;
|
||||
if (want_proto == SC_PPS_PROTO_CARD_DEFAULT) {
|
||||
want_proto = atr_first_proto(card.atr, card.atr_len);
|
||||
}
|
||||
|
||||
req[0] = (uint8_t)(want_proto & 0x0F);
|
||||
if (p->use_ta1) {
|
||||
req[1] = p->ta1;
|
||||
reqlen = 2;
|
||||
@@ -1406,14 +1421,31 @@ void SmartCardPPS(const smart_card_pps_t *p) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
// resp is [ok][active protocol][ta1 in force]. Remember a rate that is
|
||||
// actually faster than the default so later ATRs can put it back; 0x11 is
|
||||
// the default and means "forget what we had".
|
||||
// resp is [ok][active protocol][ta1 in force].
|
||||
//
|
||||
// Only a rate is worth remembering. A protocol override is a deliberate
|
||||
// one-off - `smart pps` defaults to T=1, so asking for a rate alone
|
||||
// switches the card's framing - and making that stick across every later
|
||||
// ATR breaks anything that builds T=0 APDUs, the SAM commands included.
|
||||
// Leave it to this session and do not cache it.
|
||||
if (resp[0] == 1) {
|
||||
if (resp[2] != 0x11) {
|
||||
|
||||
uint8_t card_proto = atr_first_proto(card.atr, card.atr_len);
|
||||
|
||||
if (resp[2] == 0x11) {
|
||||
sc_pps_forget(); // back to the default rate
|
||||
|
||||
} else if (resp[1] == card_proto) {
|
||||
sc_pps_remember(card.atr, card.atr_len, resp[1], resp[2]);
|
||||
|
||||
} else {
|
||||
// rate negotiated alongside a protocol change: honour it now, but
|
||||
// do not restore it later behind the user's back
|
||||
sc_pps_forget();
|
||||
if (g_dbglevel >= DBG_ERROR) {
|
||||
Dbprintf("SC: T=%u selected, rate not remembered (card offers T=%u first)",
|
||||
resp[1], card_proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
9714ecc830e0dfb9180147c7c2300f0e8e1a5ce5a4b126f929010dd180b278a508dde0312eb2271e866650baf9ccaa6cc7f5cc9612c914a31cbc8efd83471c90 *client/resources/sim022.bin
|
||||
+27
-20
@@ -476,10 +476,10 @@ static int CmdSmartRaw(const char *Cmd) {
|
||||
CLIParserInit(&ctx, "smart raw",
|
||||
"Sends raw bytes to card",
|
||||
"smart raw -s -0 -d 00a404000e315041592e5359532e4444463031 -> `1PAY.SYS.DDF01` PPSE directory with get ATR\n"
|
||||
"smart raw -0 -d 00a404000e325041592e5359532e4444463031 -> `2PAY.SYS.DDF01` PPSE directory\n"
|
||||
"smart raw -0 -t -d 00a4040007a0000000041010 -> Mastercard\n"
|
||||
"smart raw -0 -t -d 00a4040007a0000000031010 -> Visa\n"
|
||||
"smart raw -1 -s -d 00a404000e325041592e5359532e444446303100 -> PPSE over T=1\n"
|
||||
"smart raw --t0 -d 00a404000e325041592e5359532e4444463031 -> `2PAY.SYS.DDF01` PPSE directory\n"
|
||||
"smart raw --t0 -t -d 00a4040007a0000000041010 -> Mastercard\n"
|
||||
"smart raw --t0 -t -d 00a4040007a0000000031010 -> Visa\n"
|
||||
"smart raw --t1 -s -d 00a404000e325041592e5359532e444446303100 -> PPSE over T=1\n"
|
||||
" (T=1 carries the whole APDU, so case 4 needs its Le)"
|
||||
);
|
||||
|
||||
@@ -489,8 +489,8 @@ static int CmdSmartRaw(const char *Cmd) {
|
||||
arg_lit0("a", NULL, "active smartcard without select (reset sc module)"),
|
||||
arg_lit0("s", NULL, "active smartcard with select (get ATR)"),
|
||||
arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
|
||||
arg_lit0("0", NULL, "use protocol T=0"),
|
||||
arg_lit0("1", NULL, "use protocol T=1 (needs SIM module fw v4.51+)"),
|
||||
arg_lit0(NULL, "t0", "use protocol T=0"),
|
||||
arg_lit0(NULL, "t1", "use protocol T=1 (needs SIM module fw v4.51+)"),
|
||||
arg_int0(NULL, "timeout", "<ms>", "Timeout in MS waiting for SIM to respond. (def 337ms)"),
|
||||
arg_str1("d", "data", "<hex>", "bytes to send"),
|
||||
arg_param_end
|
||||
@@ -921,29 +921,34 @@ static int CmdSmartPPS(const char *Cmd) {
|
||||
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "smart pps",
|
||||
"Run an ISO 7816-3 protocol and parameter selection exchange.\n"
|
||||
"Run an ISO 7816-3 protocol and parameter selection exchange.\n""\n"
|
||||
"With neither --t0 nor --t1 the card keeps the protocol its ATR\n"
|
||||
"says it runs, so --ta1 on its own changes the rate and nothing else.\n"
|
||||
"The card is reset and its ATR read first, because PPS is only\n"
|
||||
"legal in the window straight after the ATR.\n"
|
||||
"\n"
|
||||
"Note `smart raw -1` already switches a card to T=1 by itself when\n"
|
||||
"Note `smart raw --t1` already switches a card to T=1 by itself when\n"
|
||||
"the ATR offers it; this is for negotiating Fi/Di explicitly.\n"
|
||||
"Needs SIM module firmware v4.51 or newer.\n"
|
||||
"\n"
|
||||
"The negotiated rate only holds for the rest of this session, and\n"
|
||||
"only for commands that do not reset the card. Connecting a client\n"
|
||||
"reads the module version, which reboots the module back to the\n"
|
||||
"default rate while the card stays at the negotiated one - the next\n"
|
||||
"command then fails until something resets the card. `smart info`,\n"
|
||||
"or any `smart raw -s`, puts both back to the default.",
|
||||
"smart pps -1 -> select T=1\n"
|
||||
"smart pps -0 -> select T=0\n"
|
||||
"smart pps -1 --ta1 96 -> select T=1 and F=512 / D=32"
|
||||
"A negotiated rate is remembered against this card's ATR and put\n"
|
||||
"back after every later ATR, so it survives resets and reconnects.\n"
|
||||
"A different card drops it, and `--ta1 11` forgets it.\n"
|
||||
"\n"
|
||||
"A protocol change is not remembered: it applies until the next\n"
|
||||
"reset only, so it cannot silently break commands that build for\n"
|
||||
"the other protocol.",
|
||||
"smart pps --ta1 93 -> rate only, framing left alone\n"
|
||||
"smart pps --ta1 11 -> back to the default rate\n"
|
||||
"smart pps --t1 -> select T=1\n"
|
||||
"smart pps --t0 -> select T=0\n"
|
||||
"smart pps --t1 --ta1 96 -> select T=1 and F=512 / D=32"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("0", NULL, "select protocol T=0"),
|
||||
arg_lit0("1", NULL, "select protocol T=1 (default)"),
|
||||
arg_lit0(NULL, "t0", "select protocol T=0"),
|
||||
arg_lit0(NULL, "t1", "select protocol T=1"),
|
||||
arg_str0(NULL, "ta1", "<hex>", "also negotiate this TA1 (FI << 4 | DI)"),
|
||||
arg_param_end
|
||||
};
|
||||
@@ -968,7 +973,9 @@ static int CmdSmartPPS(const char *Cmd) {
|
||||
}
|
||||
|
||||
smart_card_pps_t payload = {
|
||||
.protocol = use_t0 ? 0 : 1,
|
||||
// Neither flag: negotiate the rate and leave the framing alone. The
|
||||
// device resolves this to whatever the card's ATR says it runs.
|
||||
.protocol = use_t0 ? 0 : (use_t1 ? 1 : SC_PPS_PROTO_CARD_DEFAULT),
|
||||
.ta1 = (ta1len > 0) ? ta1[0] : 0x11,
|
||||
.use_ta1 = (ta1len > 0) ? 1 : 0,
|
||||
};
|
||||
|
||||
+6
-1
@@ -513,8 +513,13 @@ typedef struct {
|
||||
uint8_t data[];
|
||||
} PACKED smart_card_raw_t;
|
||||
|
||||
// A PPS has to name a protocol - PPS0 has no "leave it alone" encoding - so
|
||||
// when the caller only wants a rate, ask for the one the card already runs and
|
||||
// the exchange changes nothing but Fi/Di.
|
||||
#define SC_PPS_PROTO_CARD_DEFAULT 0xFF
|
||||
|
||||
typedef struct {
|
||||
uint8_t protocol; // T to select, 0 or 1
|
||||
uint8_t protocol; // T to select, 0 or 1, or SC_PPS_PROTO_CARD_DEFAULT
|
||||
uint8_t ta1; // FI << 4 | DI, only read when use_ta1 is set
|
||||
uint8_t use_ta1;
|
||||
} PACKED smart_card_pps_t;
|
||||
|
||||
Reference in New Issue
Block a user