1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   3 // Copyright (C) Merlok - 2017 
   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 // Command: hf list. It shows data from arm buffer. 
  10 //----------------------------------------------------------------------------- 
  12 #include "cmdhflist.h" 
  22 #include "iso14443crc.h" 
  23 #include "iso15693tools.h" 
  25 #include "protocols.h" 
  26 #include "crapto1/crapto1.h" 
  27 #include "mifare/mifarehost.h" 
  28 #include "mifare/mifaredefault.h" 
  34         uint32_t nt
;        // tag challenge 
  35         uint32_t nt_enc
;    // encrypted tag challenge 
  36         uint8_t nt_enc_par
; // encrypted tag challenge parity 
  37         uint32_t nr_enc
;    // encrypted reader challenge 
  38         uint32_t ar_enc
;    // encrypted reader response 
  39         uint8_t ar_enc_par
; // encrypted reader response parity 
  40         uint32_t at_enc
;    // encrypted tag response 
  41         uint8_t at_enc_par
; // encrypted tag response parity 
  42         bool first_auth
;    // is first authentication 
  43         uint32_t ks2
;       // ar ^ ar_enc 
  44         uint32_t ks3
;       // at ^ at_enc 
  58 static enum MifareAuthSeq MifareAuthState
; 
  59 static TAuthData AuthData
