1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2015 Piwi 
   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 Topaz (NFC Type 1) commands 
   9 //----------------------------------------------------------------------------- 
  11 #include "cmdhftopaz.h" 
  18 #include "cmdparser.h" 
  23 #include "iso14443crc.h" 
  24 #include "protocols.h" 
  26 #define TOPAZ_STATIC_MEMORY     (0x0f * 8)              // 15 blocks with 8 Bytes each 
  28 // a struct to describe a memory area which contains lock bits and the corresponding lockable memory area 
  29 typedef struct dynamic_lock_area 
{ 
  30         struct dynamic_lock_area 
*next
; 
  31         uint16_t        byte_offset
;                    // the address of the lock bits 
  32         uint16_t        size_in_bits
; 
  33         uint16_t        first_locked_byte
;              // the address of the lockable area 
  34         uint16_t        bytes_locked_per_bit
; 
  35 } dynamic_lock_area_t
; 
  42         uint8_t data_blocks
[TOPAZ_STATIC_MEMORY
/8][8];  // this memory is always there 
  43         uint8_t *dynamic_memory
;                                                // this memory can be there 
  44         dynamic_lock_area_t 
*dynamic_lock_areas
;                // lock area descriptors 
  48 static void topaz_switch_on_field(void) 
  50         UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_CONNECT 
| ISO14A_NO_SELECT 
| ISO14A_NO_DISCONNECT 
| ISO14A_TOPAZMODE
, 0, 0}}; 
  55 static void topaz_switch_off_field(void) 
  57         UsbCommand c 
= {CMD_READER_ISO_14443a
, {0, 0, 0}}; 
  62 // send a raw topaz command, returns the length of the response (0 in case of error) 
  63 static int topaz_send_cmd_raw(uint8_t *cmd
, uint8_t len
, uint8_t *response
) 
  65         UsbCommand c 
