1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com> 
   4 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   5 // at your option, any later version. See the LICENSE.txt file for the text of 
   7 //----------------------------------------------------------------------------- 
   8 // High frequency ISO14443B commands 
   9 //----------------------------------------------------------------------------- 
  15 #include "iso14443crc.h" 
  16 #include "proxmark3.h" 
  21 #include "cmdparser.h" 
  26 static int CmdHelp(const char *Cmd
); 
  28 int CmdHF14BList(const char *Cmd
) 
  30         PrintAndLog("Deprecated command, use 'hf list 14b' instead"); 
  35 int CmdHF14BSim(const char *Cmd
) 
  37         UsbCommand c 
= {CMD_SIMULATE_TAG_ISO_14443B
}; 
  43 int CmdHF14BSnoop(const char *Cmd
) 
  45         UsbCommand c 
= {CMD_SNOOP_ISO_14443B
}; 
  51 /* New command to read the contents of a SRI512 tag 
  52  * SRI512 tags are ISO14443-B modulated memory tags, 
  53  * this command just dumps the contents of the memory 
  55 int CmdSri512Read(const char *Cmd
) 
  57         UsbCommand c 
= {CMD_READ_SRI512_TAG
, {strtol(Cmd
, NULL
, 0), 0, 0}}; 
  63 /* New command to read the contents of a SRIX4K tag 
  64  * SRIX4K tags are ISO14443-B modulated memory tags, 
  65  * this command just dumps the contents of the memory/ 
  67 int CmdSrix4kRead(const char *Cmd
) 
  69         UsbCommand c 
= {CMD_READ_SRIX4K_TAG
, {strtol(Cmd
, NULL
, 0), 0, 0}}; 
  78         UsbCommand c 
= {CMD_ISO_14443B_COMMAND
, {0, 0, 0}}; 
  81         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,1000)) { 
  87 int HF14BCmdRaw(bool reply
, bool *crc
, bool power
, uint8_t *data
, uint8_t *datalen
, bool verbose
){ 
  90                 ComputeCrc14443(CRC_14443_B
, data
, *datalen
, data
+*datalen
, data
+*datalen
+1); 
  94         UsbCommand c 
= {CMD_ISO_14443B_COMMAND
, {0, 0, 0}}; // len,recv,power 
  98         memcpy(c
.d
.asBytes
, data
, *datalen
); 
 102         if (!reply
) return 1;  
 105         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) { 
 106                 if (verbose
) PrintAndLog("timeout while waiting for reply."); 
 110         *datalen 
= resp
.arg
[0]; 
 111         if (verbose
) PrintAndLog("received %u octets", *datalen
); 
 112         if(*datalen
<3) return 0; 
 114         memcpy(data
, resp
.d
.asBytes
, *datalen
); 
 116         uint8_t first 
= 0, second 
= 0; 
 117         ComputeCrc14443(CRC_14443_B
, data
, *datalen
-2, &first
, &second
); 
 118         *crc 
= ( data
[*datalen
-2] == first 
&& data
[*datalen
-1] == second
); 
 121                 PrintAndLog("[LEN %u] %s[%02X %02X] %s", 
 123                                 sprint_hex(data
, *datalen
-2), 
 132 int CmdHF14BCmdRaw (const char *Cmd
) { 
 139     uint8_t data
[USB_CMD_DATA_SIZE
] = {0x00}; 
 144                 PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); 
 145         PrintAndLog("       -r    do not read response"); 
 146         PrintAndLog("       -c    calculate and append CRC"); 
 147         PrintAndLog("       -p    leave the field on after receive"); 
 148                 PrintAndLog("       -s    active signal field ON with select"); 
 149                 PrintAndLog("       -ss   active signal field ON with select for SRx ST Microelectronics tags"); 
 154     while (*Cmd
==' ' || *Cmd
=='\t') Cmd
++; 
 156     while (Cmd
[i
]!='\0') { 
 157         if (Cmd
[i
]==' ' || Cmd
[i
]=='\t') { i
++; continue; } 
 175                                         if (Cmd
[i
+2]=='s' || Cmd
[i
+2]=='S') { 
 181                     PrintAndLog("Invalid option"); 
 187         if ((Cmd
[i
]>='0' && Cmd
[i
]<='9') || 
 188             (Cmd
[i
]>='a' && Cmd
[i
]<='f') || 
 189             (Cmd
[i
]>='A' && Cmd
[i
]<='F') ) { 
 190             buf
[strlen(buf
)+1]=0; 
 191             buf
[strlen(buf
)]=Cmd
[i
]; 
 194             if (strlen(buf
)>=2) { 
 195                 sscanf(buf
,"%x",&temp
); 
 196                 data
[datalen
++]=(uint8_t)(temp 
& 0xff); 
 198                                 memset(buf
, 0x00, sizeof(buf
)); 
 202         PrintAndLog("Invalid char on input"); 
 207       PrintAndLog("Missing data input"); 
 211         if (select
){ //auto select 14b tag 
 230                 if (HF14BCmdRaw(true, &crc2
, true, cmd2
, &cmdLen
, false)==0) return rawClose(); 
 232                 PrintAndLog("REQB   : %s", sprint_hex(cmd2
, cmdLen
)); 
 234                 if ( SRx 
&& (cmdLen 
!= 3 || !crc2
) ) return rawClose(); 
 235                 else if (cmd2
[0] != 0x50 || cmdLen 
!= 14 || !crc2
) return rawClose(); 
 247                         // UID from cmd2[1 - 4] 
 257                 if (HF14BCmdRaw(true, &crc2
, true, cmd2
, &cmdLen
, false)==0) return rawClose(); 
 258                 PrintAndLog("ATTRIB : %s", sprint_hex(cmd2
, cmdLen
)); 
 260                 if (cmdLen 
!= 3 || !crc2
) return rawClose();             
 261                 if (SRx 
&& cmd2
[0] != chipID
) return rawClose(); 
 264         return HF14BCmdRaw(reply
, &crc
, power
, data
, &datalen
, true); 
 267 // print full atqb info 
 268 static void print_atqb_resp(uint8_t *data
){ 
 269         //PrintAndLog ("           UID: %s", sprint_hex(data+1,4)); 
 270         PrintAndLog ("      App Data: %s", sprint_hex(data
+5,4)); 
 271         PrintAndLog ("      Protocol: %s", sprint_hex(data
+9,3)); 
 272         uint8_t BitRate 
= data
[9]; 
 273         if (!BitRate
) PrintAndLog ("      Bit Rate: 106 kbit/s only PICC <-> PCD"); 
 274         if (BitRate 
& 0x10)     PrintAndLog ("      Bit Rate: 212 kbit/s PICC -> PCD supported"); 
 275         if (BitRate 
& 0x20)     PrintAndLog ("      Bit Rate: 424 kbit/s PICC -> PCD supported");  
 276         if (BitRate 
& 0x40)     PrintAndLog ("      Bit Rate: 847 kbit/s PICC -> PCD supported");  
 277         if (BitRate 
& 0x01)     PrintAndLog ("      Bit Rate: 212 kbit/s PICC <- PCD supported"); 
 278         if (BitRate 
& 0x02)     PrintAndLog ("      Bit Rate: 424 kbit/s PICC <- PCD supported");  
 279         if (BitRate 
& 0x04)     PrintAndLog ("      Bit Rate: 847 kbit/s PICC <- PCD supported");  
 280         if (BitRate 
& 0x80)     PrintAndLog ("                Same bit rate <-> required"); 
 282         uint16_t maxFrame 
= data
[10]>>4; 
 283         if (maxFrame 
< 5)               maxFrame 
= 8 * maxFrame 
+ 16; 
 284         else if (maxFrame 
== 5) maxFrame 
= 64; 
 285         else if (maxFrame 
== 6) maxFrame 
= 96; 
 286         else if (maxFrame 
== 7) maxFrame 
= 128; 
 287         else if (maxFrame 
== 8) maxFrame 
= 256; 
 290         PrintAndLog ("Max Frame Size: %u%s",maxFrame
, (maxFrame 
== 257) ? "+ RFU" : ""); 
 292         uint8_t protocolT 
= data
[10] & 0xF; 
 293         PrintAndLog (" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT
) ? "" : "not " ); 
 294         PrintAndLog ("Frame Wait Int: %u", data
[11]>>4); 
 295         PrintAndLog (" App Data Code: Application is %s",(data
[11]&4) ? "Standard" : "Proprietary"); 
 296         PrintAndLog (" Frame Options: NAD is %ssupported",(data
[11]&2) ? "" : "not "); 
 297         PrintAndLog (" Frame Options: CID is %ssupported",(data
[11]&1) ? "" : "not "); 
 298         PrintAndLog ("Max Buf Length: %u (MBLI) %s",data
[14]>>4, (data
[14] & 0xF0) ? "" : "not supported"); 
 303 // get SRx chip model (from UID) // from ST Microelectronics 
 304 char *get_ST_Chip_Model(uint8_t data
){ 
 305         static char model
[20]; 
 306         char *retStr 
= model
; 
 307         memset(model
,0, sizeof(model
)); 
 310                 case 0x0: sprintf(retStr
, "SRIX4K (Special)"); break; 
 311                 case 0x2: sprintf(retStr
, "SR176"); break; 
 312                 case 0x3: sprintf(retStr
, "SRIX4K"); break; 
 313                 case 0x4: sprintf(retStr
, "SRIX512"); break; 
 314                 case 0x6: sprintf(retStr
, "SRI512"); break; 
 315                 case 0x7: sprintf(retStr
, "SRI4K"); break; 
 316                 case 0xC: sprintf(retStr
, "SRT512"); break; 
 317                 default : sprintf(retStr
, "Unknown"); break; 
 322 int print_ST_Lock_info(uint8_t model
){ 
 323         //assume connection open and tag selected... 
 324         uint8_t data
[16] = {0x00}; 
 331         if (model 
== 0x2) { //SR176 has special command: 
 340         if (HF14BCmdRaw(true, &crc
, true, data
, &datalen
, false)==0) return rawClose(); 
 342         if (datalen 
!= resplen 
|| !crc
) return rawClose(); 
 344         PrintAndLog("Chip Write Protection Bits:"); 
 345         // now interpret the data 
 347                 case 0x0: //fall through (SRIX4K special) 
 348                 case 0x3: //fall through (SRIx4K) 
 352                         PrintAndLog("   raw: %s",printBits(1,data
+3)); 
 353                         PrintAndLog(" 07/08:%slocked", (data
[3] & 1) ? " not " : " " ); 
 354                         for (uint8_t i 
= 1; i
<8; i
++){ 
 355                                 PrintAndLog("    %02u:%slocked", blk1
, (data
[3] & (1 << i
)) ? " not " : " " ); 
 359                 case 0x4: //fall through (SRIX512) 
 360                 case 0x6: //fall through (SRI512) 
 361                 case 0xC: //             (SRT512) 
 362                         //need data[2] and data[3] 
 364                         PrintAndLog("   raw: %s",printBits(2,data
+2)); 
 365                         for (uint8_t b
=2; b
<4; b
++){ 
 366                                 for (uint8_t i
=0; i
<8; i
++){ 
 367                                         PrintAndLog("    %02u:%slocked", blk1
, (data
[b
] & (1 << i
)) ? " not " : " " ); 
 375                         PrintAndLog("   raw: %s",printBits(1,data
+2)); 
 376                         for (uint8_t i 
= 0; i
<8; i
++){ 
 377                                 PrintAndLog(" %02u/%02u:%slocked", blk1
, blk1
+1, (data
[2] & (1 << i
)) ? " " : " not " ); 
 387 // print UID info from SRx chips (ST Microelectronics) 
 388 static void print_st_general_info(uint8_t *data
){ 
 389         //uid = first 8 bytes in data 
 390         PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data
,8,8),8)); 
 391         PrintAndLog(" MFG: %02X, %s", data
[6], getTagInfo(data
[6])); 
 392         PrintAndLog("Chip: %02X, %s", data
[5]>>2, get_ST_Chip_Model(data
[5]>>2)); 
 396 // 14b get and print UID only (general info) 
 397 int HF14BStdReader(uint8_t *data
, uint8_t *datalen
){ 
 398         //05 00 00 = find one tag in field 
 399         //1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0]) 
 400         //a3 = ?  (resp 03 [e2 c2]) 
 401         //02 = ?  (resp 02 [6a d3]) 
 402         // 022b (resp 02 67 00 [29  5b]) 
 403         // 0200a40400 (resp 02 67 00 [29 5b]) 
 404         // 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b]) 
 405         // 0200a4040c07a0000002480200 (resp 02 67 00 [29 5b]) 
 406         // 0200a4040006a0000000010100 (resp 02 6a 82 [4b 4c]) 
 407         // 0200a4040c09d27600002545500200 (resp 02 67 00 [29 5b]) 
 408         // 0200a404000cd2760001354b414e4d30310000 (resp 02 6a 82 [4b 4c]) 
 409         // 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c]) 
 410         // 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c]) 
 411         //03 = ?  (resp 03 [e3 c2]) 
 412         //c2 = ?  (resp c2 [66 15]) 
 413         //b2 = ?  (resp a3 [e9 67])              
 414         //a2 = ?  (resp 02 [6a d3]) 
 422         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)==0) return rawClose(); 
 424         if (data
[0] != 0x50 || *datalen 
!= 14 || !crc
) return rawClose(); 
 426         PrintAndLog ("\n14443-3b tag found:"); 
 427         PrintAndLog ("           UID: %s", sprint_hex(data
+1,4)); 
 434         // UID from data[1 - 4] 
 446         if (HF14BCmdRaw(true, &crc2
, true, cmd2
, &cmdLen
, false)==0) return rawClose(); 
 448         if (cmdLen 
!= 3 || !crc2
) return rawClose(); 
 449         // add attrib responce to data 
 455 // 14b get and print Full Info (as much as we know) 
 456 int HF14BStdInfo(uint8_t *data
, uint8_t *datalen
){ 
 457         if (!HF14BStdReader(data
,datalen
)) return 0; 
 460         print_atqb_resp(data
); 
 464 // SRx get and print general info about SRx chip from UID 
 465 int HF14B_ST_Reader(uint8_t *data
, uint8_t *datalen
, bool closeCon
){ 
 473         // verbose on for now for testing - turn off when functional 
 474         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)==0) return rawClose(); 
 476         if (*datalen 
!= 3 || !crc
) return rawClose(); 
 478         uint8_t chipID 
= data
[0]; 
 485         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)==0) return rawClose(); 
 487         if (*datalen 
!= 3 || !crc 
|| data
[0] != chipID
) return rawClose(); 
 494         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)==0) return rawClose(); 
 496         if (*datalen 
!= 10 || !crc
) return rawClose(); 
 499         if (closeCon
) rawClose(); 
 501         PrintAndLog("\n14443-3b ST tag found:"); 
 502         print_st_general_info(data
); 
 506 // SRx get and print full info (needs more info...) 
 507 int HF14B_ST_Info(uint8_t *data
, uint8_t *datalen
){ 
 508         if (!HF14B_ST_Reader(data
, datalen
, false)) return 0; 
 510         //add locking bit information here. 
 511         if (print_ST_Lock_info(data
[5]>>2))  
 517 // test for other 14b type tags (mimic another reader - don't have tags to identify) 
 518 int HF14B_Other_Reader(uint8_t *data
, uint8_t *datalen
){ 
 527         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)!=0) { 
 528                 if (*datalen 
> 2 || !crc
) { 
 529                         PrintAndLog ("\n14443-3b tag found:"); 
 530                         PrintAndLog ("Unknown tag type answered to a 0x000b3f80 command ans:"); 
 531                         PrintAndLog ("%s",sprint_hex(data
,*datalen
)); 
 541         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)!=0) { 
 543                         PrintAndLog ("\n14443-3b tag found:"); 
 544                         PrintAndLog ("Unknown tag type answered to a 0x0A command ans:"); 
 545                         PrintAndLog ("%s",sprint_hex(data
,*datalen
)); 
 555         if (HF14BCmdRaw(true, &crc
, true, data
, datalen
, false)!=0) { 
 557                         PrintAndLog ("\n14443-3b tag found:"); 
 558                         PrintAndLog ("Unknown tag type answered to a 0x0C command ans:"); 
 559                         PrintAndLog ("%s",sprint_hex(data
,*datalen
)); 
 568 // get and print all info known about any known 14b tag 
 569 int HF14BInfo(bool verbose
){ 
 570         uint8_t data
[USB_CMD_DATA_SIZE
]; 
 573         // try std 14b (atqb) 
 574         if (HF14BStdInfo(data
, &datalen
)) return 1; 
 577         if (HF14B_ST_Info(data
, &datalen
)) return 1; 
 579         // try unknown 14b read commands (to be identified later) 
 580         //   could be read of calypso, CEPAS, moneo, or pico pass. 
 581         if (HF14B_Other_Reader(data
, &datalen
)) return 1; 
 583         if (verbose
) PrintAndLog("no 14443B tag found"); 
 587 // menu command to get and print all info known about any known 14b tag 
 588 int CmdHF14Binfo(const char *Cmd
){ 
 589         return HF14BInfo(true); 
 592 // get and print general info about all known 14b chips 
 593 int HF14BReader(bool verbose
){ 
 594         uint8_t data
[USB_CMD_DATA_SIZE
]; 
 597         // try std 14b (atqb) 
 598         if (HF14BStdReader(data
, &datalen
)) return 1; 
 601         if (HF14B_ST_Reader(data
, &datalen
, true)) return 1; 
 603         // try unknown 14b read commands (to be identified later) 
 604         //   could be read of calypso, CEPAS, moneo, or pico pass. 
 605         if (HF14B_Other_Reader(data
, &datalen
)) return 1; 
 607         if (verbose
) PrintAndLog("no 14443B tag found"); 
 611 // menu command to get and print general info about all known 14b chips 
 612 int CmdHF14BReader(const char *Cmd
){ 
 613         return HF14BReader(true); 
 616 int CmdSriWrite( const char *Cmd
){ 
 618  * For SRIX4K  blocks 00 - 7F 
 619  * hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata 
 621  * For SR512  blocks 00 - 0F 
 622  * hf 14b raw -c -p 09 $sr512wblock $sr512wdata 
 624  * Special block FF =  otp_lock_reg block. 
 627         char cmdp 
= param_getchar(Cmd
, 0); 
 628         uint8_t blockno 
= -1; 
 629         uint8_t data
[4] = {0x00}; 
 630         bool isSrix4k 
= true; 
 633         if (strlen(Cmd
) < 1 || cmdp 
== 'h' || cmdp 
== 'H') { 
 634                 PrintAndLog("Usage:  hf 14b write <1|2> <BLOCK> <DATA>"); 
 635                 PrintAndLog("    [1 = SRIX4K]"); 
 636                 PrintAndLog("    [2 = SRI512]"); 
 637                 PrintAndLog("    [BLOCK number depends on tag, special block == FF]"); 
 638                 PrintAndLog("     sample: hf 14b write 1 7F 11223344"); 
 639                 PrintAndLog("           : hf 14b write 1 FF 11223344"); 
 640                 PrintAndLog("           : hf 14b write 2 15 11223344"); 
 641                 PrintAndLog("           : hf 14b write 2 FF 11223344"); 
 648         //blockno = param_get8(Cmd, 1); 
 650         if ( param_gethex(Cmd
,1, &blockno
, 2) ) { 
 651                 PrintAndLog("Block number must include 2 HEX symbols"); 
 656                 if ( blockno 
> 0x7f && blockno 
!= 0xff ){ 
 657                         PrintAndLog("Block number out of range"); 
 661                 if ( blockno 
> 0x0f && blockno 
!= 0xff ){ 
 662                         PrintAndLog("Block number out of range"); 
 667         if (param_gethex(Cmd
, 2, data
, 8)) { 
 668                 PrintAndLog("Data must include 8 HEX symbols"); 
 672         if ( blockno 
== 0xff) 
 673                 PrintAndLog("[%s] Write special block %02X [ %s ]", (isSrix4k
)?"SRIX4K":"SRI512" , blockno
,  sprint_hex(data
,4) ); 
 675                 PrintAndLog("[%s] Write block %02X [ %s ]", (isSrix4k
)?"SRIX4K":"SRI512", blockno
,  sprint_hex(data
,4) ); 
 677         sprintf(str
, "-c 09 %02x %02x%02x%02x%02x", blockno
, data
[0], data
[1], data
[2], data
[3]); 
 683 int srix4kChecksum(uint32_t value
) { 
 688 4 bytes                 : 00 1A 20 01 
 691 #define NibbleHigh(b) ( (b & 0xF0) >> 4 ) 
 692 #define NibbleLow(b)  ( b & 0x0F ) 
 693 #define Crumb(b,p)    (((b & (0x3 << p) ) >> p ) & 0xF)  
 695         // only the lower crumbs. 
 696         uint8_t block 
= (value 
& 0xFF); 
 698         uint8_t valuebytes
[] = {0,0,0}; 
 700         // if ( strlen(Cmd) > 0){ 
 701                 // value = param_get32ex(Cmd, 0, 0, 16); 
 703                 // block = value & 0xFF; 
 705                 // value &= 0xFFFFFF00; 
 709         num_to_bytes(value
, 3, valuebytes
); 
 712         // Crumb swapping of value. 
 713         uint8_t temp
[] = {0,0}; 
 714         temp
[0] = (Crumb(value
, 22) << 4 | Crumb(value
, 14 ) << 2 | Crumb(value
, 6)) << 4; 
 715         temp
[0] |= Crumb(value
, 20) << 4 | Crumb(value
, 12 ) << 2 | Crumb(value
, 4); 
 716         temp
[1] = (Crumb(value
, 18) << 4 | Crumb(value
, 10 ) << 2 | Crumb(value
, 2)) << 4; 
 717         temp
[1] |= Crumb(value
, 16) << 4 | Crumb(value
, 8  ) << 2 | Crumb(value
, 0); 
 720         uint32_t chksum 
= 0xFF - block
; 
 722         // chksum is reduced by each nibbles of value. 
 723         for (i 
= 0; i 
< 3; ++i
){ 
 724                 chksum 
-= NibbleHigh(valuebytes
[i
]); 
 725                 chksum 
-= NibbleLow(valuebytes
[i
]); 
 729         // and left shift twice 
 731         uint8_t base4
[] = {0,0,0,0};     
 733         base4
[i
--] = (chksum 
% 4 << 2); 
 737         // merge scambled and chksum parts 
 739                 ( NibbleLow ( base4
[0]) << 28 ) | 
 740                 ( NibbleHigh( temp
[0])  << 24 ) | 
 742                 ( NibbleLow ( base4
[1]) << 20 ) | 
 743                 ( NibbleLow ( temp
[0])  << 16 ) | 
 745                 ( NibbleLow ( base4
[2]) << 12 ) | 
 746                 ( NibbleHigh( temp
[1])  << 8 ) | 
 748                 ( NibbleLow ( base4
[3]) << 4 ) | 
 749                   NibbleLow ( temp
[1] ); 
 751         PrintAndLog("ICE | %08X", encvalue
); 
 754 int srix4kMagicbytes(){ 
 761 static command_t CommandTable
[] =  
 763         {"help",        CmdHelp
,        1, "This help"}, 
 764         {"info",        CmdHF14Binfo
,   0, "Find and print details about a 14443B tag"}, 
 765         {"list",        CmdHF14BList
,   0, "[Deprecated] List ISO 14443B history"}, 
 766         {"reader",      CmdHF14BReader
, 0, "Act as a 14443B reader to identify a tag"}, 
 767         {"sim",         CmdHF14BSim
,    0, "Fake ISO 14443B tag"}, 
 768         {"snoop",       CmdHF14BSnoop
,  0, "Eavesdrop ISO 14443B"}, 
 769         {"sri512read",  CmdSri512Read
,  0, "Read contents of a SRI512 tag"}, 
 770         {"srix4kread",  CmdSrix4kRead
,  0, "Read contents of a SRIX4K tag"}, 
 771         {"sriwrite",    CmdSriWrite
,    0, "Write data to a SRI512 | SRIX4K tag"}, 
 772         {"raw",         CmdHF14BCmdRaw
, 0, "Send raw hex data to tag"}, 
 773         //{"calcSrix4",   srix4kchksum, 1, "a srix4k checksum test"}, 
 774         {NULL
, NULL
, 0, NULL
} 
 777 int CmdHF14B(const char *Cmd
) 
 779         CmdsParse(CommandTable
, Cmd
); 
 783 int CmdHelp(const char *Cmd
) 
 785         CmdsHelp(CommandTable
);