1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   5 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   6 // at your option, any later version. See the LICENSE.txt file for the text of 
   8 //----------------------------------------------------------------------------- 
   9 // High frequency commands 
  10 //----------------------------------------------------------------------------- 
  20 #include "iso14443crc.h" 
  23 #include "cmdparser.h" 
  28 #include "cmdhflegic.h" 
  29 #include "cmdhficlass.h" 
  33 #include "cmdhftopaz.h" 
  34 #include "protocols.h" 
  35 #include "emv/cmdemv.h" 
  36 #include "cmdhflist.h" 
  37 #include "cmdhffido.h" 
  39 static int CmdHelp(const char *Cmd
); 
  41 int CmdHFTune(const char *Cmd
) 
  43   UsbCommand c
={CMD_MEASURE_ANTENNA_TUNING_HF
}; 
  49  * @brief iso14443B_CRC_check Checks CRC in command or response 
  53  * @return  0 : CRC-command, CRC not ok 
  54  *          1 : CRC-command, CRC ok 
  58 uint8_t iso14443B_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
) 
  62         if(len 
<= 2) return 2; 
  64         ComputeCrc14443(CRC_14443_B
, data
, len
-2, &b1
, &b2
); 
  65         if(b1 
!= data
[len
-2] || b2 
!= data
[len
-1]) { 
  73  * @brief iclass_CRC_Ok Checks CRC in command or response 
  77  * @return  0 : CRC-command, CRC not ok 
  78  *              1 : CRC-command, CRC ok 
  81 uint8_t iclass_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
) 
  83         if(len 
< 4) return 2;//CRC commands (and responses) are all at least 4 bytes 
  87         if(!isResponse
)//Commands to tag 
  90                   These commands should have CRC. Total length leftmost 
  93                   12 UPDATE - unsecured, ends with CRC16 
  94                   14 UPDATE - secured, ends with signature instead 
  97                 if(len 
== 4 || len 
== 12)//Covers three of them 
  99                         //Don't include the command byte 
 100                         ComputeCrc14443(CRC_ICLASS
, (data
+1), len
-3, &b1
, &b2
); 
 101                         return b1 
== data
[len 
-2] && b2 
== data
[len
-1]; 
 106                 These tag responses should have CRC. Total length leftmost 
 108                 10  READ                data[8] crc[2] 
 109                 34  READ4               data[32]crc[2] 
 110                 10  UPDATE      data[8] crc[2] 
 111                 10 SELECT       csn[8] crc[2] 
 112                 10  IDENTIFY  asnb[8] crc[2] 
 113                 10  PAGESEL   block1[8] crc[2] 
 114                 10  DETECT    csn[8] crc[2] 
 118                 4  CHECK                chip_response[4] 
 123                 In conclusion, without looking at the command; any response 
 124                 of length 10 or 34 should have CRC 
 126                 if(len 
!= 10 && len 
!= 34) return true; 
 128                 ComputeCrc14443(CRC_ICLASS
, data
, len
-2, &b1
, &b2
); 
 129                 return b1 
== data
[len 
-2] && b2 
== data
[len
-1]; 
 134 bool is_last_record(uint16_t tracepos
, uint8_t *trace
, uint16_t traceLen
) 
 136         return(tracepos 
+ sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen
); 
 140 bool next_record_is_response(uint16_t tracepos
, uint8_t *trace
) 
 142         uint16_t next_records_datalen 
= *((uint16_t *)(trace 
+ tracepos 
+ sizeof(uint32_t) + sizeof(uint16_t))); 
 144         return(next_records_datalen 
& 0x8000); 
 148 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
) 
 151 #define MAX_TOPAZ_READER_CMD_LEN        16 
 153         uint32_t last_timestamp 
