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
This commit is contained in:
pwpiwi 2015-03-17 07:41:08 +01:00
commit ef00343cb1
3 changed files with 84 additions and 63 deletions

View file

@ -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

View file

@ -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;

View file

@ -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