; 
  61 static void ClearAuthData() { 
  64         AuthData
.first_auth 
= true; 
  70  * @brief iso14443A_CRC_check Checks CRC in command or response 
  74  * @return  0 : CRC-command, CRC not ok 
  75  *          1 : CRC-command, CRC ok 
  78 static uint8_t iso14443A_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
) 
  82         if(len 
<= 2) return 2; 
  84         if(isResponse 
& (len 
< 6)) return 2; 
  86         ComputeCrc14443(CRC_14443_A
, data
, len
-2, &b1
, &b2
); 
  87         if (b1 
!= data
[len
-2] || b2 
!= data
[len
-1]) { 
  95 static uint8_t iso14443_4_CRC_check(uint8_t* data
, uint8_t len
) 
  99         if(len 
<= 2) return 2; 
 101         ComputeCrc14443(CRC_14443_A
, data
, len
-2, &b1
, &b2
); 
 102         if (b1 
!= data
[len
-2] || b2 
!= data
[len
-1]) { 
 110 static uint8_t mifare_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
) 
 112         switch(MifareAuthState
) { 
 115                         return iso14443A_CRC_check(isResponse
, data
, len
); 
 123  * @brief iso14443B_CRC_check Checks CRC in command or response 
 127  * @return  0 : CRC-command, CRC not ok 
 128  *          1 : CRC-command, CRC ok 
 129  *          2 : Not crc-command 
 131 static uint8_t iso14443B_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
) 
 135         if(len 
<= 2) return 2; 
 137         ComputeCrc14443(CRC_14443_B
, data
, len
-2, &b1
, &b2
); 
 138         if(b1 
!= data
[len
-2] || b2 
!= data
[len
-1]) { 
 146 static uint8_t iso15693_CRC_check(uint8_t* d
, uint16_t n
) 
 148         if (n 
<= 2) return 2; 
 150         return (Iso15693Crc(d
, n
) == ISO15693_CRC_CHECK 
? 1 : 0); 
 155  * @brief iclass_CRC_Ok Checks CRC in command or response 
 159  * @return  0 : CRC-command, CRC not ok 
 160  *          1 : CRC-command, CRC ok 
 161  *          2 : Not crc-command 
 163 uint8_t iclass_CRC_check(bool isResponse
, uint8_t* data
, uint8_t len
) 
 165         if(len 
< 4) return 2;//CRC commands (and responses) are all at least 4 bytes 
 169         if(!isResponse
)//Commands to tag 
 172                   These commands should have CRC. Total length leftmost 
 175                   12 UPDATE - unsecured, ends with CRC16 
 176                   14 UPDATE - secured, ends with signature instead 
 179                 if(len 
== 4 || len 
== 12)//Covers three of them 
 181                         //Don't include the command byte 
 182                         ComputeCrc14443(CRC_ICLASS
, (data
+1), len
-3, &b1
, &b2
); 
 183                         return b1 
== data
[len 
-2] && b2 
== data
[len
-1]; 
 188                 These tag responses should have CRC. Total length leftmost 
 190                 10  READ        data[8] crc[2] 
 191                 34  READ4       data[32]crc[2] 
 192                 10  UPDATE  data[8] crc[2] 
 193                 10 SELECT   csn[8] crc[2] 
 194                 10  IDENTIFY  asnb[8] crc[2] 
 195                 10  PAGESEL   block1[8] crc[2] 
 196                 10  DETECT    csn[8] crc[2] 
 200                 4  CHECK        chip_response[4] 
 205                 In conclusion, without looking at the command; any response 
 206                 of length 10 or 34 should have CRC 
 208                 if(len 
!= 10 && len 
!= 34) return true; 
 210                 ComputeCrc14443(CRC_ICLASS
, data
, len
-2, &b1
, &b2
); 
 211                 return b1 
== data
[len 
-2] && b2 
== data
[len
-1]; 
 216 void annotateIclass(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
) 
 220         case ICLASS_CMD_ACTALL
:      snprintf(exp
,size
,"ACTALL"); break; 
 221         case ICLASS_CMD_READ_OR_IDENTIFY
:{ 
 223                         snprintf(exp
,size
,"READ(%d)",cmd
[1]); 
 225                         snprintf(exp
,size
,"IDENTIFY"); 
 229         case ICLASS_CMD_SELECT
:      snprintf(exp
,size
,"SELECT"); break; 
 230         case ICLASS_CMD_PAGESEL
:     snprintf(exp
,size
,"PAGESEL(%d)", cmd
[1]); break; 
 231         case ICLASS_CMD_READCHECK_KC
:snprintf(exp
,size
,"READCHECK[Kc](%d)", cmd
[1]); break; 
 232         case ICLASS_CMD_READCHECK_KD
:snprintf(exp
,size
,"READCHECK[Kd](%d)", cmd
[1]); break; 
 233         case ICLASS_CMD_CHECK
:       snprintf(exp
,size
,"CHECK"); break; 
 234         case ICLASS_CMD_DETECT
:      snprintf(exp
,size
,"DETECT"); break; 
 235         case ICLASS_CMD_HALT
:        snprintf(exp
,size
,"HALT"); break; 
 236         case ICLASS_CMD_UPDATE
:      snprintf(exp
,size
,"UPDATE(%d)",cmd
[1]); break; 
 237         case ICLASS_CMD_ACT
:         snprintf(exp
,size
,"ACT"); break; 
 238         case ICLASS_CMD_READ4
:       snprintf(exp
,size
,"READ4(%d)",cmd
[1]); break; 
 239         default:                     snprintf(exp
,size
,"?"); break; 
 245 void annotateIso15693(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
) 
 248                 // Mandatory Commands, all Tags must support them: 
 249                 case ISO15693_INVENTORY             
:snprintf(exp
, size
, "INVENTORY");return; 
 250                 case ISO15693_STAYQUIET             
:snprintf(exp
, size
, "STAY_QUIET");return; 
 251                 // Optional Commands, Tags may support them: 
 252                 case ISO15693_READBLOCK             
:snprintf(exp
, size
, "READBLOCK");return; 
 253                 case ISO15693_WRITEBLOCK            
:snprintf(exp
, size
, "WRITEBLOCK");return; 
 254                 case ISO15693_LOCKBLOCK             
:snprintf(exp
, size
, "LOCKBLOCK");return; 
 255                 case ISO15693_READ_MULTI_BLOCK      
:snprintf(exp
, size
, "READ_MULTI_BLOCK");return; 
 256                 case ISO15693_SELECT                
:snprintf(exp
, size
, "SELECT");return; 
 257                 case ISO15693_RESET_TO_READY        
:snprintf(exp
, size
, "RESET_TO_READY");return; 
 258                 case ISO15693_WRITE_AFI             
:snprintf(exp
, size
, "WRITE_AFI");return; 
 259                 case ISO15693_LOCK_AFI              
:snprintf(exp
, size
, "LOCK_AFI");return; 
 260                 case ISO15693_WRITE_DSFID           
:snprintf(exp
, size
, "WRITE_DSFID");return; 
 261                 case ISO15693_LOCK_DSFID            
:snprintf(exp
, size
, "LOCK_DSFID");return; 
 262                 case ISO15693_GET_SYSTEM_INFO       
:snprintf(exp
, size
, "GET_SYSTEM_INFO");return; 
 263                 case ISO15693_READ_MULTI_SECSTATUS  
:snprintf(exp
, size
, "READ_MULTI_SECSTATUS");return; 
 267         if (cmd
[1] > ISO15693_STAYQUIET 
&& cmd
[1] < ISO15693_READBLOCK
) snprintf(exp
, size
, "Mandatory RFU"); 
 268         else if (cmd
[1] > ISO15693_READ_MULTI_SECSTATUS 
&& cmd
[1] <= 0x9F) snprintf(exp
, size
, "Optional RFU"); 
 269         else if ( cmd
[1] >= 0xA0 && cmd
[1] <= 0xDF ) snprintf(exp
, size
, "Custom command"); 
 270         else if ( cmd
[1] >= 0xE0 && cmd
[1] <= 0xFF ) snprintf(exp
, size
, "Proprietary command"); 
 274 void annotateTopaz(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
) 
 277                 case TOPAZ_REQA                     
:snprintf(exp
, size
, "REQA");break; 
 278                 case TOPAZ_WUPA                     
:snprintf(exp
, size
, "WUPA");break; 
 279                 case TOPAZ_RID                      
:snprintf(exp
, size
, "RID");break; 
 280                 case TOPAZ_RALL                     
:snprintf(exp
, size
, "RALL");break; 
 281                 case TOPAZ_READ                     
:snprintf(exp
, size
, "READ");break; 
 282                 case TOPAZ_WRITE_E                  
:snprintf(exp
, size
, "WRITE-E");break; 
 283                 case TOPAZ_WRITE_NE                 
:snprintf(exp
, size
, "WRITE-NE");break; 
 284                 case TOPAZ_RSEG                     
:snprintf(exp
, size
, "RSEG");break; 
 285                 case TOPAZ_READ8                    
:snprintf(exp
, size
, "READ8");break; 
 286                 case TOPAZ_WRITE_E8                 
:snprintf(exp
, size
, "WRITE-E8");break; 
 287                 case TOPAZ_WRITE_NE8                
:snprintf(exp
, size
, "WRITE-NE8");break; 
 288                 default:                            snprintf(exp
,size
,"?"); break; 
 293 void annotateIso7816(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
) 
 296                 case ISO7816_READ_BINARY                
:snprintf(exp
, size
, "READ BINARY");break; 
 297                 case ISO7816_WRITE_BINARY               
:snprintf(exp
, size
, "WRITE BINARY");break; 
 298                 case ISO7816_UPDATE_BINARY              
:snprintf(exp
, size
, "UPDATE BINARY");break; 
 299                 case ISO7816_ERASE_BINARY               
:snprintf(exp
, size
, "ERASE BINARY");break; 
 300                 case ISO7816_READ_RECORDS               
:snprintf(exp
, size
, "READ RECORD(S)");break; 
 301                 case ISO7816_WRITE_RECORD               
:snprintf(exp
, size
, "WRITE RECORD");break; 
 302                 case ISO7816_APPEND_RECORD              
:snprintf(exp
, size
, "APPEND RECORD");break; 
 303                 case ISO7816_UPDATE_DATA                
:snprintf(exp
, size
, "UPDATE DATA");break; 
 304                 case ISO7816_GET_DATA                   
:snprintf(exp
, size
, "GET DATA");break; 
 305                 case ISO7816_PUT_DATA                   
:snprintf(exp
, size
, "PUT DATA");break; 
 306                 case ISO7816_SELECT_FILE                
:snprintf(exp
, size
, "SELECT FILE");break; 
 307                 case ISO7816_VERIFY                     
:snprintf(exp
, size
, "VERIFY");break; 
 308                 case ISO7816_INTERNAL_AUTHENTICATE      
:snprintf(exp
, size
, "INTERNAL AUTHENTICATE");break; 
 309                 case ISO7816_EXTERNAL_AUTHENTICATE      
:snprintf(exp
, size
, "EXTERNAL AUTHENTICATE");break; 
 310                 case ISO7816_GET_CHALLENGE              
:snprintf(exp
, size
, "GET CHALLENGE");break; 
 311                 case ISO7816_MANAGE_CHANNEL             
:snprintf(exp
, size
, "MANAGE CHANNEL");break; 
 312                 case ISO7816_GET_RESPONSE               
:snprintf(exp
, size
, "GET RESPONSE");break; 
 313                 case ISO7816_ENVELOPE                   
:snprintf(exp
, size
, "ENVELOPE");break; 
 314                 case ISO7816_GET_PROCESSING_OPTIONS     
:snprintf(exp
, size
, "GET PROCESSING OPTIONS");break; 
 315                 default                                 :snprintf(exp
,size
,"?"); break; 
 320 void annotateIso14443_4(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
){ 
 322         if ((cmd
[0] & 0xc3) == 0xc2) { 
 323                 switch (cmd
[0] & 0x30) { 
 324                         case 0x00   : snprintf(exp
, size
, "S-block DESELECT"); break; 
 325                         case 0x30   : snprintf(exp
, size
, "S-block WTX"); break; 
 326                         default     : snprintf(exp
, size
, "S-block (RFU)"); break; 
 330         else if ((cmd
[0] & 0xe0) == 0xa0) { 
 331                 if ((cmd
[0] & 0x10) == 0) 
 332                         snprintf(exp
, size
, "R-block ACK"); 
 334                         snprintf(exp
, size
, "R-block NACK"); 
 339                 switch (cmd
[0] & 0x0c) { 
 340                         case 0x08: // CID following  
 341                         case 0x04: // NAD following 
 344                         case 0x0c: // CID and NAD following 
 348                                 pos 
= 1; // no CID, no NAD 
 351                 annotateIso7816(exp
, size
, &cmd
[pos
], cmdsize
-pos
); 
 358 0E xx = SELECT ID (xx = Chip-ID) 
 360 08 yy = Read Block (yy = block number) 
 361 09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) 
 362 0C = Reset to Inventory 
 364 0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) 
 367 void annotateIso14443b(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
) 
 370         case ISO14443B_REQB   
: snprintf(exp
,size
,"REQB");break; 
 371         case ISO14443B_ATTRIB 
: snprintf(exp
,size
,"ATTRIB");break; 
 372         case ISO14443B_HALT   
: snprintf(exp
,size
,"HALT");break; 
 373         case ISO14443B_INITIATE     
: snprintf(exp
,size
,"INITIATE");break; 
 374         case ISO14443B_SELECT       
: snprintf(exp
,size
,"SELECT(%d)",cmd
[1]);break; 
 375         case ISO14443B_GET_UID      
: snprintf(exp
,size
,"GET UID");break; 
 376         case ISO14443B_READ_BLK     
: snprintf(exp
,size
,"READ_BLK(%d)", cmd
[1]);break; 
 377         case ISO14443B_WRITE_BLK    
: snprintf(exp
,size
,"WRITE_BLK(%d)",cmd
[1]);break; 
 378         case ISO14443B_RESET        
: snprintf(exp
,size
,"RESET");break; 
 379         case ISO14443B_COMPLETION   
: snprintf(exp
,size
,"COMPLETION");break; 
 380         case ISO14443B_AUTHENTICATE 
: snprintf(exp
,size
,"AUTHENTICATE");break; 
 381         default                     : snprintf(exp
,size 
,"?");break; 
 386 void annotateIso14443a(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
) 
 390         case ISO14443A_CMD_WUPA
: 
 391                 snprintf(exp
,size
,"WUPA"); 
 393         case ISO14443A_CMD_ANTICOLL_OR_SELECT
:{ 
 394                 // 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) 
 395                 // 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) 
 398                         snprintf(exp
,size
,"SELECT_UID"); break; 
 401                         snprintf(exp
,size
,"ANTICOLL"); break; 
 404         case ISO14443A_CMD_ANTICOLL_OR_SELECT_2
:{ 
 405                 //95 20 = Anticollision of cascade level2 
 406                 //95 70 = Select of cascade level2 
 409                         snprintf(exp
,size
,"SELECT_UID-2"); break; 
 412                         snprintf(exp
,size
,"ANTICOLL-2"); break; 
 415         case ISO14443A_CMD_REQA
: 
 416                 snprintf(exp
,size
,"REQA"); 
 418         case MIFARE_CMD_READBLOCK
:   snprintf(exp
,size
,"READBLOCK(%d)",cmd
[1]); break; 
 419         case MIFARE_CMD_WRITEBLOCK
:  snprintf(exp
,size
,"WRITEBLOCK(%d)",cmd
[1]); break; 
 420         case ISO14443A_CMD_HALT
: 
 421                 snprintf(exp
,size
,"HALT"); 
 422                 MifareAuthState 
= masNone
; 
 424         case ISO14443A_CMD_RATS
:        snprintf(exp
,size
,"RATS"); break; 
 425         case MIFARE_CMD_INC
:            snprintf(exp
,size
,"INC(%d)",cmd
[1]); break; 
 426         case MIFARE_CMD_DEC
:            snprintf(exp
,size
,"DEC(%d)",cmd
[1]); break; 
 427         case MIFARE_CMD_RESTORE
:        snprintf(exp
,size
,"RESTORE(%d)",cmd
[1]); break; 
 428         case MIFARE_CMD_TRANSFER
:       snprintf(exp
,size
,"TRANSFER(%d)",cmd
[1]); break; 
 429         case MIFARE_AUTH_KEYA
: 
 431                         snprintf(exp
,size
,"AUTH-A(%d)",cmd
[1]); 
 432                         MifareAuthState 
= masNt
; 
 434                         //  case MIFARE_ULEV1_VERSION :  both 0x60. 
 435                         snprintf(exp
,size
,"EV1 VERSION"); 
 438         case MIFARE_AUTH_KEYB
: 
 439                 MifareAuthState 
= masNt
; 
 440                 snprintf(exp
,size
,"AUTH-B(%d)",cmd
[1]); 
 442         case MIFARE_MAGICWUPC1
:         snprintf(exp
,size
,"MAGIC WUPC1"); break; 
 443         case MIFARE_MAGICWUPC2
:         snprintf(exp
,size
,"MAGIC WUPC2"); break; 
 444         case MIFARE_MAGICWIPEC
:         snprintf(exp
,size
,"MAGIC WIPEC"); break; 
 445         case MIFARE_ULC_AUTH_1
:     snprintf(exp
,size
,"AUTH "); break; 
 446         case MIFARE_ULC_AUTH_2
:     snprintf(exp
,size
,"AUTH_ANSW"); break; 
 447         case MIFARE_ULEV1_AUTH
: 
 449                         snprintf(exp
,size
,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd
[1], cmd
[2], cmd
[3], cmd
[4] ); 
 451                         snprintf(exp
,size
,"PWD-AUTH"); 
 453         case MIFARE_ULEV1_FASTREAD
:{ 
 454                 if ( cmdsize 
>=3 && cmd
[2] <= 0xE6) 
 455                         snprintf(exp
,size
,"READ RANGE (%d-%d)",cmd
[1],cmd
[2]); 
 457                         snprintf(exp
,size
,"?"); 
 460         case MIFARE_ULC_WRITE
:{ 
 462                         snprintf(exp
,size
,"WRITEBLOCK(%d)",cmd
[1]); 
 464                         snprintf(exp
,size
,"?"); 
 467         case MIFARE_ULEV1_READ_CNT
:{ 
 469                         snprintf(exp
,size
,"READ CNT(%d)",cmd
[1]); 
 471                         snprintf(exp
,size
,"?"); 
 474         case MIFARE_ULEV1_INCR_CNT
:{ 
 476                         snprintf(exp
,size
,"INCR(%d)",cmd
[1]); 
 478                         snprintf(exp
,size
,"?"); 
 481         case MIFARE_ULEV1_READSIG
:      snprintf(exp
,size
,"READ_SIG"); break; 
 482         case MIFARE_ULEV1_CHECKTEAR
:    snprintf(exp
,size
,"CHK_TEARING(%d)",cmd
[1]); break; 
 483         case MIFARE_ULEV1_VCSL
:     snprintf(exp
,size
,"VCSL"); break; 
 484         default:                        snprintf(exp
,size
,"?"); break; 
 489 void annotateMifare(char *exp
, size_t size
, uint8_t* cmd
, uint8_t cmdsize
, uint8_t* parity
, uint8_t paritysize
, bool isResponse
) { 
 490         if (!isResponse 
&& cmdsize 
== 1) { 
 492                         case ISO14443A_CMD_WUPA
: 
 493                         case ISO14443A_CMD_REQA
: 
 494                                 MifareAuthState 
= masNone
; 
 502         if (MifareAuthState 
== masNone
) { 
 503                 if (cmdsize 
== 9 && cmd
[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT 
&& cmd
[1] == 0x70) { 
 505                         AuthData
.uid 
= bytes_to_num(&cmd
[2], 4); 
 507                 if (cmdsize 
== 9 && cmd
[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 
&& cmd
[1] == 0x70) { 
 509                         AuthData
.uid 
= bytes_to_num(&cmd
[2], 4); 
 513         switch(MifareAuthState
) { 
 515                         if (cmdsize 
== 4 && isResponse
) { 
 516                                 snprintf(exp
,size
,"AUTH: nt %s", (AuthData
.first_auth
) ? "" : "(enc)"); 
 517                                 MifareAuthState 
= masNrAr
; 
 518                                 if (AuthData
.first_auth
) { 
 519                                         AuthData
.nt 
= bytes_to_num(cmd
, 4); 
 521                                         AuthData
.nt_enc 
= bytes_to_num(cmd
, 4); 
 522                                         AuthData
.nt_enc_par 
= parity
[0]; 
 526                                 MifareAuthState 
= masError
; 
 530                         if (cmdsize 
== 8 && !isResponse
) { 
 531                                 snprintf(exp
,size
,"AUTH: nr ar (enc)"); 
 532                                 MifareAuthState 
= masAt
; 
 533                                 AuthData
.nr_enc 
= bytes_to_num(cmd
, 4); 
 534                                 AuthData
.ar_enc 
= bytes_to_num(&cmd
[4], 4); 
 535                                 AuthData
.ar_enc_par 
= parity
[0] << 4; 
 538                                 MifareAuthState 
= masError
; 
 542                         if (cmdsize 
== 4 && isResponse
) { 
 543                                 snprintf(exp
,size
,"AUTH: at (enc)"); 
 544                                 MifareAuthState 
= masAuthComplete
; 
 545                                 AuthData
.at_enc 
= bytes_to_num(cmd
, 4); 
 546                                 AuthData
.at_enc_par 
= parity
[0]; 
 549                                 MifareAuthState 
= masError
; 
 556         if (!isResponse 
&& ((MifareAuthState 
== masNone
) || (MifareAuthState 
== masError
))) 
 557                 annotateIso14443a(exp
, size
, cmd
, cmdsize
); 
 562 static uint64_t GetCrypto1ProbableKey(TAuthData 
*ad
) { 
 563         struct Crypto1State 
*revstate 
= lfsr_recovery64(ad
->ks2
, ad
->ks3
); 
 564         lfsr_rollback_word(revstate
, 0, 0); 
 565         lfsr_rollback_word(revstate
, 0, 0); 
 566         lfsr_rollback_word(revstate
, ad
->nr_enc
, 1); 
 567         lfsr_rollback_word(revstate
, ad
->uid 
^ ad
->nt
, 0); 
 570         crypto1_get_lfsr(revstate
, &lfsr
); 
 571         crypto1_destroy(revstate
); 
 577 static bool NTParityChk(TAuthData 
*ad
, uint32_t ntx
) { 
 579                 (oddparity8(ntx 
>> 8 & 0xff) ^ (ntx 
& 0x01) ^ ((ad
->nt_enc_par 
>> 5) & 0x01) ^ (ad
->nt_enc 
& 0x01)) || 
 580                 (oddparity8(ntx 
>> 16 & 0xff) ^ (ntx 
>> 8 & 0x01) ^ ((ad
->nt_enc_par 
>> 6) & 0x01) ^ (ad
->nt_enc 
>> 8 & 0x01)) || 
 581                 (oddparity8(ntx 
>> 24 & 0xff) ^ (ntx 
>> 16 & 0x01) ^ ((ad
->nt_enc_par 
>> 7) & 0x01) ^ (ad
->nt_enc 
>> 16 & 0x01)) 
 585         uint32_t ar 
= prng_successor(ntx
, 64); 
 587                 (oddparity8(ar 
>> 8 & 0xff) ^ (ar 
& 0x01) ^ ((ad
->ar_enc_par 
>> 5) & 0x01) ^ (ad
->ar_enc 
& 0x01)) || 
 588                 (oddparity8(ar 
>> 16 & 0xff) ^ (ar 
>> 8 & 0x01) ^ ((ad
->ar_enc_par 
>> 6) & 0x01) ^ (ad
->ar_enc 
>> 8 & 0x01)) || 
 589                 (oddparity8(ar 
>> 24 & 0xff) ^ (ar 
>> 16 & 0x01) ^ ((ad
->ar_enc_par 
>> 7) & 0x01) ^ (ad
->ar_enc 
>> 16 & 0x01)) 
 593         uint32_t at 
= prng_successor(ntx
, 96); 
 595                 (oddparity8(ar 
& 0xff) ^ (at 
>> 24 & 0x01) ^ ((ad
->ar_enc_par 
>> 4) & 0x01) ^ (ad
->at_enc 
>> 24 & 0x01)) || 
 596                 (oddparity8(at 
>> 8 & 0xff) ^ (at 
& 0x01) ^ ((ad
->at_enc_par 
>> 5) & 0x01) ^ (ad
->at_enc 
& 0x01)) || 
 597                 (oddparity8(at 
>> 16 & 0xff) ^ (at 
>> 8 & 0x01) ^ ((ad
->at_enc_par 
>> 6) & 0x01) ^ (ad
->at_enc 
>> 8 & 0x01)) || 
 598                 (oddparity8(at 
>> 24 & 0xff) ^ (at 
>> 16 & 0x01) ^ ((ad
->at_enc_par 
>> 7) & 0x01) ^ (ad
->at_enc 
>> 16 & 0x01)) 
 606 static bool CheckCrypto1Parity(uint8_t *cmd_enc
, uint8_t cmdsize
, uint8_t *cmd
, uint8_t *parity_enc
) { 
 607         for (int i 
= 0; i 
< cmdsize 
- 1; i
++) { 
 608                 if (oddparity8(cmd
[i
]) ^ (cmd
[i 
+ 1] & 0x01) ^ ((parity_enc
[i 
/ 8] >> (7 - i 
% 8)) & 0x01) ^ (cmd_enc
[i 
+ 1] & 0x01)) 
 616 static bool NestedCheckKey(uint64_t key
, TAuthData 
*ad
, uint8_t *cmd
, uint8_t cmdsize
, uint8_t *parity
) { 
 617         uint8_t buf
[32] = {0}; 
 618         struct Crypto1State 
*pcs
; 
 623         pcs 
= crypto1_create(key
); 
 624         uint32_t nt1 
= crypto1_word(pcs
, ad
->nt_enc 
^ ad
->uid
, 1) ^ ad
->nt_enc
; 
 625         uint32_t ar 
= prng_successor(nt1
, 64); 
 626         uint32_t at 
= prng_successor(nt1
, 96); 
 628         crypto1_word(pcs
, ad
->nr_enc
, 1); 
 629 //  uint32_t nr1 = crypto1_word(pcs, ad->nr_enc, 1) ^ ad->nr_enc;  // if needs deciphered nr 
 630         uint32_t ar1 
= crypto1_word(pcs
, 0, 0) ^ ad
->ar_enc
; 
 631         uint32_t at1 
= crypto1_word(pcs
, 0, 0) ^ ad
->at_enc
; 
 633         if (!(ar 
== ar1 
&& at 
== at1 
&& NTParityChk(ad
, nt1
))) { 
 634                 crypto1_destroy(pcs
); 
 638         memcpy(buf
, cmd
, cmdsize
); 
 639         mf_crypto1_decrypt(pcs
, buf
, cmdsize
, 0); 
 641         crypto1_destroy(pcs
); 
 643         if (!CheckCrypto1Parity(cmd
, cmdsize
, buf
, parity
)) 
 646         if(!CheckCrc14443(CRC_14443_A
, buf
, cmdsize
)) 
 650         AuthData
.ks2 
= AuthData
.ar_enc 
^ ar
; 
 651         AuthData
.ks3 
= AuthData
.at_enc 
^ at
; 
 657 static bool DecodeMifareData(uint8_t *cmd
, uint8_t cmdsize
, uint8_t *parity
, bool isResponse
, uint8_t *mfData
, size_t *mfDataLen
) { 
 658         static struct Crypto1State 
*traceCrypto1
; 
 659         static uint64_t mfLastKey
; 
 663         if (MifareAuthState 
== masAuthComplete
) { 
 665                         crypto1_destroy(traceCrypto1
); 
 669                 MifareAuthState 
= masFirstData
; 
 676         if (MifareAuthState 
== masFirstData
) { 
 677                 if (AuthData
.first_auth
) { 
 678                         AuthData
.ks2 
= AuthData
.ar_enc 
^ prng_successor(AuthData
.nt
, 64); 
 679                         AuthData
.ks3 
= AuthData
.at_enc 
^ prng_successor(AuthData
.nt
, 96); 
 681                         mfLastKey 
= GetCrypto1ProbableKey(&AuthData
); 
 682                         PrintAndLog("            |          * | key | probable key:%012"PRIx64
" Prng:%s   ks2:%08x ks3:%08x |     |", 
 684                                 validate_prng_nonce(AuthData
.nt
) ? "WEAK": "HARD", 
 688                         AuthData
.first_auth 
= false; 
 690                         traceCrypto1 
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
); 
 693                                 crypto1_destroy(traceCrypto1
); 
 697                         // check last used key 
 699                                 if (NestedCheckKey(mfLastKey
, &AuthData
, cmd
, cmdsize
, parity
)) { 
 700                                         PrintAndLog("            |          * | key | last used key:%012"PRIx64
"            ks2:%08x ks3:%08x |     |", 
 705                                 traceCrypto1 
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
); 
 709                         // check default keys 
 711                                 for (int defaultKeyCounter 
= 0; defaultKeyCounter 
< MifareDefaultKeysSize
; defaultKeyCounter
++){ 
 712                                         if (NestedCheckKey(MifareDefaultKeys
[defaultKeyCounter
], &AuthData
, cmd
, cmdsize
, parity
)) { 
 713                                                 PrintAndLog("            |          * | key | default key:%012"PRIx64
"              ks2:%08x ks3:%08x |     |", 
 714                                                         MifareDefaultKeys
[defaultKeyCounter
], 
 718                                                 mfLastKey 
= MifareDefaultKeys
[defaultKeyCounter
]; 
 719                                                 traceCrypto1 
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
); 
 726                         if (!traceCrypto1 
&& validate_prng_nonce(AuthData
.nt
)) { 
 727                                 uint32_t ntx 
= prng_successor(AuthData
.nt
, 90); 
 728                                 for (int i 
= 0; i 
< 16383; i
++) { 
 729                                         ntx 
= prng_successor(ntx
, 1); 
 730                                         if (NTParityChk(&AuthData
, ntx
)){ 
 732                                                 uint32_t ks2 
= AuthData
.ar_enc 
^ prng_successor(ntx
, 64); 
 733                                                 uint32_t ks3 
= AuthData
.at_enc 
^ prng_successor(ntx
, 96); 
 734                                                 struct Crypto1State 
*pcs 
= lfsr_recovery64(ks2
, ks3
); 
 735                                                 memcpy(mfData
, cmd
, cmdsize
); 
 736                                                 mf_crypto1_decrypt(pcs
, mfData
, cmdsize
, 0); 
 738                                                 crypto1_destroy(pcs
); 
 739                                                 if (CheckCrypto1Parity(cmd
, cmdsize
, mfData
, parity
) && CheckCrc14443(CRC_14443_A
, mfData
, cmdsize
)) { 
 744                                                         mfLastKey 
= GetCrypto1ProbableKey(&AuthData
); 
 745                                                         PrintAndLog("            |          * | key | nested probable key:%012"PRIx64
"      ks2:%08x ks3:%08x |     |", 
 750                                                         traceCrypto1 
= lfsr_recovery64(AuthData
.ks2
, AuthData
.ks3
); 
 759                                 printf("hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData
.uid
, AuthData
.nt
, AuthData
.ar_enc
, AuthData
.at_enc
); 
 760                                 MifareAuthState 
= masError
; 
 762                                 /* TOO SLOW( needs to have more strong filter. with this filter - aprox 4 mln tests 
 763                                 uint32_t t = msclock(); 
 766                                 for (uint32_t i = 0; i < 0xFFFFFFFF; i++) { 
 767                                         if (NTParityChk(&AuthData, i)){ 
 769                                                 uint32_t ks2 = AuthData.ar_enc ^ prng_successor(i, 64); 
 770                                                 uint32_t ks3 = AuthData.at_enc ^ prng_successor(i, 96); 
 771                                                 struct Crypto1State *pcs = lfsr_recovery64(ks2, ks3); 
 779                                                         printf("delta=%d n=%d ks2=%x ks3=%x \n", msclock() - t1 , n, ks2, ks3); 
 785                                 printf("delta=%d n=%d\n", msclock() - t, n); 
 792                 MifareAuthState 
= masData
; 
 795         if (MifareAuthState 
== masData 
&& traceCrypto1
) { 
 796                 memcpy(mfData
, cmd
, cmdsize
); 
 797                 mf_crypto1_decrypt(traceCrypto1
, mfData
, cmdsize
, 0); 
 798                 *mfDataLen 
= cmdsize
; 
 801         return *mfDataLen 
> 0; 
 805 bool is_last_record(uint16_t tracepos
, uint8_t *trace
, uint16_t traceLen
) 
 807         return(tracepos 
+ sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen
); 
 811 bool next_record_is_response(uint16_t tracepos
, uint8_t *trace
) 
 813         uint16_t next_records_datalen 
= *((uint16_t *)(trace 
+ tracepos 
+ sizeof(uint32_t) + sizeof(uint16_t))); 
 815         return(next_records_datalen 
& 0x8000); 
 819 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
) 
 822 #define MAX_TOPAZ_READER_CMD_LEN    16 
 824         uint32_t last_timestamp 
= timestamp 
+ *duration
; 
 826         if ((*data_len 
!= 1) || (frame
[0] == TOPAZ_WUPA
) || (frame
[0] == TOPAZ_REQA
)) return false; 
 828         memcpy(topaz_reader_command
, frame
, *data_len
); 
 830         while (!is_last_record(*tracepos
, trace
, traceLen
) && !next_record_is_response(*tracepos
, trace
)) { 
 831                 uint32_t next_timestamp 
= *((uint32_t *)(trace 
+ *tracepos
)); 
 832                 *tracepos 
+= sizeof(uint32_t); 
 833                 uint16_t next_duration 
= *((uint16_t *)(trace 
+ *tracepos
)); 
 834                 *tracepos 
+= sizeof(uint16_t); 
 835                 uint16_t next_data_len 
= *((uint16_t *)(trace 
+ *tracepos
)) & 0x7FFF; 
 836                 *tracepos 
+= sizeof(uint16_t); 
 837                 uint8_t *next_frame 
= (trace 
+ *tracepos
); 
 838                 *tracepos 
+= next_data_len
; 
 839                 if ((next_data_len 
== 1) && (*data_len 
+ next_data_len 
<= MAX_TOPAZ_READER_CMD_LEN
)) { 
 840                         memcpy(topaz_reader_command 
+ *data_len
, next_frame
, next_data_len
); 
 841                         *data_len 
+= next_data_len
; 
 842                         last_timestamp 
= next_timestamp 
+ next_duration
; 
 845                         *tracepos 
= *tracepos 
- next_data_len 
- sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t); 
 848                 uint16_t next_parity_len 
= (next_data_len
-1)/8 + 1; 
 849                 *tracepos 
+= next_parity_len
; 
 852         *duration 
= last_timestamp 
- timestamp
; 
 858 uint16_t printTraceLine(uint16_t tracepos
, uint16_t traceLen
, uint8_t *trace
, uint8_t protocol
, bool showWaitCycles
, bool markCRCBytes
) 
 861         uint16_t data_len
, parity_len
; 
 863         uint8_t topaz_reader_command
[9]; 
 864         uint32_t timestamp
, first_timestamp
, EndOfTransmissionTimestamp
; 
 865         char explanation
[30] = {0}; 
 866         uint8_t mfData
[32] = {0}; 
 867         size_t mfDataLen 
= 0; 
 869         if (tracepos 
+ sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen
) return traceLen
; 
 871         first_timestamp 
= *((uint32_t *)(trace
)); 
 872         timestamp 
= *((uint32_t *)(trace 
+ tracepos
)); 
 875         duration 
= *((uint16_t *)(trace 
+ tracepos
)); 
 877         data_len 
= *((uint16_t *)(trace 
+ tracepos
)); 
 880         if (data_len 
& 0x8000) { 
 886         parity_len 
= (data_len
-1)/8 + 1; 
 888         if (tracepos 
+ data_len 
+ parity_len 
> traceLen
) { 
 891         uint8_t *frame 
= trace 
+ tracepos
; 
 892         tracepos 
+= data_len
; 
 893         uint8_t *parityBytes 
= trace 
+ tracepos
; 
 894         tracepos 
+= parity_len
; 
 896         if (protocol 
== TOPAZ 
&& !isResponse
) { 
 897                 // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each. 
 899                 if (merge_topaz_reader_frames(timestamp
, &duration
, &tracepos
, traceLen
, trace
, frame
, topaz_reader_command
, &data_len
)) { 
 900                         frame 
= topaz_reader_command
; 
 904         //Check the CRC status 
 905         uint8_t crcStatus 
= 2; 
 910                                 crcStatus 
= iclass_CRC_check(isResponse
, frame
, data_len
); 
 914                                 crcStatus 
= iso14443B_CRC_check(isResponse
, frame
, data_len
); 
 917                                 crcStatus 
= mifare_CRC_check(isResponse
, frame
, data_len
); 
 920                                 crcStatus 
= iso14443A_CRC_check(isResponse
, frame
, data_len
); 
 923                                 crcStatus 
= iso14443_4_CRC_check(frame
, data_len
); 
 926                                 crcStatus 
= iso15693_CRC_check(frame
, data_len
); 
 932         //0 CRC-command, CRC not ok 
 933         //1 CRC-command, CRC ok 
 936         //--- Draw the data column 
 939         for (int j 
= 0; j 
< data_len 
&& j
/16 < 16; j
++) { 
 940                 uint8_t parityBits 
= parityBytes
[j
>>3]; 
 941                 if (protocol 
!= ISO_14443B
 
 942                         && protocol 
!= ISO_15693
 
 943                         && protocol 
!= ISO_7816_4
 
 944                         && (isResponse 
|| protocol 
== ISO_14443A
) 
 945                         && (oddparity8(frame
[j
]) != ((parityBits 
>> (7-(j
&0x0007))) & 0x01))) { 
 946                         snprintf(line
[j
/16]+(( j 
% 16) * 4), 110, " %02x!", frame
[j
]); 
 948                         snprintf(line
[j
/16]+(( j 
% 16) * 4), 110, " %02x ", frame
[j
]); 
 953                 if(crcStatus 
== 0 || crcStatus 
== 1) 
 955                         char *pos1 
= line
[(data_len
-2)/16]+(((data_len
-2) % 16) * 4); 
 957                         char *pos2 
= line
[(data_len
)/16]+(((data_len
) % 16) * 4); 
 958                         sprintf(pos2
, "%c", ']'); 
 962         // mark short bytes (less than 8 Bit + Parity) 
 963         if (protocol 
== ISO_14443A 
|| protocol 
== PROTO_MIFARE
) { 
 964                 if (duration 
< 128 * (9 * data_len
)) { 
 965                         line
[(data_len
-1)/16][((data_len
-1)%16
) * 4 + 3] = '\''; 
 970                 sprintf(line
[0]," <empty trace - possible error>"); 
 973         //--- Draw the CRC column 
 974         char *crc 
= (crcStatus 
== 0 ? "!crc" : (crcStatus 
== 1 ? " ok " : "    ")); 
 976         EndOfTransmissionTimestamp 
= timestamp 
+ duration
; 
 978         if (protocol 
== PROTO_MIFARE
) 
 979                 annotateMifare(explanation
, sizeof(explanation
), frame
, data_len
, parityBytes
, parity_len
, isResponse
); 
 984                         case ICLASS
:      annotateIclass(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 985                         case ISO_14443A
:  annotateIso14443a(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 986                         case ISO_14443B
:  annotateIso14443b(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 987                         case TOPAZ
:       annotateTopaz(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 988                         case ISO_15693
:   annotateIso15693(explanation
,sizeof(explanation
),frame
,data_len
); break; 
 989                         case ISO_7816_4
:  annotateIso7816(explanation
, sizeof(explanation
), frame
, data_len
); break; 
 990                         case ISO_14443_4
: annotateIso14443_4(explanation
, sizeof(explanation
), frame
, data_len
); break; 
 995         int num_lines 
= MIN((data_len 
- 1)/16 + 1, 16); 
 996         for (int j 
= 0; j 
< num_lines 
; j
++) { 
 998                         PrintAndLog(" %10" PRIu32 
" | %10" PRIu32 
" | %s |%-64s | %s| %s", 
 999                                 (timestamp 
- first_timestamp
), 
1000                                 (EndOfTransmissionTimestamp 
- first_timestamp
), 
1001                                 (isResponse 
? "Tag" : "Rdr"), 
1003                                 (j 
== num_lines
-1) ? crc 
: "    ", 
1004                                 (j 
== num_lines
-1) ? explanation 
: ""); 
1006                         PrintAndLog("            |            |     |%-64s | %s| %s", 
1008                                 (j 
== num_lines
-1) ? crc 
: "    ", 
1009                                 (j 
== num_lines
-1) ? explanation 
: ""); 
1013         if (DecodeMifareData(frame
, data_len
, parityBytes
, isResponse
, mfData
, &mfDataLen
)) { 
1014                 memset(explanation
, 0x00, sizeof(explanation
)); 
1016                         explanation
[0] = '>'; 
1017                         annotateIso14443a(&explanation
[1], sizeof(explanation
) - 1, mfData
, mfDataLen
); 
1019                 uint8_t crcc 
= iso14443A_CRC_check(isResponse
, mfData
, mfDataLen
); 
1020                 PrintAndLog("            |          * | dec |%-64s | %-4s| %s", 
1021                         sprint_hex(mfData
, mfDataLen
), 
1022                         (crcc 
== 0 ? "!crc" : (crcc 
== 1 ? " ok " : "    ")), 
1023                         (true) ? explanation 
: ""); 
1026         if (is_last_record(tracepos
, trace
, traceLen
)) return traceLen
; 
1028         if (showWaitCycles 
&& !isResponse 
&& next_record_is_response(tracepos
, trace
)) { 
1029                 uint32_t next_timestamp 
= *((uint32_t *)(trace 
+ tracepos
)); 
1030                 PrintAndLog(" %10d | %10d | %s | fdt (Frame Delay Time): %d", 
1031                         (EndOfTransmissionTimestamp 
- first_timestamp
), 
1032                         (next_timestamp 
- first_timestamp
), 
1034                         (next_timestamp 
- EndOfTransmissionTimestamp
)); 
1041 int CmdHFList(const char *Cmd
) 
1043         bool showWaitCycles 
= false; 
1044         bool markCRCBytes 
= false; 
1045         bool loadFromFile 
= false; 
1046         bool PCSCtrace 
= false; 
1047         bool saveToFile 
= false; 
1052         char type
[40] = {0}; 
1053         char filename
[FILE_PATH_SIZE
] = {0}; 
1054         uint8_t protocol 
= 0; 
1056         // parse command line 
1057         int tlen 
= param_getstr(Cmd
, 0, type
, sizeof(type
)); 
1058         if (param_getlength(Cmd
, 1) == 1) { 
1059                 param1 
= param_getchar(Cmd
, 1); 
1061                 param_getstr(Cmd
, 1, filename
, sizeof(filename
)); 
1063         if (param_getlength(Cmd
, 2) == 1) { 
1064                 param2 
= param_getchar(Cmd
, 2); 
1065         } else if (strlen(filename
) == 0) { 
1066                 param_getstr(Cmd
, 2, filename
, sizeof(filename
)); 
1068         if (param_getlength(Cmd
, 3) == 1) { 
1069                 param3 
= param_getchar(Cmd
, 3); 
1070         } else if (strlen(filename
) == 0) { 
1071                 param_getstr(Cmd
, 3, filename
, sizeof(filename
)); 
1073         if (param_getlength(Cmd
, 4) == 1) { 
1074                 param4 
= param_getchar(Cmd
, 4); 
1075         } else if (strlen(filename
) == 0) { 
1076                 param_getstr(Cmd
, 4, filename
, sizeof(filename
)); 
1080         bool errors 
= false; 
1087                         || (param1 
!= 0 && param1 
!= 'f' && param1 
!= 'c' && param1 
!= 'l' && param1 
!= 'p') 
1088                         || (param2 
!= 0 && param2 
!= 'f' && param2 
!= 'c' && param2 
!= 'l' && param1 
!= 'p') 
1089                         || (param3 
!= 0 && param3 
!= 'f' && param3 
!= 'c' && param3 
!= 'l' && param1 
!= 'p') 
1090                         || (param4 
!= 0 && param4 
!= 'f' && param4 
!= 'c' && param4 
!= 'l' && param4 
!= 'p')) { 
1095                 if (strcmp(type
,     "iclass") == 0)    protocol 
= ICLASS
; 
1096                 else if(strcmp(type
, "14a") == 0)       protocol 
= ISO_14443A
; 
1097                 else if(strcmp(type
, "mf") == 0)        protocol 
= PROTO_MIFARE
; 
1098                 else if(strcmp(type
, "14b") == 0)       protocol 
= ISO_14443B
; 
1099                 else if(strcmp(type
, "topaz") == 0)     protocol 
= TOPAZ
; 
1100                 else if(strcmp(type
, "7816") == 0)      protocol 
= ISO_7816_4
; 
1101                 else if(strcmp(type
, "14-4") == 0)      protocol 
= ISO_14443_4
; 
1102                 else if(strcmp(type
, "15") == 0)        protocol 
= ISO_15693
; 
1103                 else if(strcmp(type
, "raw") == 0)       protocol 
= -1;//No crc, no annotations 
1104                 else if (strcmp(type
, "save") == 0)     saveToFile 
= true; 
1108         if (param1 
== 'f' || param2 
== 'f' || param3 
== 'f' || param4 
== 'f') { 
1109                 showWaitCycles 
= true; 
1112         if (param1 
== 'c' || param2 
== 'c' || param3 
== 'c' || param4 
== 'c') { 
1113                 markCRCBytes 
= true; 
1116         if (param1 
== 'l' || param2 
== 'l' || param3 
== 'l' || param4 
== 'l') { 
1117                 loadFromFile 
= true; 
1120         if (param1 
== 'p' || param2 
== 'p' || param3 
== 'p' || param4 
== 'p') { 
1124         if ((loadFromFile 
|| saveToFile
) && strlen(filename
) == 0) { 
1128         if (loadFromFile 
&& saveToFile
) { 
1133                 PrintAndLog("List or save protocol data."); 
1134                 PrintAndLog("Usage:  hf list <protocol> [f] [c] [p] [l <filename>]"); 
1135                 PrintAndLog("        hf list save <filename>"); 
1136                 PrintAndLog("    f      - show frame delay times as well"); 
1137                 PrintAndLog("    c      - mark CRC bytes"); 
1138                 PrintAndLog("    p      - use trace buffer from PCSC card reader instead of PM3"); 
1139                 PrintAndLog("    l      - load data from file instead of trace buffer"); 
1140                 PrintAndLog("    save   - save data to file"); 
1141                 PrintAndLog("Supported <protocol> values:"); 
1142                 PrintAndLog("    raw    - just show raw data without annotations"); 
1143                 PrintAndLog("    14a    - interpret data as iso14443a communications"); 
1144                 PrintAndLog("    mf     - interpret data as iso14443a communications and decrypt crypto1 stream"); 
1145                 PrintAndLog("    14b    - interpret data as iso14443b communications"); 
1146                 PrintAndLog("    15     - interpret data as iso15693 communications"); 
1147                 PrintAndLog("    iclass - interpret data as iclass communications"); 
1148                 PrintAndLog("    topaz  - interpret data as topaz communications"); 
1149                 PrintAndLog("    7816   - interpret data as 7816-4 APDU communications"); 
1150                 PrintAndLog("    14-4   - interpret data as ISO14443-4 communications"); 
1152                 PrintAndLog("example: hf list 14a f"); 
1153                 PrintAndLog("example: hf list iclass"); 
1154                 PrintAndLog("example: hf list save myCardTrace.trc"); 
1155                 PrintAndLog("example: hf list 14a l myCardTrace.trc"); 
1161         uint32_t tracepos 
= 0; 
1162         uint32_t traceLen 
= 0; 
1165                 #define TRACE_CHUNK_SIZE (1<<16)        // 64K to start with. Will be enough for BigBuf and some room for future extensions 
1166                 FILE *tracefile 
= NULL
; 
1168                 trace 
= malloc(TRACE_CHUNK_SIZE
); 
1169                 if (trace 
== NULL
) { 
1170                         PrintAndLog("Cannot allocate memory for trace"); 
1173                 if ((tracefile 
= fopen(filename
,"rb")) == NULL
) { 
1174                         PrintAndLog("Could not open file %s", filename
); 
1178                 while (!feof(tracefile
)) { 
1179                         bytes_read 
= fread(trace
+traceLen
, 1, TRACE_CHUNK_SIZE
, tracefile
); 
1180                         traceLen 
+= bytes_read
; 
1181                         if (!feof(tracefile
)) { 
1182                                 uint8_t *p 
= realloc(trace
, traceLen 
+ TRACE_CHUNK_SIZE
); 
1184                                         PrintAndLog("Cannot allocate memory for trace"); 
1193         } else if (PCSCtrace
) { 
1194                 trace 
= pcsc_get_trace_addr(); 
1195                 traceLen 
= pcsc_get_traceLen(); 
1197                 trace 
= malloc(USB_CMD_DATA_SIZE
); 
1198                 // Query for the size of the trace 
1199                 UsbCommand response
; 
1200                 GetFromBigBuf(trace
, USB_CMD_DATA_SIZE
, 0, &response
, -1, false); 
1201                 traceLen 
= response
.arg
[2]; 
1202                 if (traceLen 
> USB_CMD_DATA_SIZE
) { 
1203                         uint8_t *p 
= realloc(trace
, traceLen
); 
1205                                 PrintAndLog("Cannot allocate memory for trace"); 
1210                         GetFromBigBuf(trace
, traceLen
, 0, NULL
, -1, false); 
1215                 FILE *tracefile 
= NULL
; 
1216                 if ((tracefile 
= fopen(filename
,"wb")) == NULL
) { 
1217                         PrintAndLog("Could not create file %s", filename
); 
1220                 fwrite(trace
, 1, traceLen
, tracefile
); 
1221                 PrintAndLog("Recorded Activity (TraceLen = %d bytes) written to file %s", traceLen
, filename
); 
1224                 PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen
); 
1226                 PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); 
1227                 PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)"); 
1228                 PrintAndLog("iClass    - Timings are not as accurate"); 
1230                 PrintAndLog("      Start |        End | Src | Data (! denotes parity error, ' denotes short bytes)            | CRC | Annotation         |"); 
1231                 PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|"); 
1234                 while(tracepos 
< traceLen
) 
1236                         tracepos 
= printTraceLine(tracepos
, traceLen
, trace
, protocol
, showWaitCycles
, markCRCBytes
);