Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hf 14a apdu now uses the FWI and SGFI values from the ATS to determine an appropriate timeout. #2226

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
- Changed `hf 14a apdu` - It now uses the FWI and SGFI values from the ATS to determine an appropriate timeout (@nvx)
- Added a thread to check when device comes online again. It will connect and update prompt (@iceman1001)
- Changed CLI offline prompt - replaces the old prompt when offline is detected (@iceman100)
- Changed `hf mf info` - it now uses found keys to try identify Gen2 cards (@iceman1001)
Expand Down
56 changes: 47 additions & 9 deletions client/src/cmdhf14a.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,11 @@ int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card
return PM3_ECARDEXCHANGE;
}

iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.data.asBytes;
if (card) {
memcpy(card, vcard, sizeof(iso14a_card_select_t));
}

if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
// get ATS
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
Expand All @@ -1029,19 +1034,19 @@ int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card
gs_frame_len = atsFSC[fsci];
}
}

if (card) {
card->ats_len = resp.oldarg[0];
memcpy(card->ats, resp.data.asBytes, card->ats_len);
}
} else {
// get frame length from ATS in card data structure
iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.data.asBytes;
if (vcard->ats_len > 1) {
uint8_t fsci = vcard->ats[1] & 0x0f;
if (fsci < ARRAYLEN(atsFSC)) {
gs_frame_len = atsFSC[fsci];
}
}

if (card) {
memcpy(card, vcard, sizeof(iso14a_card_select_t));
}
}

SetISODEPState(ISODEP_NFCA);
Expand All @@ -1060,11 +1065,44 @@ int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card
static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
*chainingout = false;

size_t timeout = 1500;
if (activateField) {
// select with no disconnect and set gs_frame_len
int selres = SelectCard14443A_4(false, true, NULL);
if (selres != PM3_SUCCESS)
iso14a_card_select_t card;
int selres = SelectCard14443A_4(false, true, &card);
if (selres != PM3_SUCCESS) {
return selres;
}

// Extract FWI and SFGI from ATS and increase timeout by the indicated values
// for most cards these values are trivially small so will make no practical
// difference but some "cards" like hf_cardhopper overwrite these to their
// maximum values resulting in ~5 seconds each which can cause timeouts if we
// just ignore it
if (((card.ats[1] & 0x20) == 0x20) && card.ats_len > 2) {
// TB is present in ATS

uint8_t tb;
if ((card.ats[1] & 0x10) == 0x10 && card.ats_len > 3) {
// TA is also present, so TB at ats[3]
tb = card.ats[3];
} else {
// TA is not present, so TB is at ats[2]
tb = card.ats[2];
}

uint8_t fwi = (tb & 0xF0) >> 4;
if (fwi != 0x0F) {
uint32_t fwt = 256 * 16 * (1 << fwi);
timeout += fwt;
}

uint8_t sfgi = tb & 0x0F;
if (sfgi != 0x0F) {
uint32_t sgft = 256 * 16 * (1 << sfgi);
timeout += sgft;
}
}
}

uint16_t cmdc = 0;
Expand All @@ -1082,7 +1120,7 @@ static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool

PacketResponseNG resp;

if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, timeout)) {
uint8_t *recv = resp.data.asBytes;
int iLen = resp.oldarg[0];
uint8_t res = resp.oldarg[1];
Expand Down Expand Up @@ -2410,7 +2448,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {

int isMagic = 0;
if (isMifareClassic) {
isMagic = detect_mf_magic(true, MF_KEY_A, 0);
isMagic = detect_mf_magic(true, MF_KEY_B, 0xFFFFFFFFFFFF);
}
if (isMifareUltralight) {
isMagic = (detect_mf_magic(false, MF_KEY_A, 0) == MAGIC_NTAG21X);
Expand Down
Loading