From ef00343cb1f6ab306020c4108cd414e8df6b132f Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Tue, 17 Mar 2015 07:41:08 +0100 Subject: [PATCH] revert change "hf list topaz" to "hf list nfc" refactored Startbit detection in MillerDecoding() relaxed startbit detection in MillerDecoding() fixed CRC checking and CRC bytes marking in hf list fixed topaz multi frame command listing in hf list topaz --- armsrc/iso14443a.c | 55 ++++++++++++---------------- armsrc/iso14443a.h | 3 +- client/cmdhf.c | 89 +++++++++++++++++++++++++++++++--------------- 3 files changed, 84 insertions(+), 63 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a78dae6e..06a134f6 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -248,8 +248,7 @@ void UartReset() Uart.parityLen = 0; // number of decoded parity bytes Uart.shiftReg = 0; // shiftreg to hold decoded data bits Uart.parityBits = 0; // holds 8 parity bits - Uart.twoBits = 0x0000; // buffer for 2 Bits - Uart.highCnt = 0; + Uart.fourBits = 0x00000000; // buffer for 4 Bits Uart.startTime = 0; Uart.endTime = 0; } @@ -265,40 +264,34 @@ void UartInit(uint8_t *data, uint8_t *parity) static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { - Uart.twoBits = (Uart.twoBits << 8) | bit; + Uart.fourBits = (Uart.fourBits << 8) | bit; if (Uart.state == STATE_UNSYNCD) { // not yet synced - if (Uart.highCnt < 1) { // wait for a stable unmodulated signal - if (Uart.twoBits == 0xffff) { - Uart.highCnt++; - } else { - Uart.highCnt = 0; - } - } else { - Uart.syncBit = 0xFFFF; // not set - // we look for a ...1111111100x11111xxxxxx pattern (the start bit) - if ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8; // mask is 11x11111 xxxxxxxx, - // check for 00x11111 xxxxxxxx - else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7; // both masks shifted right one bit, left padded with '1' - else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6; // ... - else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5; - else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4; - else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3; - else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2; - else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1; - if (Uart.syncBit != 0xFFFF) { // found a sync bit - Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); - Uart.startTime -= Uart.syncBit; - Uart.endTime = Uart.startTime; - Uart.state = STATE_START_OF_COMMUNICATION; - } + Uart.syncBit = 9999; // not set + // we look for a ...xxxx1111111100x11111xxxxxx pattern + // (unmodulated, followed by the start bit = 8 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) +#define ISO14443A_STARTBIT_MASK 0x007FEF80 // mask is 00000000 01111111 11101111 10000000 +#define ISO14443A_STARTBIT_PATTERN 0x007F8F80 // pattern is 00000000 01111111 10001111 10000000 + if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 0 == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 1 == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 2 == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 3 == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 4 == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 5 == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 6 == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1; + else if ((Uart.fourBits & ISO14443A_STARTBIT_MASK) >> 7 == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0; + if (Uart.syncBit != 9999) { // found a sync bit + Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8); + Uart.startTime -= Uart.syncBit; + Uart.endTime = Uart.startTime; + Uart.state = STATE_START_OF_COMMUNICATION; } } else { - if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) { - if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation in both halves - error + if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { + if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error UartReset(); } else { // Modulation in first half = Sequence Z = logic "0" if (Uart.state == STATE_MILLER_X) { // error - must not follow after X @@ -322,7 +315,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) } } } else { - if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" + if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg Uart.state = STATE_MILLER_X; @@ -358,12 +351,10 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) return TRUE; // we are finished with decoding the raw data sequence } else { UartReset(); // Nothing received - start over - Uart.highCnt = 1; } } if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC UartReset(); - Uart.highCnt = 1; } else { // a logic "0" Uart.bitCount++; Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index d99236b2..ec99ab99 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -63,8 +63,7 @@ typedef struct { uint16_t syncBit; uint8_t parityBits; uint8_t parityLen; - uint16_t highCnt; - uint16_t twoBits; + uint32_t fourBits; uint32_t startTime, endTime; uint8_t *output; uint8_t *parity; diff --git a/client/cmdhf.c b/client/cmdhf.c index f4d76210..960dcf7f 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -189,7 +189,34 @@ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) } /** - * @brief iso14443B_CRC_Ok Checks CRC in command or response + * @brief iso14443A_CRC_check Checks CRC in command or response + * @param isResponse + * @param data + * @param len + * @return 0 : CRC-command, CRC not ok + * 1 : CRC-command, CRC ok + * 2 : Not crc-command + */ + +uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len) +{ + uint8_t b1,b2; + + if(len <= 2) return 2; + + if(isResponse & (len < 6)) return 2; + + ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2); + if (b1 != data[len-2] || b2 != data[len-1]) { + return 0; + } else { + return 1; + } +} + + +/** + * @brief iso14443B_CRC_check Checks CRC in command or response * @param isResponse * @param data * @param len @@ -206,9 +233,10 @@ uint8_t iso14443B_CRC_check(bool isResponse, uint8_t* data, uint8_t len) ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2); if(b1 != data[len-2] || b2 != data[len-1]) { - return 0; + return 0; + } else { + return 1; } - return 1; } /** @@ -287,33 +315,42 @@ bool next_record_is_response(uint16_t tracepos, uint8_t *trace) } -void merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len) +bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len) { #define MAX_TOPAZ_READER_CMD_LEN 9 uint32_t last_timestamp = timestamp + *duration; - memcpy(topaz_reader_command, frame, MIN(*data_len, MAX_TOPAZ_READER_CMD_LEN)); + if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false; + + memcpy(topaz_reader_command, frame, *data_len); while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) { uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos)); *tracepos += sizeof(uint32_t); - last_timestamp = next_timestamp + *((uint16_t *)(trace + *tracepos)); + uint16_t next_duration = *((uint16_t *)(trace + *tracepos)); *tracepos += sizeof(uint16_t); uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF; *tracepos += sizeof(uint16_t); uint8_t *next_frame = (trace + *tracepos); *tracepos += next_data_len; - if (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN) { + if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) { memcpy(topaz_reader_command + *data_len, next_frame, next_data_len); *data_len += next_data_len; - } + last_timestamp = next_timestamp + next_duration; + } else { + // rewind and exit + *tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t); + break; + } uint16_t next_parity_len = (next_data_len-1)/8 + 1; *tracepos += next_parity_len; } *duration = last_timestamp - timestamp; + + return true; } @@ -354,32 +391,27 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui tracepos += parity_len; if (protocol == TOPAZ && !isResponse) { - // topaz reader commands come in 1 or 9 separate frames with 8 Bits each. + // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each. // merge them: - merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len); - frame = topaz_reader_command; + if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) { + frame = topaz_reader_command; + } } //Check the CRC status uint8_t crcStatus = 2; if (data_len > 2) { - uint8_t b1, b2; switch (protocol) { case ICLASS: crcStatus = iclass_CRC_check(isResponse, frame, data_len); break; case ISO_14443B: - case TOPAZ: + case TOPAZ: crcStatus = iso14443B_CRC_check(isResponse, frame, 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; - } - } + crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); break; default: break; @@ -403,19 +435,18 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } uint8_t parityBits = parityBytes[j>>3]; if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { - snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); - + snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x!", frame[j]); } else { - snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]); + snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]); } } - if(crcStatus == 1 || crcStatus == 2) + if(crcStatus == 0 || crcStatus == 1) {//CRC-command - char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1; + char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4); (*pos1) = '['; - char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2; - (*pos2) = ']'; + char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4); + sprintf(pos2, "%c", ']'); } if(data_len == 0) { @@ -443,7 +474,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui int num_lines = MIN((data_len - 1)/16 + 1, 16); for (int j = 0; j < num_lines ; j++) { if (j == 0) { - PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s", + PrintAndLog(" %9d | %9d | %s |%-64s | %s| %s", (timestamp - first_timestamp), (EndOfTransmissionTimestamp - first_timestamp), (isResponse ? "Tag" : "Rdr"), @@ -451,7 +482,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui (j == num_lines-1) ? crc : " ", (j == num_lines-1) ? explanation : ""); } else { - PrintAndLog(" | | | %-64s| %s| %s", + PrintAndLog(" | | |%-64s | %s| %s", line[j], (j == num_lines-1) ? crc : " ", (j == num_lines-1) ? explanation : ""); @@ -498,7 +529,7 @@ int CmdHFList(const char *Cmd) protocol = ISO_14443A; } else if(strcmp(type, "14b") == 0) { protocol = ISO_14443B; - } else if(strcmp(type,"nfc")== 0) { + } else if(strcmp(type,"topaz")== 0) { protocol = TOPAZ; } else if(strcmp(type,"raw")== 0) { protocol = -1;//No crc, no annotations -- 2.39.2