From ee1eadee0f50922d9d88692bbc5ea12a16e0d1fc Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Fri, 13 Mar 2015 07:36:52 +0100 Subject: [PATCH] add: start to support Topaz tags - hf 14a reader now exits gracefully in case of proprietary anticollision sequence - changed miller decoder to handle Topaz 8 data bits/no parity frames from reader - started to implement hf list topaz --- armsrc/iso14443a.c | 5 +++ armsrc/iso14443a.h | 2 +- client/cmdhf.c | 97 ++++++++++++++++++++++++++++++---------------- client/cmdhf14a.c | 14 ++++++- common/protocols.h | 17 ++++++-- 5 files changed, 96 insertions(+), 39 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index ac839cfd..f52e3eb8 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1719,6 +1719,11 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u memset(uid_ptr,0,10); } + // check for proprietary anticollision: + if ((resp[0] & 0x1F) == 0) { + return 3; + } + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 1e978e88..d99236b2 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -56,7 +56,7 @@ typedef struct { // DROP_FIRST_HALF, } state; uint16_t shiftReg; - uint16_t bitCount; + int16_t bitCount; uint16_t len; uint16_t byteCntMax; uint16_t posCnt; diff --git a/client/cmdhf.c b/client/cmdhf.c index 22063bbb..03d89c0b 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -141,6 +141,23 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } } + +void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) +{ + + switch(cmd[0]) { + case TOPAZ_REQA :snprintf(exp, size, "REQA");break; + case TOPAZ_WUPA :snprintf(exp, size, "WUPA");break; + case TOPAZ_RID :snprintf(exp, size, "RID");break; + case TOPAZ_RALL :snprintf(exp, size, "RALL");break; + case TOPAZ_READ :snprintf(exp, size, "READ");break; + case TOPAZ_WRITE_E :snprintf(exp, size, "WRITE-E");break; + case TOPAZ_WRITE_NE :snprintf(exp, size, "WRITE-NE");break; + default: snprintf(exp,size,"?"); break; + } +} + + /** 06 00 = INITIATE 0E xx = SELECT ID (xx = Chip-ID) @@ -255,11 +272,18 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len) } } + +uint16_t merge_topaz_reader_frames(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *topaz_reader_command, uint16_t *data_len) +{ + return tracepos; +} + + uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles) { bool isResponse; uint16_t duration, data_len, parity_len; - + uint8_t topaz_reader_command[9]; uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp; char explanation[30] = {0}; @@ -290,29 +314,35 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui uint8_t *parityBytes = trace + tracepos; tracepos += parity_len; + if (protocol == TOPAZ && !isResponse) { + // topaz reader commands come in 1 or 9 separate frames with 8 Bits each. + // merge them: + tracepos = merge_topaz_reader_frames(tracepos, traceLen, trace, topaz_reader_command, &data_len); + } + //Check the CRC status uint8_t crcStatus = 2; if (data_len > 2) { uint8_t b1, b2; - if(protocol == ICLASS) - { - crcStatus = iclass_CRC_check(isResponse, frame, data_len); - - }else if (protocol == ISO_14443B) - { - crcStatus = iso14443B_CRC_check(isResponse, frame, data_len); - } - else if (protocol == ISO_14443A){//Iso 14443a - - ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); - - if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { - if(!(isResponse & (data_len < 6))) - { + switch (protocol) { + case ICLASS: + crcStatus = iclass_CRC_check(isResponse, frame, data_len); + break; + case ISO_14443B: + case TOPAZ: + crcStatus = iso14443B_CRC_check(isResponse, topaz_reader_command, data_len); + break; + case ISO_14443A: + ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2); + if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) { + if(!(isResponse & (data_len < 6))) { crcStatus = 0; + } } - } + break; + default: + break; } } //0 CRC-command, CRC not ok @@ -361,12 +391,13 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui if(!isResponse) { - if(protocol == ICLASS) - annotateIclass(explanation,sizeof(explanation),frame,data_len); - else if (protocol == ISO_14443A) - annotateIso14443a(explanation,sizeof(explanation),frame,data_len); - else if(protocol == ISO_14443B) - annotateIso14443b(explanation,sizeof(explanation),frame,data_len); + switch(protocol) { + case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break; + case ISO_14443A: annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break; + case ISO_14443B: annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break; + case TOPAZ: annotateTopaz(explanation,sizeof(explanation),frame,data_len); break; + default: break; + } } int num_lines = MIN((data_len - 1)/16 + 1, 16); @@ -382,7 +413,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } else { PrintAndLog(" | | | %-64s| %s| %s", line[j], - (j == num_lines-1)?crc:" ", + (j == num_lines-1) ? crc : " ", (j == num_lines-1) ? explanation : ""); } } @@ -425,20 +456,17 @@ int CmdHFList(const char *Cmd) } if(!errors) { - if(strcmp(type, "iclass") == 0) - { + if(strcmp(type, "iclass") == 0) { protocol = ICLASS; - }else if(strcmp(type, "14a") == 0) - { + } else if(strcmp(type, "14a") == 0) { protocol = ISO_14443A; - } - else if(strcmp(type, "14b") == 0) - { + } else if(strcmp(type, "14b") == 0) { protocol = ISO_14443B; - }else if(strcmp(type,"raw")== 0) - { + } else if(strcmp(type,"topaz")== 0) { + protocol = TOPAZ; + } else if(strcmp(type,"raw")== 0) { protocol = -1;//No crc, no annotations - }else{ + } else { errors = true; } } @@ -452,6 +480,7 @@ int CmdHFList(const char *Cmd) PrintAndLog(" 14a - interpret data as iso14443a communications"); PrintAndLog(" 14b - interpret data as iso14443b communications"); PrintAndLog(" iclass - interpret data as iclass communications"); + PrintAndLog(" topaz - interpret data as topaz communications"); PrintAndLog(""); PrintAndLog("example: hf list 14a f"); PrintAndLog("example: hf list iclass"); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index d36ebb8b..8978f43d 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -140,7 +140,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]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision if(select_status == 0) { PrintAndLog("iso14443a card select failed"); @@ -152,6 +152,18 @@ int CmdHF14AReader(const char *Cmd) return 0; } + if(select_status == 3) { + PrintAndLog("Card doesn't support standard iso14443-3 anticollision"); + PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + // disconnect + c.arg[0] = 0; + c.arg[1] = 0; + c.arg[2] = 0; + SendCommand(&c); + return 0; + } + + PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); diff --git a/common/protocols.h b/common/protocols.h index 01b738c2..e687ca7a 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -168,9 +168,20 @@ NXP/Philips CUSTOM COMMANDS #define ISO15693_READ_MULTI_SECSTATUS 0x2C -#define ISO_14443A 0 -#define ICLASS 1 -#define ISO_14443B 2 +// Topaz command set: +#define TOPAZ_REQA 0x26 // Request +#define TOPAZ_WUPA 0x52 // WakeUp +#define TOPAZ_RID 0x78 // Read ID +#define TOPAZ_RALL 0x00 // Read All (all bytes) +#define TOPAZ_READ 0x01 // Read (a single byte) +#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte) +#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte) + + +#define ISO_14443A 0 +#define ICLASS 1 +#define ISO_14443B 2 +#define TOPAZ 3 //-- Picopass fuses #define FUSE_FPERS 0x80 -- 2.39.2