= timestamp 
+ *duration
; 
 155         if ((*data_len 
!= 1) || (frame
[0] == TOPAZ_WUPA
) || (frame
[0] == TOPAZ_REQA
)) return false; 
 157         memcpy(topaz_reader_command
, frame
, *data_len
); 
 159         while (!is_last_record(*tracepos
, trace
, traceLen
) && !next_record_is_response(*tracepos
, trace
)) { 
 160                 uint32_t next_timestamp 
= *((uint32_t *)(trace 
+ *tracepos
)); 
 161                 *tracepos 
+= sizeof(uint32_t); 
 162                 uint16_t next_duration 
= *((uint16_t *)(trace 
+ *tracepos
)); 
 163                 *tracepos 
+= sizeof(uint16_t); 
 164                 uint16_t next_data_len 
= *((uint16_t *)(trace 
+ *tracepos
)) & 0x7FFF; 
 165                 *tracepos 
+= sizeof(uint16_t); 
 166                 uint8_t *next_frame 
= (trace 
+ *tracepos
); 
 167                 *tracepos 
+= next_data_len
; 
 168                 if ((next_data_len 
== 1) && (*data_len 
+ next_data_len 
<= MAX_TOPAZ_READER_CMD_LEN
)) { 
 169                         memcpy(topaz_reader_command 
+ *data_len
, next_frame
, next_data_len
); 
 170                         *data_len 
+= next_data_len
; 
 171                         last_timestamp 
= next_timestamp 
+ next_duration
; 
 174                         *tracepos 
= *tracepos 
- next_data_len 
- sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t); 
 177                 uint16_t next_parity_len 
= (next_data_len
-1)/8 + 1; 
 178                 *tracepos 
+= next_parity_len
; 
 181         *duration 
= last_timestamp 
- timestamp
; 
 187 uint16_t printTraceLine(uint16_t tracepos
, uint16_t traceLen
, uint8_t *trace
, uint8_t protocol
, bool showWaitCycles
, bool markCRCBytes
) 
 190         uint16_t data_len
, parity_len
; 
 192         uint8_t topaz_reader_command
[9]; 
 193         uint32_t timestamp
, first_timestamp
, EndOfTransmissionTimestamp
; 
 194         char explanation
[30] = {0}; 
 195         uint8_t mfData
[32] = {0}; 
 196         size_t mfDataLen 
= 0; 
 198         if (tracepos 
+ sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen
) return traceLen
; 
 200         first_timestamp 
= *((uint32_t *)(trace
)); 
 201         timestamp 
= *((uint32_t *)(trace 
+ tracepos
)); 
 204         duration 
= *((uint16_t *)(trace 
+ tracepos
)); 
 206         data_len 
= *((uint16_t *)(trace 
+ tracepos
)); 
 209         if (data_len 
& 0x8000) { 
 215         parity_len 
= (data_len
-1)/8 + 1; 
 217         if (tracepos 
+ data_len 
+ parity_len 
> traceLen
) { 
 220         uint8_t *frame 
= trace 
+ tracepos
; 
 221         tracepos 
+= data_len
; 
 222         uint8_t *parityBytes 
= trace 
+ tracepos
; 
 223         tracepos 
+= parity_len
; 
 225         if (protocol 
== TOPAZ 
&& !isResponse
) { 
 226                 // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each. 
 228                 if (merge_topaz_reader_frames(timestamp
, &duration
, &tracepos
, traceLen
, trace
, frame
, topaz_reader_command
, &data_len
)) { 
 229                         frame 
= topaz_reader_command
; 
 233         //Check the CRC status 
 234         uint8_t crcStatus 
= 2; 
 239                                 crcStatus 
= iclass_CRC_check(isResponse
, frame
, data_len
); 
 243                                 crcStatus 
= iso14443B_CRC_check(isResponse
, frame
, data_len
);  
 246                                 crcStatus 
= mifare_CRC_check(isResponse
, frame
, data_len
); 
 249                                 crcStatus 
= iso14443A_CRC_check(isResponse
, frame
, data_len
); 
 255         //0 CRC-command, CRC not ok 
 256         //1 CRC-command, CRC ok 
 259         //--- Draw the data column 
 260         //char line[16][110]; 
 263         for (int j 
= 0; j 
< data_len 
&& j
/16 < 16; j
++) { 
 265                 uint8_t parityBits 
= parityBytes
[j
>>3]; 
 266                 if (protocol 
!= ISO_14443B 
&& (isResponse 
|| protocol 
== ISO_14443A
) && (oddparity8(frame
[j
]) != ((parityBits 
>> (7-(j
&0x0007))) & 0x01))) { 
 267                         snprintf(line
[j
/16]+(( j 
% 16) * 4),110, "%02x! ", frame
[j
]); 
 269                         snprintf(line
[j
/16]+(( j 
% 16) * 4), 110, " %02x ", frame
[j
]); 
 275                 if(crcStatus 
== 0 || crcStatus 
== 1) 
 277                         char *pos1 
= line
[(data_len
-2)/16]+(((data_len
-2) % 16) * 4); 
 279                         char *pos2 
= line
[(data_len
)/16]+(((data_len
) % 16) * 4); 
 280                         sprintf(pos2
, "%c", ']'); 
 287                         sprintf(line
[0],"<empty trace - possible error>"); 
 290         //--- Draw the CRC column 
 292         char *crc 
= (crcStatus 
== 0 ? "!crc" : (crcStatus 
== 1 ? " ok " : "    ")); 
 294         EndOfTransmissionTimestamp 
= timestamp 
+ duration
; 
 296         if (protocol 
== PROTO_MIFARE
) 
 297                 annotateMifare(explanation
, sizeof(explanation
), frame
, data_len
, parityBytes
, parity_len
, isResponse
); 
 302                         case ICLASS
:            annotateIclass(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 303                         case ISO_14443A
:        annotateIso14443a(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 304                         case ISO_14443B
:        annotateIso14443b(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 305                         case TOPAZ
:                     annotateTopaz(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 310         int num_lines 
= MIN((data_len 
- 1)/16 + 1, 16); 
 311         for (int j 
= 0; j 
< num_lines 
; j
++) { 
 313                         PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s", 
 314                                 (timestamp 
- first_timestamp
), 
 315                                 (EndOfTransmissionTimestamp 
- first_timestamp
), 
 316                                 (isResponse 
? "Tag" : "Rdr"), 
 318                                 (j 
== num_lines
-1) ? crc 
: "    ", 
 319                                 (j 
== num_lines
-1) ? explanation 
: ""); 
 321                         PrintAndLog("            |            |     |%-64s | %s| %s", 
 323                                 (j 
== num_lines
-1) ? crc 
: "    ", 
 324                                 (j 
== num_lines
-1) ? explanation 
: ""); 
 328         if (DecodeMifareData(frame
, data_len
, parityBytes
, isResponse
, mfData
, &mfDataLen
)) { 
 329                 memset(explanation
, 0x00, sizeof(explanation
)); 
 331                         explanation
[0] = '>'; 
 332                         annotateIso14443a(&explanation
[1], sizeof(explanation
) - 1, mfData
, mfDataLen
); 
 334                 uint8_t crcc 
= iso14443A_CRC_check(isResponse
, mfData
, mfDataLen
); 
 335                 PrintAndLog("            |          * | dec |%-64s | %-4s| %s", 
 336                         sprint_hex(mfData
, mfDataLen
), 
 337                         (crcc 
== 0 ? "!crc" : (crcc 
== 1 ? " ok " : "    ")), 
 338                         (true) ? explanation 
: ""); 
 341         if (is_last_record(tracepos
, trace
, traceLen
)) return traceLen
; 
 343         if (showWaitCycles 
&& !isResponse 
&& next_record_is_response(tracepos
, trace
)) { 
 344                 uint32_t next_timestamp 
= *((uint32_t *)(trace 
+ tracepos
)); 
 345                 PrintAndLog(" %10d | %10d | %s | fdt (Frame Delay Time): %d", 
 346                         (EndOfTransmissionTimestamp 
- first_timestamp
), 
 347                         (next_timestamp 
- first_timestamp
), 
 349                         (next_timestamp 
- EndOfTransmissionTimestamp
)); 
 356 int CmdHFList(const char *Cmd
) 
 358         #ifdef WITH_SMARTCARD 
 359                 PrintAndLog("TEST_WITH_SMARTCARD"); 
 362                 PrintAndLog("TEST_WITH_TEST"); 
 364         bool showWaitCycles 
= false; 
 365         bool markCRCBytes 
= false; 
 366         bool loadFromFile 
= false; 
 367         bool saveToFile 
= false; 
 372         char filename
[FILE_PATH_SIZE
] = {0}; 
 373         uint8_t protocol 
= 0; 
 375         // parse command line 
 376         int tlen 
= param_getstr(Cmd
, 0, type
, sizeof(type
)); 
 377         if (param_getlength(Cmd
, 1) == 1) { 
 378                 param1 
= param_getchar(Cmd
, 1); 
 380                 param_getstr(Cmd
, 1, filename
, sizeof(filename
)); 
 382         if (param_getlength(Cmd
, 2) == 1) { 
 383                 param2 
= param_getchar(Cmd
, 2); 
 384         } else if (strlen(filename
) == 0) { 
 385                 param_getstr(Cmd
, 2, filename
, sizeof(filename
)); 
 387         if (param_getlength(Cmd
, 3) == 1) { 
 388                 param3 
= param_getchar(Cmd
, 3); 
 389         } else if (strlen(filename
) == 0) { 
 390                 param_getstr(Cmd
, 3, filename
, sizeof(filename
)); 
 401                         || (param1 
!= 0 && param1 
!= 'f' && param1 
!= 'c' && param1 
!= 'l') 
 402                         || (param2 
!= 0 && param2 
!= 'f' && param2 
!= 'c' && param2 
!= 'l') 
 403                         || (param3 
!= 0 && param3 
!= 'f' && param3 
!= 'c' && param3 
!= 'l')) { 
 408                 if(strcmp(type
, "iclass") == 0) { 
 410                 } else if(strcmp(type
, "mf") == 0) { 
 411                         protocol 
= PROTO_MIFARE
; 
 412                 } else if(strcmp(type
, "14a") == 0) { 
 413                         protocol 
= ISO_14443A
; 
 414                 } else if(strcmp(type
, "14b") == 0)     { 
 415                         protocol 
= ISO_14443B
; 
 416                 } else if(strcmp(type
,"topaz") == 0) { 
 418                 } else if(strcmp(type
, "7816") == 0) { 
 419                         protocol 
= ISO_7816_4
;   
 420                 } else if(strcmp(type
,"raw") == 0) { 
 421                         protocol 
= -1; //No crc, no annotations 
 422                 } else if (strcmp(type
, "save") == 0) { 
 429         if (param1 
== 'f' || param2 
== 'f' || param3 
== 'f') { 
 430                 showWaitCycles 
= true; 
 433         if (param1 
== 'c' || param2 
== 'c' || param3 
== 'c') { 
 437         if (param1 
== 'l' || param2 
== 'l' || param3 
== 'l') { 
 441         if ((loadFromFile 
|| saveToFile
) && strlen(filename
) == 0) { 
 445         if (loadFromFile 
&& saveToFile
) { 
 450                 PrintAndLog("List or save protocol data."); 
 451                 PrintAndLog("Usage:  hf list <protocol> [f] [c] [l <filename>]"); 
 452                 PrintAndLog("        hf list save <filename>"); 
 453                 PrintAndLog("    f      - show frame delay times as well"); 
 454                 PrintAndLog("    c      - mark CRC bytes"); 
 455                 PrintAndLog("    l      - load data from file instead of trace buffer"); 
 456                 PrintAndLog("    save   - save data to file"); 
 457                 PrintAndLog("Supported <protocol> values:"); 
 458                 PrintAndLog("    raw    - just show raw data without annotations"); 
 459                 PrintAndLog("    14a    - interpret data as iso14443a communications"); 
 460                 PrintAndLog("    mf     - interpret data as iso14443a communications and decrypt crypto1 stream"); 
 461                 PrintAndLog("    14b    - interpret data as iso14443b communications"); 
 462                 PrintAndLog("    iclass - interpret data as iclass communications"); 
 463                 PrintAndLog("    topaz  - interpret data as topaz communications"); 
 465                 PrintAndLog("example: hf list 14a f"); 
 466                 PrintAndLog("example: hf list iclass"); 
 467                 PrintAndLog("example: hf list save myCardTrace.trc"); 
 468                 PrintAndLog("example: hf list 14a l myCardTrace.trc"); 
 474         uint32_t tracepos 
= 0; 
 475         uint32_t traceLen 
= 0; 
 478                 #define TRACE_CHUNK_SIZE (1<<16)                // 64K to start with. Will be enough for BigBuf and some room for future extensions 
 479                 FILE *tracefile 
= NULL
; 
 481                 trace 
= malloc(TRACE_CHUNK_SIZE
); 
 483                         PrintAndLog("Cannot allocate memory for trace"); 
 486                 if ((tracefile 
= fopen(filename
,"rb")) == NULL
) {  
 487                         PrintAndLog("Could not open file %s", filename
); 
 491                 while (!feof(tracefile
)) { 
 492                         bytes_read 
= fread(trace
+traceLen
, 1, TRACE_CHUNK_SIZE
, tracefile
); 
 493                         traceLen 
+= bytes_read
; 
 494                         if (!feof(tracefile
)) { 
 495                                 uint8_t *p 
= realloc(trace
, traceLen 
+ TRACE_CHUNK_SIZE
); 
 497                                         PrintAndLog("Cannot allocate memory for trace"); 
 507                 trace 
= malloc(USB_CMD_DATA_SIZE
); 
 508                 // Query for the size of the trace 
 510                 GetFromBigBuf(trace
, USB_CMD_DATA_SIZE
, 0, &response
, -1, false); 
 511                 traceLen 
= response
.arg
[2]; 
 512                 if (traceLen 
> USB_CMD_DATA_SIZE
) { 
 513                         uint8_t *p 
= realloc(trace
, traceLen
); 
 515                                 PrintAndLog("Cannot allocate memory for trace"); 
 520                         GetFromBigBuf(trace
, traceLen
, 0, NULL
, -1, false); 
 525                 FILE *tracefile 
= NULL
; 
 526                 if ((tracefile 
= fopen(filename
,"wb")) == NULL
) {  
 527                         PrintAndLog("Could not create file %s", filename
); 
 530                 fwrite(trace
, 1, traceLen
, tracefile
); 
 531                 PrintAndLog("Recorded Activity (TraceLen = %d bytes) written to file %s", traceLen
, filename
); 
 534                 PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen
); 
 536                 PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); 
 537                 PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); 
 538                 PrintAndLog("iClass    - Timings are not as accurate"); 
 540                 PrintAndLog("      Start |        End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |"); 
 541                 PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|"); 
 544                 while(tracepos 
< traceLen
) 
 546                         tracepos 
= printTraceLine(tracepos
, traceLen
, trace
, protocol
, showWaitCycles
, markCRCBytes
); 
 554 int CmdHFSearch(const char *Cmd
){ 
 557         ans 
= CmdHF14AInfo("s"); 
 559                 PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n"); 
 562         ans 
= HFiClassReader("", false, false); 
 564                 PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n"); 
 567         ans 
= HF15Reader("", false); 
 569                 PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n"); 
 572         //14b is longest test currently (and rarest chip type) ... put last 
 573         ans 
= HF14BInfo(false); 
 575                 PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n"); 
 578         PrintAndLog("\nno known/supported 13.56 MHz tags found\n"); 
 582 int CmdHFSnoop(const char *Cmd
) 
 585         UsbCommand c 
= {CMD_HF_SNIFFER
, {strtol(Cmd
, &pEnd
,0),strtol(pEnd
, &pEnd
,0),0}}; 
 590 static command_t CommandTable
[] =  
 592         {"help",        CmdHelp
,                1, "This help"}, 
 593         {"14a",         CmdHF14A
,               1, "{ ISO14443A RFIDs... }"}, 
 594         {"14b",         CmdHF14B
,               1, "{ ISO14443B RFIDs... }"}, 
 595         {"15",          CmdHF15
,                1, "{ ISO15693 RFIDs... }"}, 
 596         {"epa",         CmdHFEPA
,               1, "{ German Identification Card... }"}, 
 597         {"legic",       CmdHFLegic
,             0, "{ LEGIC RFIDs... }"}, 
 598         {"iclass",      CmdHFiClass
,    1, "{ ICLASS RFIDs... }"}, 
 599         {"mf",          CmdHFMF
,                1, "{ MIFARE RFIDs... }"}, 
 600         {"mfu",         CmdHFMFUltra
,   1, "{ MIFARE Ultralight RFIDs... }"}, 
 601         {"mfp",         CmdHFMFP
,               1, "{ MIFARE Plus RFIDs... }"}, 
 602         {"topaz",       CmdHFTopaz
,             1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, 
 603         {"fido",        CmdHFFido
,              1, "{ FIDO and FIDO2 authenticators... }"}, 
 604         {"tune",        CmdHFTune
,              0, "Continuously measure HF antenna tuning"}, 
 605         {"list",        CmdHFList
,              1, "List protocol data in trace buffer"}, 
 606         {"search",      CmdHFSearch
,    1, "Search for known HF tags [preliminary]"}, 
 607         {"snoop",   CmdHFSnoop
,     0, "<samples to skip (10000)> <triggers to skip (1)> Generic HF Snoop"}, 
 608         {NULL
,          NULL
,                   0, NULL
} 
 611 int CmdHF(const char *Cmd
) 
 613   CmdsParse(CommandTable
, Cmd
); 
 617 int CmdHelp(const char *Cmd
) 
 619   CmdsHelp(CommandTable
);