X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/8db0534ed1647ff3b17cff63bf0dc1bdbaf039ed..ee1eadee0f50922d9d88692bbc5ea12a16e0d1fc:/client/cmdhf.c diff --git a/client/cmdhf.c b/client/cmdhf.c index 7f1246cc..03d89c0b 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -23,6 +23,7 @@ #include "cmdhficlass.h" #include "cmdhfmf.h" #include "cmdhfmfu.h" +#include "protocols.h" static int CmdHelp(const char *Cmd); @@ -33,175 +34,6 @@ int CmdHFTune(const char *Cmd) return 0; } -//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501 -/* -ISO14443A (usually NFC tags) - 26 (7bits) = REQA - 30 = Read (usage: 30+1byte block number+2bytes ISO14443A-CRC - answer: 16bytes) - A2 = Write (usage: A2+1byte block number+4bytes data+2bytes ISO14443A-CRC - answer: 0A [ACK] or 00 [NAK]) - 52 (7bits) = WUPA (usage: 52(7bits) - answer: 2bytes ATQA) - 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) - 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) - 95 20 = Anticollision of cascade level2 - 95 70 = Select of cascade level2 - 50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card) -Mifare - 60 = Authenticate with KeyA - 61 = Authenticate with KeyB - 40 (7bits) = Used to put Chinese Changeable UID cards in special mode (must be followed by 43 (8bits) - answer: 0A) - C0 = Decrement - C1 = Increment - C2 = Restore - B0 = Transfer -Ultralight C - A0 = Compatibility Write (to accomodate MIFARE commands) - 1A = Step1 Authenticate - AF = Step2 Authenticate - - -ISO14443B - 05 = REQB - 1D = ATTRIB - 50 = HALT -SRIX4K (tag does not respond to 05) - 06 00 = INITIATE - 0E xx = SELECT ID (xx = Chip-ID) - 0B = Get UID - 08 yy = Read Block (yy = block number) - 09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) - 0C = Reset to Inventory - 0F = Completion - 0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) - - -ISO15693 - MANDATORY COMMANDS (all ISO15693 tags must support those) - 01 = Inventory (usage: 260100+2bytes ISO15693-CRC - answer: 12bytes) - 02 = Stay Quiet - OPTIONAL COMMANDS (not all tags support them) - 20 = Read Block (usage: 0220+1byte block number+2bytes ISO15693-CRC - answer: 4bytes) - 21 = Write Block (usage: 0221+1byte block number+4bytes data+2bytes ISO15693-CRC - answer: 4bytes) - 22 = Lock Block - 23 = Read Multiple Blocks (usage: 0223+1byte 1st block to read+1byte last block to read+2bytes ISO15693-CRC) - 25 = Select - 26 = Reset to Ready - 27 = Write AFI - 28 = Lock AFI - 29 = Write DSFID - 2A = Lock DSFID - 2B = Get_System_Info (usage: 022B+2bytes ISO15693-CRC - answer: 14 or more bytes) - 2C = Read Multiple Block Security Status (usage: 022C+1byte 1st block security to read+1byte last block security to read+2bytes ISO15693-CRC) - -EM Microelectronic CUSTOM COMMANDS - A5 = Active EAS (followed by 1byte IC Manufacturer code+1byte EAS type) - A7 = Write EAS ID (followed by 1byte IC Manufacturer code+2bytes EAS value) - B8 = Get Protection Status for a specific block (followed by 1byte IC Manufacturer code+1byte block number+1byte of how many blocks after the previous is needed the info) - E4 = Login (followed by 1byte IC Manufacturer code+4bytes password) -NXP/Philips CUSTOM COMMANDS - A0 = Inventory Read - A1 = Fast Inventory Read - A2 = Set EAS - A3 = Reset EAS - A4 = Lock EAS - A5 = EAS Alarm - A6 = Password Protect EAS - A7 = Write EAS ID - A8 = Read EPC - B0 = Inventory Page Read - B1 = Fast Inventory Page Read - B2 = Get Random Number - B3 = Set Password - B4 = Write Password - B5 = Lock Password - B6 = Bit Password Protection - B7 = Lock Page Protection Condition - B8 = Get Multiple Block Protection Status - B9 = Destroy SLI - BA = Enable Privacy - BB = 64bit Password Protection - 40 = Long Range CMD (Standard ISO/TR7003:1990) - */ - -#define ICLASS_CMD_ACTALL 0x0A -#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C -#define ICLASS_CMD_SELECT 0x81 -#define ICLASS_CMD_PAGESEL 0x84 -#define ICLASS_CMD_READCHECK_KD 0x88 -#define ICLASS_CMD_READCHECK_KC 0x18 -#define ICLASS_CMD_CHECK 0x05 -#define ICLASS_CMD_DETECT 0x0F -#define ICLASS_CMD_HALT 0x00 -#define ICLASS_CMD_UPDATE 0x87 -#define ICLASS_CMD_ACT 0x8E -#define ICLASS_CMD_READ4 0x06 - - -#define ISO14443A_CMD_REQA 0x26 -#define ISO14443A_CMD_READBLOCK 0x30 -#define ISO14443A_CMD_WUPA 0x52 -#define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93 -#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95 -#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ? -#define ISO14443A_CMD_HALT 0x50 -#define ISO14443A_CMD_RATS 0xE0 - -#define MIFARE_AUTH_KEYA 0x60 -#define MIFARE_AUTH_KEYB 0x61 -#define MIFARE_MAGICMODE 0x40 -#define MIFARE_CMD_INC 0xC0 -#define MIFARE_CMD_DEC 0xC1 -#define MIFARE_CMD_RESTORE 0xC2 -#define MIFARE_CMD_TRANSFER 0xB0 - -#define MIFARE_ULC_WRITE 0xA0 -#define MIFARE_ULC_AUTH_1 0x1A -#define MIFARE_ULC_AUTH_2 0xAF - -/** -06 00 = INITIATE -0E xx = SELECT ID (xx = Chip-ID) -0B = Get UID -08 yy = Read Block (yy = block number) -09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) -0C = Reset to Inventory -0F = Completion -0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) -**/ - -#define ISO14443B_REQB 0x05 -#define ISO14443B_ATTRIB 0x1D -#define ISO14443B_HALT 0x50 -#define ISO14443B_INITIATE 0x06 -#define ISO14443B_SELECT 0x0E -#define ISO14443B_GET_UID 0x0B -#define ISO14443B_READ_BLK 0x08 -#define ISO14443B_WRITE_BLK 0x09 -#define ISO14443B_RESET 0x0C -#define ISO14443B_COMPLETION 0x0F -#define ISO14443B_AUTHENTICATE 0x0A - -//First byte is 26 -#define ISO15693_INVENTORY 0x01 -#define ISO15693_STAYQUIET 0x02 -//First byte is 02 -#define ISO15693_READBLOCK 0x20 -#define ISO15693_WRITEBLOCK 0x21 -#define ISO15693_LOCKBLOCK 0x22 -#define ISO15693_READ_MULTI_BLOCK 0x23 -#define ISO15693_SELECT 0x25 -#define ISO15693_RESET_TO_READY 0x26 -#define ISO15693_WRITE_AFI 0x27 -#define ISO15693_LOCK_AFI 0x28 -#define ISO15693_WRITE_DSFID 0x29 -#define ISO15693_LOCK_DSFID 0x2A -#define ISO15693_GET_SYSTEM_INFO 0x2B -#define ISO15693_READ_MULTI_SECSTATUS 0x2C - - -#define ISO_14443A 0 -#define ICLASS 1 -#define ISO_14443B 2 - void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { @@ -230,19 +62,21 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) snprintf(exp,size,"ANTICOLL-2"); break; } } - case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; - case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; - case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; - case ISO14443A_CMD_HALT: snprintf(exp,size,"HALT"); break; - case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break; - case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; - case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; - case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; - case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; - case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break; - case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break; - case MIFARE_MAGICMODE: snprintf(exp,size,"MAGIC"); break; - default: snprintf(exp,size,"?"); break; + case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; + case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; + case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; + case ISO14443A_CMD_HALT: snprintf(exp,size,"HALT"); break; + case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break; + case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; + case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; + case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; + case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break; + case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break; + case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break; + case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; + case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break; + case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; + default: snprintf(exp,size,"?"); break; } return; } @@ -307,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) @@ -421,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}; @@ -456,6 +314,40 @@ 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; + 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 + //1 CRC-command, CRC ok + //2 Not crc-command //--- Draw the data column //char line[16][110]; @@ -469,7 +361,6 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui for (k=0 ; k<8 ; k++) { oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } - 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]); @@ -477,6 +368,14 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } else { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x ", frame[j]); } + + } + if(crcStatus == 1) + {//CRC-command + char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1; + (*pos1) = '['; + char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2; + (*pos2) = ']'; } if(data_len == 0) { @@ -485,45 +384,20 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui } } //--- Draw the CRC column - 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))) - { - crcStatus = 0; - } - } - } - } - //0 CRC-command, CRC not ok - //1 CRC-command, CRC ok - //2 Not crc-command char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : " ")); EndOfTransmissionTimestamp = timestamp + duration; 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); @@ -539,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 : ""); } } @@ -582,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; } } @@ -609,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");