= {CMD_READER_ISO_14443a
, {ISO14A_RAW 
| ISO14A_NO_DISCONNECT 
| ISO14A_TOPAZMODE
, len
, 0}}; 
  66         memcpy(c
.d
.asBytes
, cmd
, len
); 
  70         WaitForResponse(CMD_ACK
, &resp
); 
  72         if (resp
.arg
[0] > 0) { 
  73                 memcpy(response
, resp
.d
.asBytes
, resp
.arg
[0]); 
  80 // calculate CRC bytes and send topaz command, returns the length of the response (0 in case of error)  
  81 static int topaz_send_cmd(uint8_t *cmd
, uint8_t len
, uint8_t *response
) 
  84         uint8_t first
, second
; 
  85                 ComputeCrc14443(CRC_14443_B
, cmd
, len
-2, &first
, &second
); 
  90         return topaz_send_cmd_raw(cmd
, len
, response
); 
  94 // select a topaz tag. Send WUPA and RID. 
  95 static int topaz_select(uint8_t *atqa
, uint8_t *rid_response
) 
  97         // ToDo: implement anticollision 
  99         uint8_t wupa_cmd
[] = {TOPAZ_WUPA
}; 
 100         uint8_t rid_cmd
[] = {TOPAZ_RID
, 0, 0, 0, 0, 0, 0, 0, 0}; 
 102         topaz_switch_on_field(); 
 104         if (!topaz_send_cmd(wupa_cmd
, sizeof(wupa_cmd
), atqa
)) { 
 105                 topaz_switch_off_field(); 
 106                 return -1;              // WUPA failed 
 109         if (!topaz_send_cmd(rid_cmd
, sizeof(rid_cmd
), rid_response
)) { 
 110                 topaz_switch_off_field(); 
 111                 return -2;              // RID failed 
 118 // read all of the static memory of a selected Topaz tag. 
 119 static int topaz_rall(uint8_t *uid
, uint8_t *response
) 
 121         uint8_t rall_cmd
[] = {TOPAZ_RALL
, 0, 0, 0, 0, 0, 0, 0, 0}; 
 123         memcpy(&rall_cmd
[3], uid
, 4); 
 124         if (!topaz_send_cmd(rall_cmd
, sizeof(rall_cmd
), response
)) { 
 125                 topaz_switch_off_field(); 
 126                 return -1;              // RALL failed 
 133 // read a block (8 Bytes) of a selected Topaz tag. 
 134 static int topaz_read_block(uint8_t *uid
, uint8_t blockno
, uint8_t *block_data
) 
 136         uint8_t read8_cmd
[] = {TOPAZ_READ8
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
 137         uint8_t read8_response
[11]; 
 139         read8_cmd
[1] = blockno
; 
 140         memcpy(&read8_cmd
[10], uid
, 4); 
 141         if (!topaz_send_cmd(read8_cmd
, sizeof(read8_cmd
), read8_response
)) { 
 142                 topaz_switch_off_field(); 
 143                 return -1;              // READ8 failed 
 146         memcpy(block_data
, &read8_response
[1], 8); 
 152 // read a segment (16 blocks = 128 Bytes) of a selected Topaz tag. Works only for tags with dynamic memory. 
 153 static int topaz_read_segment(uint8_t *uid
, uint8_t segno
, uint8_t *segment_data
) 
 155         uint8_t rseg_cmd
[] = {TOPAZ_RSEG
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
 156         uint8_t rseg_response
[131]; 
 158         rseg_cmd
[1] = segno 
<< 4; 
 159         memcpy(&rseg_cmd
[10], uid
, 4); 
 160         if (!topaz_send_cmd(rseg_cmd
, sizeof(rseg_cmd
), rseg_response
)) { 
 161                 topaz_switch_off_field(); 
 162                 return -1;              // RSEG failed 
 165         memcpy(segment_data
, &rseg_response
[1], 128); 
 171 // search for the lock area descriptor for the lockable area including byteno  
 172 static dynamic_lock_area_t 
*get_dynamic_lock_area(uint16_t byteno
) 
 174         dynamic_lock_area_t 
*lock_area
; 
 176         lock_area 
= topaz_tag
.dynamic_lock_areas
; 
 178         while (lock_area 
!= NULL
) { 
 179                 if (byteno 
< lock_area
->first_locked_byte
) { 
 180                         lock_area 
= lock_area
->next
; 
 190 // check if a memory byte is locked. 
 191 static bool topaz_byte_is_locked(uint16_t byteno
) 
 194         uint16_t locked_bytes_per_bit
; 
 195         dynamic_lock_area_t 
*lock_area
; 
 197         if (byteno 
< TOPAZ_STATIC_MEMORY
) { 
 198                 lockbits 
= &topaz_tag
.data_blocks
[0x0e][0]; 
 199                 locked_bytes_per_bit 
= 8; 
 201                 lock_area 
= get_dynamic_lock_area(byteno
); 
 202                 if (lock_area 
== NULL
) { 
 205                         lockbits 
= &topaz_tag
.dynamic_memory
[lock_area
->byte_offset 
- TOPAZ_STATIC_MEMORY
]; 
 206                         locked_bytes_per_bit 
= lock_area
->bytes_locked_per_bit
; 
 207                         byteno 
= byteno 
- lock_area
->first_locked_byte
; 
 211         uint16_t blockno 
= byteno 
/ locked_bytes_per_bit
; 
 212         if(lockbits
[blockno
/8] & (0x01 << (blockno 
% 8))) { 
 220 // read and print the Capability Container 
 221 static int topaz_print_CC(uint8_t *data
) 
 223         if(data
[0] != 0xe1) { 
 224                 topaz_tag
.size 
= TOPAZ_STATIC_MEMORY
; 
 225                 return -1;              // no NDEF message 
 228         PrintAndLog("Capability Container: %02x %02x %02x %02x", data
[0], data
[1], data
[2], data
[3]); 
 229         PrintAndLog("  %02x: NDEF Magic Number", data
[0]);  
 230         PrintAndLog("  %02x: version %d.%d supported by tag", data
[1], (data
[1] & 0xF0) >> 4, data
[1] & 0x0f); 
 231         uint16_t memsize 
= (data
[2] + 1) * 8; 
 232         topaz_tag
.size 
= memsize
; 
 233         topaz_tag
.dynamic_memory 
= malloc(memsize 
- TOPAZ_STATIC_MEMORY
); 
 234         PrintAndLog("  %02x: Physical Memory Size of this tag: %d bytes", data
[2], memsize
); 
 235         PrintAndLog("  %02x: %s / %s", data
[3],  
 236                                 (data
[3] & 0xF0) ? "(RFU)" : "Read access granted without any security",  
 237                                 (data
[3] & 0x0F)==0 ? "Write access granted without any security" : (data
[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); 
 242 // return type, length and value of a TLV, starting at memory position *TLV_ptr  
 243 static void get_TLV(uint8_t **TLV_ptr
, uint8_t *TLV_type
, uint16_t *TLV_length
, uint8_t **TLV_value
) 
 248         *TLV_type 
= **TLV_ptr
; 
 251                 case 0x00:                      // NULL TLV. 
 252                 case 0xFE:                      // Terminator TLV. 
 254                 case 0x01:                      // Lock Control TLV 
 255                 case 0x02:                      // Reserved Memory TLV 
 256                 case 0x03:                      // NDEF message TLV 
 257                 case 0xFD:                      // proprietary TLV 
 258                         *TLV_length 
= **TLV_ptr
; 
 260                         if (*TLV_length 
== 0xff) { 
 261                                 *TLV_length 
= **TLV_ptr 
<< 8; 
 263                                 *TLV_length 
|= **TLV_ptr
; 
 266                         *TLV_value 
= *TLV_ptr
; 
 267                         *TLV_ptr 
+= *TLV_length
; 
 275 // lock area TLVs contain no information on the start of the respective lockable area. Lockable areas 
 276 // do not include the lock bits and reserved memory. We therefore need to adjust the start of the  
 277 // respective lockable areas accordingly 
 278 static void adjust_lock_areas(uint16_t block_start
, uint16_t block_size
) 
 280         dynamic_lock_area_t 
*lock_area 
= topaz_tag
.dynamic_lock_areas
; 
 281         while (lock_area 
!= NULL
) { 
 282                 if (lock_area
->first_locked_byte 
<= block_start
) { 
 283                         lock_area
->first_locked_byte 
+= block_size
; 
 285                 lock_area 
= lock_area
->next
; 
 290 // read and print the lock area and reserved memory TLVs 
 291 static void topaz_print_control_TLVs(uint8_t *memory
) 
 293         uint8_t *TLV_ptr 
= memory
; 
 294         uint8_t TLV_type 
= 0; 
 297         bool lock_TLV_present 
= false; 
 298         bool reserved_memory_control_TLV_present 
= false; 
 299         uint16_t next_lockable_byte 
= 0x0f * 8;                         // first byte after static memory area 
 301         while(*TLV_ptr 
!= 0x03 && *TLV_ptr 
!= 0xFD && *TLV_ptr 
!= 0xFE) {        
 302                 // all Lock Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV) 
 303                 get_TLV(&TLV_ptr
, &TLV_type
, &TLV_length
, &TLV_value
); 
 304                 if (TLV_type 
== 0x01) {                 // a Lock Control TLV 
 305                         uint8_t pages_addr 
= TLV_value
[0] >> 4; 
 306                         uint8_t byte_offset 
= TLV_value
[0] & 0x0f; 
 307                         uint16_t size_in_bits 
= TLV_value
[1] ? TLV_value
[1] : 256; 
 308                         uint16_t size_in_bytes 
= (size_in_bits 
+ 7)/8; 
 309                         uint16_t bytes_per_page 
= 1 << (TLV_value
[2] & 0x0f); 
 310                         uint16_t bytes_locked_per_bit 
= 1 << (TLV_value
[2] >> 4); 
 311                         uint16_t area_start 
= pages_addr 
* bytes_per_page 
+ byte_offset
; 
 312                         PrintAndLog("Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.",  
 315                                                 bytes_locked_per_bit
); 
 316                         lock_TLV_present 
= true; 
 317                         dynamic_lock_area_t 
*old 
= topaz_tag
.dynamic_lock_areas
; 
 318                         dynamic_lock_area_t 
*new = topaz_tag
.dynamic_lock_areas
; 
 320                                 new = topaz_tag
.dynamic_lock_areas 
= (dynamic_lock_area_t 
*)malloc(sizeof(dynamic_lock_area_t
)); 
 322                                 while(old
->next 
!= NULL
) { 
 325                                 new = old
->next 
= (dynamic_lock_area_t 
*)malloc(sizeof(dynamic_lock_area_t
)); 
 328                         if (area_start 
<= next_lockable_byte
) { 
 329                                 // lock areas are not lockable 
 330                                 next_lockable_byte 
+= size_in_bytes
; 
 332                         new->first_locked_byte 
= next_lockable_byte
; 
 333                         new->byte_offset 
= area_start
; 
 334                         new->size_in_bits 
= size_in_bits
; 
 335                         new->bytes_locked_per_bit 
= bytes_locked_per_bit
; 
 336                         next_lockable_byte 
+= size_in_bits 
* bytes_locked_per_bit
;               
 338                 if (TLV_type 
== 0x02) {                 // a Reserved Memory Control TLV 
 339                         uint8_t pages_addr 
= TLV_value
[0] >> 4; 
 340                         uint8_t byte_offset 
= TLV_value
[0] & 0x0f; 
 341                         uint16_t size_in_bytes 
= TLV_value
[1] ? TLV_value
[1] : 256; 
 342                         uint8_t bytes_per_page 
= 1 << (TLV_value
[2] & 0x0f); 
 343                         uint16_t area_start 
= pages_addr 
* bytes_per_page 
+ byte_offset
; 
 344                         PrintAndLog("Reserved Memory of %d bytes at byte offset 0x%02x.",  
 347                         reserved_memory_control_TLV_present 
= true; 
 348                         adjust_lock_areas(area_start
, size_in_bytes
);  // reserved memory areas are not lockable 
 349                         if (area_start 
<= next_lockable_byte
) { 
 350                                 next_lockable_byte 
+= size_in_bytes
; 
 355         if (!lock_TLV_present
) { 
 356                 PrintAndLog("(No Lock Control TLV present)"); 
 359         if (!reserved_memory_control_TLV_present
) { 
 360                 PrintAndLog("(No Reserved Memory Control TLV present)"); 
 365 // read all of the dynamic memory 
 366 static int topaz_read_dynamic_data(void) 
 368         // first read the remaining block of segment 0 
 369         if(topaz_read_block(topaz_tag
.uid
, 0x0f, &topaz_tag
.dynamic_memory
[0]) == -1) { 
 370                 PrintAndLog("Error while reading dynamic memory block %02x. Aborting...", 0x0f); 
 374         // read the remaining segments 
 375         uint8_t max_segment 
= topaz_tag
.size 
/ 128 - 1; 
 376         for(uint8_t segment 
= 1; segment 
<= max_segment
; segment
++) { 
 377                 if(topaz_read_segment(topaz_tag
.uid
, segment
, &topaz_tag
.dynamic_memory
[(segment
-1)*128+8]) == -1) { 
 378                         PrintAndLog("Error while reading dynamic memory block %02x. Aborting...", 0x0f); 
 387 // read and print the dynamic memory 
 388 static void topaz_print_dynamic_data(void) 
 390         if (topaz_tag
.size 
> TOPAZ_STATIC_MEMORY
) { 
 391                 PrintAndLog("Dynamic Data blocks:"); 
 392                 if (topaz_read_dynamic_data() == 0) { 
 393                         PrintAndLog("block# | offset | Data                    | Locked(y/n)"); 
 395                         for (uint16_t blockno 
= 0x0f; blockno 
< topaz_tag
.size
/8; blockno
++) { 
 396                                 uint8_t *block_data 
= &topaz_tag
.dynamic_memory
[(blockno
-0x0f)*8]; 
 398                                 for (uint16_t j 
= 0; j 
< 8; j
++) { 
 399                                         sprintf(&line
[3*j
], "%02x ", block_data
[j
]); 
 400                                         lockbits
[j
] = topaz_byte_is_locked(blockno
*8+j
) ? 'y' : 'n'; 
 403                                 PrintAndLog("  0x%02x | 0x%04x | %s|   %-3s", blockno
, blockno
*8, line
, lockbits
); 
 410 static void topaz_print_lifecycle_state(uint8_t *data
) 
 416 static void topaz_print_NDEF(uint8_t *data
) 
 422 // read a Topaz tag and print some usefull information   
 423 int CmdHFTopazReader(const char *Cmd
) 
 427         uint8_t rid_response
[8]; 
 428         uint8_t *uid_echo 
= &rid_response
[2]; 
 429         uint8_t rall_response
[124]; 
 431         status 
= topaz_select(atqa
, rid_response
); 
 434                 PrintAndLog("Error: couldn't receive ATQA"); 
 438         PrintAndLog("ATQA : %02x %02x", atqa
[1], atqa
[0]); 
 439         if (atqa
[1] != 0x0c && atqa
[0] != 0x00) { 
 440                 PrintAndLog("Tag doesn't support the Topaz protocol."); 
 441                 topaz_switch_off_field(); 
 446                 PrintAndLog("Error: tag didn't answer to RID"); 
 447                 topaz_switch_off_field(); 
 451         topaz_tag
.HR01
[0] = rid_response
[0]; 
 452         topaz_tag
.HR01
[1] = rid_response
[1]; 
 455         PrintAndLog("HR0  : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response
[0],  
 456                                                 (rid_response
[0] & 0xF0) == 0x10 ? "" : "not ", 
 457                                                 (rid_response
[0] & 0xF0) == 0x10 ? "" : "not ", 
 458                                                 (rid_response
[0] & 0x0F) == 0x01 ? "static" : "dynamic"); 
 459         PrintAndLog("HR1  : %02x", rid_response
[1]); 
 461         status 
= topaz_rall(uid_echo
, rall_response
); 
 464                 PrintAndLog("Error: tag didn't answer to RALL"); 
 465                 topaz_switch_off_field(); 
 469         memcpy(topaz_tag
.uid
, rall_response
+2, 7); 
 470         PrintAndLog("UID  : %02x %02x %02x %02x %02x %02x %02x",  
 478         PrintAndLog("       UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s",  
 480                         getTagInfo(topaz_tag
.uid
[6])); 
 482         memcpy(topaz_tag
.data_blocks
, rall_response
+2, 0x0f*8); 
 484         PrintAndLog("Static Data blocks 00 to 0c:"); 
 485         PrintAndLog("block# | offset | Data                    | Locked(y/n)"); 
 487         for (uint16_t i 
= 0; i 
<= 0x0c; i
++) { 
 489                 for (uint16_t j 
= 0; j 
< 8; j
++) { 
 490                         sprintf(&line
[3*j
], "%02x ", topaz_tag
.data_blocks
[i
][j
] /*rall_response[2 + 8*i + j]*/); 
 491                         lockbits
[j
] = topaz_byte_is_locked(i
*8+j
) ? 'y' : 'n'; 
 494                 PrintAndLog("  0x%02x | 0x%04x | %s|   %-3s", i
, i
*8, line
, lockbits
); 
 498         PrintAndLog("Static Reserved block 0d:"); 
 499         for (uint16_t j 
= 0; j 
< 8; j
++) { 
 500                 sprintf(&line
[3*j
], "%02x ", topaz_tag
.data_blocks
[0x0d][j
]); 
 502         PrintAndLog("  0x%02x | 0x%04x | %s|   %-3s", 0x0d, 0x0d*8, line
, "n/a"); 
 505         PrintAndLog("Static Lockbits and OTP Bytes:"); 
 506         for (uint16_t j 
= 0; j 
< 8; j
++) { 
 507                 sprintf(&line
[3*j
], "%02x ", topaz_tag
.data_blocks
[0x0e][j
]); 
 509         PrintAndLog("  0x%02x | 0x%04x | %s|   %-3s", 0x0e, 0x0e*8, line
, "n/a"); 
 513         status 
= topaz_print_CC(&topaz_tag
.data_blocks
[1][0]); 
 516                 PrintAndLog("No NDEF message data present"); 
 517                 topaz_switch_off_field(); 
 522         topaz_print_control_TLVs(&topaz_tag
.data_blocks
[1][4]); 
 525         topaz_print_dynamic_data(); 
 527         topaz_print_lifecycle_state(&topaz_tag
.data_blocks
[1][0]); 
 529         topaz_print_NDEF(&topaz_tag
.data_blocks
[1][0]); 
 531         topaz_switch_off_field(); 
 536 int CmdHFTopazCmdRaw(const char *Cmd
) 
 538         PrintAndLog("not yet implemented. Use hf 14 raw with option -T."); 
 543 static int CmdHelp(const char *Cmd
); 
 546 static command_t CommandTable
[] =  
 548         {"help",        CmdHelp
,                        1, "This help"}, 
 549         {"reader",      CmdHFTopazReader
,       0, "Act like a Topaz reader"}, 
 550         {"snoop",       CmdHF14ASnoop
,          0, "Eavesdrop a Topaz reader-tag communication"}, 
 551         {"raw",         CmdHFTopazCmdRaw
,       0, "Send raw hex data to tag"}, 
 552         {NULL
,          NULL
,                           0, NULL
} 
 556 int CmdHFTopaz(const char *Cmd
) { 
 557         (void)WaitForResponseTimeout(CMD_ACK
,NULL
,100); 
 558         CmdsParse(CommandTable
, Cmd
); 
 563 static int CmdHelp(const char *Cmd
) 
 565         CmdsHelp(CommandTable
);