X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/19d6d91fd5a0fe2fdb70f77e54d1697c827a2cc7..6a1f2d82bb7d33cd49f9c191f36144ca10d5b629:/client/cmdhf14a.c diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 534444fd..5d1c4853 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -43,10 +43,13 @@ int CmdHF14AList(const char *Cmd) if (param == 'f') { ShowWaitCycles = true; } - - uint8_t got[1920]; - GetFromBigBuf(got,sizeof(got),0); - WaitForResponse(CMD_ACK,NULL); + +// for the time being. Need better Bigbuf handling. +#define TRACE_SIZE 3000 + + uint8_t trace[TRACE_SIZE]; + GetFromBigBuf(trace, TRACE_SIZE, 0); + WaitForResponse(CMD_ACK, NULL); PrintAndLog("Recorded Activity"); PrintAndLog(""); @@ -56,123 +59,105 @@ int CmdHF14AList(const char *Cmd) PrintAndLog(" Start | End | Src | Data"); PrintAndLog("-----------|-----------|-----|--------"); - int i = 0; - uint32_t first_timestamp = 0; + uint16_t tracepos = 0; + uint16_t duration; + uint16_t data_len; + uint16_t parity_len; + bool isResponse; uint32_t timestamp; - uint32_t EndOfTransmissionTimestamp = 0; + uint32_t first_timestamp; + uint32_t EndOfTransmissionTimestamp; for (;;) { - if(i >= 1900) { + + if(tracepos >= TRACE_SIZE) { break; } - bool isResponse; - timestamp = *((uint32_t *)(got+i)); - if (timestamp & 0x80000000) { - timestamp &= 0x7fffffff; + timestamp = *((uint32_t *)(trace + tracepos)); + if(tracepos == 0) { + first_timestamp = timestamp; + } + tracepos += 4; + duration = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + data_len = *((uint16_t *)(trace + tracepos)); + tracepos += 2; + + if (data_len & 0x8000) { + data_len &= 0x7fff; isResponse = true; } else { isResponse = false; } - if(i==0) { - first_timestamp = timestamp; - } - - int parityBits = *((uint32_t *)(got+i+4)); - - int len = got[i+8]; + parity_len = (data_len-1)/8 + 1; - if (len > 100) { - break; - } - if (i + len >= 1900) { + if (tracepos + data_len + parity_len >= TRACE_SIZE) { break; } - - uint8_t *frame = (got+i+9); + + uint8_t *frame = trace + tracepos; + tracepos += data_len; + uint8_t *parityBytes = trace + tracepos; + tracepos += parity_len; // Break and stick with current result if buffer was not completely full - if (frame[0] == 0x44 && frame[1] == 0x44 && frame[2] == 0x44 && frame[3] == 0x44) break; + if (timestamp == 0x44444444) break; char line[1000] = ""; int j; - if (len) { - for (j = 0; j < len; j++) { - int oddparity = 0x01; - int k; + for (j = 0; j < data_len; j++) { + int oddparity = 0x01; + int k; - for (k=0;k<8;k++) { - oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); - } - - //if((parityBits >> (len - j - 1)) & 0x01) { - if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) { - sprintf(line+(j*4), "%02x! ", frame[j]); - } else { - sprintf(line+(j*4), "%02x ", frame[j]); - } - } - } else { - if (ShowWaitCycles) { - uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff; - sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp)); + for (k=0;k<8;k++) { + oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } - } - char *crc; - crc = ""; - if (len > 2) { - uint8_t b1, b2; - for (j = 0; j < (len - 1); j++) { - // gives problems... search for the reason.. - /*if(frame[j] == 0xAA) { - switch(frame[j+1]) { - case 0x01: - crc = "[1] Two drops close after each other"; - break; - case 0x02: - crc = "[2] Potential SOC with a drop in second half of bitperiod"; - break; - case 0x03: - crc = "[3] Segment Z after segment X is not possible"; - break; - case 0x04: - crc = "[4] Parity bit of a fully received byte was wrong"; - break; - default: - crc = "[?] Unknown error"; - break; - } - break; - }*/ + uint8_t parityBits = parityBytes[j>>3]; + if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + sprintf(line+(j*4), "%02x! ", frame[j]); + } else { + sprintf(line+(j*4), "%02x ", frame[j]); } + } - if (strlen(crc)==0) { - ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2); - if (b1 != frame[len-2] || b2 != frame[len-1]) { - crc = (isResponse & (len < 6)) ? "" : " !crc"; - } else { - crc = ""; - } + char crc[6] = ""; + if (data_len > 2) { + uint8_t b1, b2; + ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + sprintf(crc, (isResponse & (data_len < 6)) ? "" : " !crc"); + } else { + sprintf(crc, ""); } - } else { - crc = ""; // SHORT } - i += (len + 9); - - EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff; - - if (!ShowWaitCycles) i += 9; + EndOfTransmissionTimestamp = timestamp + duration; PrintAndLog(" %9d | %9d | %s | %s %s", (timestamp - first_timestamp), (EndOfTransmissionTimestamp - first_timestamp), - (len?(isResponse ? "Tag" : "Rdr"):" "), - line, crc); + (isResponse ? "Tag" : "Rdr"), + line, + crc); + bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000; + + if (ShowWaitCycles && !isResponse && next_isResponse) { + uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); + if (next_timestamp != 0x44444444) { + PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d", + (EndOfTransmissionTimestamp - first_timestamp), + (next_timestamp - first_timestamp), + " ", + (next_timestamp - EndOfTransmissionTimestamp)); + } + } + } + return 0; } @@ -192,7 +177,7 @@ int CmdHF14AReader(const char *Cmd) iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint64_t select_status = resp.arg[0]; + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS if(select_status == 0) { PrintAndLog("iso14443a card select failed"); @@ -232,7 +217,7 @@ int CmdHF14AReader(const char *Cmd) WaitForResponse(CMD_ACK,&resp); memcpy(&card.ats, resp.d.asBytes, resp.arg[0]); - card.ats_len = resp.arg[0]; + card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes } // disconnect @@ -242,28 +227,36 @@ int CmdHF14AReader(const char *Cmd) SendCommand(&c); - if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte TL and 2 CRC bytes + if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes bool ta1 = 0, tb1 = 0, tc1 = 0; int pos; - if (!(card.sak & 0x02)) { + if (select_status == 2) { PrintAndLog("SAK incorrectly claims that card doesn't support RATS"); } PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len)); - if (card.ats_len > 0) { - PrintAndLog(" - TL : length is %d bytes", card.ats[0]); + PrintAndLog(" - TL : length is %d bytes", card.ats[0]); + if (card.ats[0] != card.ats_len - 2) { + PrintAndLog("ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); } - if (card.ats_len > 1) { + + if (card.ats[0] > 1) { // there is a format byte (T0) ta1 = (card.ats[1] & 0x10) == 0x10; tb1 = (card.ats[1] & 0x20) == 0x20; tc1 = (card.ats[1] & 0x40) == 0x40; + int16_t fsci = card.ats[1] & 0x0f; PrintAndLog(" - T0 : TA1 is%s present, TB1 is%s present, " - "TC1 is%s present, FSCI is %d", + "TC1 is%s present, FSCI is %d (FSC = %ld)", (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"), - (card.ats[1] & 0x0f)); + fsci, + fsci < 5 ? (fsci - 2) * 8 : + fsci < 8 ? (fsci - 3) * 32 : + fsci == 8 ? 256 : + -1 + ); } pos = 2; - if (ta1 && card.ats_len > pos) { + if (ta1) { char dr[16], ds[16]; dr[0] = ds[0] = '\0'; if (card.ats[pos] & 0x10) strcat(ds, "2, "); @@ -279,28 +272,34 @@ int CmdHF14AReader(const char *Cmd) (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); pos++; } - if (tb1 && card.ats_len > pos) { - PrintAndLog(" - TB1 : SFGI = %d, FWI = %d", - (card.ats[pos] & 0x08), - (card.ats[pos] & 0x80) >> 4); + if (tb1) { + uint32_t sfgi = card.ats[pos] & 0x0F; + uint32_t fwi = card.ats[pos] >> 4; + PrintAndLog(" - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", + (sfgi), + sfgi ? "" : "(not needed) ", + sfgi ? (1 << 12) << sfgi : 0, + fwi, + (1 << 12) << fwi + ); pos++; } - if (tc1 && card.ats_len > pos) { + if (tc1) { PrintAndLog(" - TC1 : NAD is%s supported, CID is%s supported", (card.ats[pos] & 0x01) ? "" : " NOT", (card.ats[pos] & 0x02) ? "" : " NOT"); pos++; } - if (card.ats_len > pos) { + if (card.ats[0] > pos) { char *tip = ""; - if (card.ats_len - pos > 7) { + if (card.ats[0] - pos >= 7) { if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { tip = "-> MIFARE Plus X 2K or 4K"; } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { tip = "-> MIFARE Plus S 2K or 4K"; } } - PrintAndLog(" - HB : %s%s", sprint_hex(card.ats + pos, card.ats_len - pos - 2), tip); + PrintAndLog(" - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); if (card.ats[pos] == 0xC1) { PrintAndLog(" c1 -> Mifare or (multiple) virtual cards of various type"); PrintAndLog(" %02x -> Length is %d bytes",