1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // Modified 2018, 2020 iceman
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 ISO14443B commands
10 //-----------------------------------------------------------------------------
15 #include "fileutils.h"
16 #include "cmdparser.h" // command_t
17 #include "commonutil.h" // ARRAYLEN
18 #include "comms.h" // clearCommandBuffer
19 #include "emv/emvcore.h" // TLVPrintFromBuffer
21 #include "cliparser.h"
24 #include "protocols.h" // definitions of ISO14B/7816 protocol
25 #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
26 #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
27 #include "aidsearch.h"
29 #define MAX_14B_TIMEOUT_MS (4949U)
31 // client side time out, waiting for device to ask tag.
34 // client side time out, waiting for device to ask tag a APDU to answer
35 #define APDU_TIMEOUT 2000
37 // iso14b apdu input frame length
38 static uint16_t apdu_frame_length
= 0;
39 uint16_t ats_fsc
[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
40 bool apdu_in_framing_enable
= true;
42 static int CmdHelp(const char *Cmd
);
44 static int switch_off_field_14b(void) {
45 SetISODEPState(ISODEP_INACTIVE
);
46 iso14b_raw_cmd_t packet
= {
47 .flags
= ISO14B_DISCONNECT
,
52 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
56 static uint16_t get_sw(uint8_t *d
, uint8_t n
) {
61 return d
[n
] * 0x0100 + d
[n
+ 1];
64 static void hf14b_aid_search(bool verbose
) {
66 json_t
*root
= AIDSearchInit(verbose
);
68 switch_off_field_14b();
72 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("AID Search") " --------------------");
75 bool leave_signal_on
= true;
76 bool activate_field
= true;
77 for (size_t elmindx
= 0; elmindx
< json_array_size(root
); elmindx
++) {
79 if (kbd_enter_pressed()) {
83 json_t
*data
= AIDSearchGetElm(root
, elmindx
);
84 uint8_t vaid
[200] = {0};
86 if (!AIDGetFromElm(data
, vaid
, sizeof(vaid
), &vaidlen
) || !vaidlen
)
91 uint8_t apdu_data
[PM3_CMD_DATA_SIZE
] = {0};
93 sAPDU apdu
= (sAPDU
) {0x00, 0xa4, 0x04, 0x00, vaidlen
, vaid
};
95 if (APDUEncodeS(&apdu
, false, 0x00, apdu_data
, &apdu_len
)) {
96 PrintAndLogEx(ERR
, "APDU encoding error.");
100 PrintAndLogEx(DEBUG
, ">>>> %s", sprint_hex(apdu_data
, apdu_len
));
103 uint8_t result
[1024] = {0};
104 int res
= exchange_14b_apdu(apdu_data
, apdu_len
, activate_field
, leave_signal_on
, result
, sizeof(result
), &resultlen
, -1);
105 activate_field
= false;
109 uint16_t sw
= get_sw(result
, resultlen
);
111 uint8_t dfname
[200] = {0};
112 size_t dfnamelen
= 0;
114 struct tlvdb
*tlv
= tlvdb_parse_multi(result
, resultlen
);
116 // 0x84 Dedicated File (DF) Name
117 const struct tlv
*dfnametlv
= tlvdb_get_tlv(tlvdb_find_full(tlv
, 0x84));
119 dfnamelen
= dfnametlv
->len
;
120 memcpy(dfname
, dfnametlv
->value
, dfnamelen
);
126 if (sw
== 0x9000 || sw
== 0x6283 || sw
== 0x6285) {
128 if (verbose
) PrintAndLogEx(SUCCESS
, "Application ( " _GREEN_("ok") " )");
130 if (verbose
) PrintAndLogEx(WARNING
, "Application ( " _RED_("blocked") " )");
133 PrintAIDDescriptionBuf(root
, vaid
, vaidlen
, verbose
);
136 if (dfnamelen
== vaidlen
) {
137 if (memcmp(dfname
, vaid
, vaidlen
) == 0) {
138 if (verbose
) PrintAndLogEx(INFO
, "(DF) Name found and equal to AID");
140 PrintAndLogEx(INFO
, "(DF) Name not equal to AID: %s :", sprint_hex(dfname
, dfnamelen
));
141 PrintAIDDescriptionBuf(root
, dfname
, dfnamelen
, verbose
);
144 PrintAndLogEx(INFO
, "(DF) Name not equal to AID: %s :", sprint_hex(dfname
, dfnamelen
));
145 PrintAIDDescriptionBuf(root
, dfname
, dfnamelen
, verbose
);
148 if (verbose
) PrintAndLogEx(INFO
, "(DF) Name not found");
151 if (verbose
) PrintAndLogEx(SUCCESS
, "----------------------------------------------------");
155 switch_off_field_14b();
156 if (verbose
== false && found
)
157 PrintAndLogEx(INFO
, "----------------------------------------------------");
160 static bool wait_cmd_14b(bool verbose
, bool is_select
, uint32_t timeout
) {
162 PacketResponseNG resp
;
163 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, MAX(TIMEOUT
, timeout
)) == false) {
164 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
168 uint16_t len
= (resp
.oldarg
[1] & 0xFFFF);
169 uint8_t *data
= resp
.data
.asBytes
;
171 // handle select responses
174 // 0: OK; -1: attrib fail; -2:crc fail
175 int status
= (int)resp
.oldarg
[0];
179 PrintAndLogEx(SUCCESS
, "received " _YELLOW_("%u") " bytes", len
);
180 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(data
, len
));
188 // handle raw bytes responses
191 bool crc
= check_crc(CRC_14443_B
, data
, len
);
193 PrintAndLogEx(SUCCESS
, "received " _YELLOW_("%u") " bytes", len
);
194 PrintAndLogEx(SUCCESS
, "%s[%02X %02X] %s",
195 sprint_hex(data
, len
- 2),
198 (crc
) ? _GREEN_("ok") : _RED_("fail")
200 } else if (len
== 0) {
201 PrintAndLogEx(INFO
, "no response from tag");
203 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(data
, len
));
209 static int CmdHF14BList(const char *Cmd
) {
210 return CmdTraceListAlias(Cmd
, "hf 14b", "14b");
213 static int CmdHF14BSim(const char *Cmd
) {
215 CLIParserContext
*ctx
;
216 CLIParserInit(&ctx
, "hf 14b sim",
217 "Simulate a ISO/IEC 14443 type B tag with 4 byte UID / PUPI",
218 "hf 14b sim -u 11AA33BB"
223 arg_strx0("u", "uid", "hex", "4byte UID/PUPI"),
226 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
230 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 1), pupi
, sizeof(pupi
), &n
);
234 PrintAndLogEx(FAILED
, "failed to read pupi");
238 PrintAndLogEx(INFO
, "Simulate with PUPI : " _GREEN_("%s"), sprint_hex_inrow(pupi
, sizeof(pupi
)));
239 PrintAndLogEx(INFO
, "Press pm3-button to abort simulation");
240 clearCommandBuffer();
241 SendCommandNG(CMD_HF_ISO14443B_SIMULATE
, pupi
, sizeof(pupi
));
245 static int CmdHF14BSniff(const char *Cmd
) {
247 CLIParserContext
*ctx
;
248 CLIParserInit(&ctx
, "hf 14b sniff",
249 "Sniff the communication reader and tag",
257 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
260 PacketResponseNG resp
;
261 clearCommandBuffer();
262 SendCommandNG(CMD_HF_ISO14443B_SNIFF
, NULL
, 0);
264 WaitForResponse(CMD_HF_ISO14443B_SNIFF
, &resp
);
266 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf 14b list") "` to view captured tracelog");
267 PrintAndLogEx(HINT
, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
271 static int CmdHF14BCmdRaw(const char *Cmd
) {
272 CLIParserContext
*ctx
;
273 CLIParserInit(&ctx
, "hf 14b raw",
274 "Sends raw bytes to card",
275 "hf 14b raw -cks --data 0200a40400 -> standard select, apdu 0200a4000 (7816)\n"
276 "hf 14b raw -ck --sr --data 0200a40400 -> SRx select\n"
277 "hf 14b raw -ck --cts --data 0200a40400 -> C-ticket select\n"
282 arg_lit0("k", "keep", "leave the signal field ON after receive response"),
283 arg_lit0("s", "std", "activate field, use ISO14B select"),
284 arg_lit0(NULL
, "sr", "activate field, use SRx ST select"),
285 arg_lit0(NULL
, "cts", "activate field, use ASK C-ticket select"),
286 arg_lit0("c", "crc", "calculate and append CRC"),
287 arg_lit0("r", NULL
, "do not read response from card"),
288 arg_int0("t", "timeout", "<dec>", "timeout in ms"),
289 arg_lit0("v", "verbose", "verbose"),
290 arg_strx0("d", "data", "<hex>", "data, bytes to send"),
293 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
295 bool keep_field_on
= arg_get_lit(ctx
, 1);
296 bool select_std
= arg_get_lit(ctx
, 2);
297 bool select_sr
= arg_get_lit(ctx
, 3);
298 bool select_cts
= arg_get_lit(ctx
, 4);
299 bool add_crc
= arg_get_lit(ctx
, 5);
300 bool read_reply
= (arg_get_lit(ctx
, 6) == false);
301 int user_timeout
= arg_get_int_def(ctx
, 7, -1);
302 bool verbose
= arg_get_lit(ctx
, 8);
304 uint32_t flags
= ISO14B_CONNECT
;
306 flags
|= ISO14B_APPEND_CRC
;
310 flags
|= (ISO14B_SELECT_STD
| ISO14B_CLEARTRACE
);
312 PrintAndLogEx(INFO
, "using ISO14443-B select");
313 } else if (select_sr
) {
314 flags
|= (ISO14B_SELECT_SR
| ISO14B_CLEARTRACE
);
316 PrintAndLogEx(INFO
, "using ST/SRx select");
317 } else if (select_cts
) {
318 flags
|= (ISO14B_SELECT_CTS
| ISO14B_CLEARTRACE
);
320 PrintAndLogEx(INFO
, "using ASK/C-ticket select");
323 uint8_t data
[PM3_CMD_DATA_SIZE
] = {0x00};
325 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 9), data
, sizeof(data
), &datalen
);
326 if (res
&& verbose
) {
327 PrintAndLogEx(INFO
, "called with no raw bytes");
332 uint32_t time_wait
= 0;
333 if (user_timeout
> 0) {
335 flags
|= ISO14B_SET_TIMEOUT
;
337 if (user_timeout
> MAX_14B_TIMEOUT_MS
) {
338 user_timeout
= MAX_14B_TIMEOUT_MS
;
339 PrintAndLogEx(INFO
, "set timeout to 4.9 seconds. The max we can wait for response");
342 // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
343 time_wait
= (uint32_t)((13560 / 128) * user_timeout
);
345 PrintAndLogEx(INFO
, " new raw timeout : %u ETU ( %u ms )", time_wait
, user_timeout
);
348 if (keep_field_on
== 0)
349 flags
|= ISO14B_DISCONNECT
;
354 // Max buffer is PM3_CMD_DATA_SIZE
355 datalen
= (datalen
> PM3_CMD_DATA_SIZE
) ? PM3_CMD_DATA_SIZE
: datalen
;
358 iso14b_raw_cmd_t
*packet
= (iso14b_raw_cmd_t
*)calloc(1, sizeof(iso14b_raw_cmd_t
) + datalen
);
359 if (packet
== NULL
) {
360 PrintAndLogEx(FAILED
, "failed to allocate memory");
363 packet
->flags
= flags
;
364 packet
->timeout
= time_wait
;
365 packet
->rawlen
= datalen
;
366 memcpy(packet
->raw
, data
, datalen
);
368 clearCommandBuffer();
369 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
) + packet
->rawlen
);
372 if (read_reply
== false) {
373 clearCommandBuffer();
379 // Select, device will send back iso14b_card_select_t, don't print it.
381 success
= wait_cmd_14b(verbose
, true, user_timeout
);
382 if (verbose
&& success
)
383 PrintAndLogEx(SUCCESS
, "Got response for standard select");
387 success
= wait_cmd_14b(verbose
, true, user_timeout
);
388 if (verbose
&& success
)
389 PrintAndLogEx(SUCCESS
, "Got response for ST/SRx select");
393 success
= wait_cmd_14b(verbose
, true, user_timeout
);
394 if (verbose
&& success
)
395 PrintAndLogEx(SUCCESS
, "Got response for ASK/C-ticket select");
398 // get back response from the raw bytes you sent.
399 if (success
&& datalen
> 0) {
400 wait_cmd_14b(true, false, user_timeout
);
406 static bool get_14b_UID(iso14b_card_select_t
*card
) {
411 iso14b_raw_cmd_t packet
= {
412 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_SR
| ISO14B_DISCONNECT
),
417 PacketResponseNG resp
;
418 clearCommandBuffer();
419 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
421 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
)) {
423 if (resp
.oldarg
[0] == 0) {
424 memcpy(card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
430 packet
.flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_DISCONNECT
);
431 clearCommandBuffer();
432 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
433 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
)) {
435 if (resp
.oldarg
[0] == 0) {
436 memcpy(card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
441 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
445 // print full atqb info
447 // 0,1,2,3 = application data
448 // 4 = bit rate capacity
449 // 5 = max frame size / -4 info
450 // 6 = FWI / Coding options
451 static int print_atqb_resp(uint8_t *data
, uint8_t cid
) {
452 //PrintAndLogEx(SUCCESS, " UID: %s", sprint_hex(data+1,4));
453 PrintAndLogEx(SUCCESS
, " App Data: %s", sprint_hex(data
, 4));
454 PrintAndLogEx(SUCCESS
, " Protocol: %s", sprint_hex(data
+ 4, 3));
455 uint8_t BitRate
= data
[4];
456 if (!BitRate
) PrintAndLogEx(SUCCESS
, " Bit Rate: 106 kbit/s only PICC <-> PCD");
457 if (BitRate
& 0x10) PrintAndLogEx(SUCCESS
, " Bit Rate: 212 kbit/s PICC -> PCD supported");
458 if (BitRate
& 0x20) PrintAndLogEx(SUCCESS
, " Bit Rate: 424 kbit/s PICC -> PCD supported");
459 if (BitRate
& 0x40) PrintAndLogEx(SUCCESS
, " Bit Rate: 847 kbit/s PICC -> PCD supported");
460 if (BitRate
& 0x01) PrintAndLogEx(SUCCESS
, " Bit Rate: 212 kbit/s PICC <- PCD supported");
461 if (BitRate
& 0x02) PrintAndLogEx(SUCCESS
, " Bit Rate: 424 kbit/s PICC <- PCD supported");
462 if (BitRate
& 0x04) PrintAndLogEx(SUCCESS
, " Bit Rate: 847 kbit/s PICC <- PCD supported");
463 if (BitRate
& 0x80) PrintAndLogEx(SUCCESS
, " Same bit rate <-> required");
465 uint16_t maxFrame
= data
[5] >> 4;
466 if (maxFrame
< 5) maxFrame
= 8 * maxFrame
+ 16;
467 else if (maxFrame
== 5) maxFrame
= 64;
468 else if (maxFrame
== 6) maxFrame
= 96;
469 else if (maxFrame
== 7) maxFrame
= 128;
470 else if (maxFrame
== 8) maxFrame
= 256;
473 PrintAndLogEx(SUCCESS
, "Max Frame Size: %u%s bytes", maxFrame
, (maxFrame
== 257) ? "+ RFU" : "");
475 uint8_t protocolT
= data
[5] & 0xF;
476 PrintAndLogEx(SUCCESS
, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4", (protocolT
) ? "" : "not ");
478 uint8_t fwt
= data
[6] >> 4;
480 uint32_t etus
= (32 << fwt
);
481 uint32_t fwt_time
= (302 << fwt
);
482 PrintAndLogEx(SUCCESS
, "Frame Wait Integer: %u - %u ETUs | %u us", fwt
, etus
, fwt_time
);
484 PrintAndLogEx(SUCCESS
, "Frame Wait Integer: %u - RFU", fwt
);
487 PrintAndLogEx(SUCCESS
, " App Data Code: Application is %s", (data
[6] & 4) ? "Standard" : "Proprietary");
488 PrintAndLogEx(SUCCESS
, " Frame Options: NAD is %ssupported", (data
[6] & 2) ? "" : "not ");
489 PrintAndLogEx(SUCCESS
, " Frame Options: CID is %ssupported", (data
[6] & 1) ? "" : "not ");
490 PrintAndLogEx(SUCCESS
, "Tag :");
491 PrintAndLogEx(SUCCESS
, " Max Buf Length: %u (MBLI) %s", cid
>> 4, (cid
& 0xF0) ? "" : "chained frames not supported");
492 PrintAndLogEx(SUCCESS
, " CID : %u", cid
& 0x0f);
496 // get SRx chip model (from UID) // from ST Microelectronics
497 static char *get_st_chip_model(uint8_t data
) {
498 static char model
[20];
499 char *retStr
= model
;
500 memset(model
, 0, sizeof(model
));
504 sprintf(retStr
, "SRIX4K (Special)");
507 sprintf(retStr
, "SR176");
510 sprintf(retStr
, "SRIX4K");
513 sprintf(retStr
, "SRIX512");
516 sprintf(retStr
, "SRI512");
519 sprintf(retStr
, "SRI4K");
522 sprintf(retStr
, "SRT512");
525 sprintf(retStr
, "Unknown");
531 static char *get_st_lock_info(uint8_t model
, uint8_t *lockbytes
, uint8_t blk
) {
543 case 0x0: // SRIX4K special
576 if ((lockbytes
[1] & mask
) == 0) {
577 sprintf(s
, _RED_("1"));
583 case 0xC: { // SRT512
584 //need data[2] and data[3]
644 if ((lockbytes
[b
] & mask
) == 0) {
645 sprintf(s
, _RED_("1"));
685 // iceman: this is opposite! need sample to test with.
686 if ((lockbytes
[0] & mask
)) {
687 sprintf(s
, _RED_("1"));
697 static uint8_t get_st_chipid(uint8_t *uid
) {
701 static uint8_t get_st_cardsize(uint8_t *uid
) {
702 uint8_t chipid
= get_st_chipid(uid
);
718 // print UID info from SRx chips (ST Microelectronics)
719 static void print_st_general_info(uint8_t *data
, uint8_t len
) {
720 //uid = first 8 bytes in data
721 uint8_t mfgid
= data
[6];
722 uint8_t chipid
= get_st_chipid(data
);
723 PrintAndLogEx(NORMAL
, "");
724 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(SwapEndian64(data
, 8, 8), len
));
725 PrintAndLogEx(SUCCESS
, " MFG: %02X, " _YELLOW_("%s"), mfgid
, getTagInfo(mfgid
));
726 PrintAndLogEx(SUCCESS
, "Chip: %02X, " _YELLOW_("%s"), chipid
, get_st_chip_model(chipid
));
729 // print UID info from ASK CT chips
730 static void print_ct_general_info(void *vcard
) {
731 iso14b_cts_card_select_t card
;
732 memcpy(&card
, (iso14b_cts_card_select_t
*)vcard
, sizeof(iso14b_cts_card_select_t
));
734 uint32_t uid32
= (card
.uid
[0] | card
.uid
[1] << 8 | card
.uid
[2] << 16 | card
.uid
[3] << 24);
735 PrintAndLogEx(NORMAL
, "");
736 PrintAndLogEx(SUCCESS
, "ASK C-Ticket");
737 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s") " ( " _YELLOW_("%010u") " )", sprint_hex(card
.uid
, sizeof(card
.uid
)), uid32
);
738 PrintAndLogEx(SUCCESS
, " Product Code: %02X", card
.pc
);
739 PrintAndLogEx(SUCCESS
, " Facility Code: %02X", card
.fc
);
740 PrintAndLogEx(NORMAL
, "");
744 // 05 00 00 = find one tag in field
745 // 1d xx xx xx xx 00 08 01 00 = attrib xx=UID (resp 10 [f9 e0])
746 // 0200a40400 (resp 02 67 00 [29 5b])
747 // 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b])
748 // 0200a4040c07a0000002480200 (resp 02 67 00 [29 5b])
749 // 0200a4040006a0000000010100 (resp 02 6a 82 [4b 4c])
750 // 0200a4040c09d27600002545500200 (resp 02 67 00 [29 5b])
751 // 0200a404000cd2760001354b414e4d30310000 (resp 02 6a 82 [4b 4c])
752 // 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c])
753 // 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
755 // 14b get and print Full Info (as much as we know)
756 static bool HF14B_Std_Info(bool verbose
, bool do_aid_search
) {
757 // 14b get and print UID only (general info)
758 iso14b_raw_cmd_t packet
= {
759 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_DISCONNECT
),
764 clearCommandBuffer();
765 PacketResponseNG resp
;
766 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
767 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
769 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
771 switch_off_field_14b();
775 iso14b_card_select_t card
;
776 memcpy(&card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
778 int status
= resp
.oldarg
[0];
781 PrintAndLogEx(NORMAL
, "");
782 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("Tag information") " --------------------");
783 PrintAndLogEx(SUCCESS
, " UID : " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
784 PrintAndLogEx(SUCCESS
, " ATQB : %s", sprint_hex(card
.atqb
, sizeof(card
.atqb
)));
785 PrintAndLogEx(SUCCESS
, " CHIPID : %02X", card
.chipid
);
786 print_atqb_resp(card
.atqb
, card
.cid
);
789 hf14b_aid_search(verbose
);
795 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 STD ATTRIB fail");
798 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 STD CRC fail");
801 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-b STD select failed");
808 // SRx get and print full info (needs more info...)
809 static bool HF14B_ST_Info(bool verbose
, bool do_aid_search
) {
811 iso14b_raw_cmd_t packet
= {
812 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_SR
| ISO14B_DISCONNECT
),
817 clearCommandBuffer();
818 PacketResponseNG resp
;
819 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
820 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
822 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
827 iso14b_card_select_t card
;
828 memcpy(&card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
830 int status
= resp
.oldarg
[0];
834 print_st_general_info(card
.uid
, card
.uidlen
);
837 hf14b_aid_search(verbose
);
842 // menu command to get and print all info known about any known 14b tag
843 static int CmdHF14Binfo(const char *Cmd
) {
844 CLIParserContext
*ctx
;
845 CLIParserInit(&ctx
, "hf 14b info",
846 "Tag information for ISO/IEC 14443 type B based tags",
852 arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
853 arg_lit0("v", "verbose", "verbose"),
856 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
857 bool do_aid_search
= arg_get_lit(ctx
, 1);
858 bool verbose
= arg_get_lit(ctx
, 2);
860 return infoHF14B(verbose
, do_aid_search
);
863 static bool HF14B_st_reader(bool verbose
) {
865 iso14b_raw_cmd_t packet
= {
866 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_SR
| ISO14B_DISCONNECT
),
871 // SRx get and print general info about SRx chip from UID
872 clearCommandBuffer();
873 PacketResponseNG resp
;
874 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
875 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
877 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
882 iso14b_card_select_t card
;
883 memcpy(&card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
885 int status
= resp
.oldarg
[0];
888 print_st_general_info(card
.uid
, card
.uidlen
);
891 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 ST ATTRIB fail");
894 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 ST CRC fail");
897 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 ST random chip id fail");
900 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-b ST select SRx failed");
906 static bool HF14B_std_reader(bool verbose
) {
907 iso14b_raw_cmd_t packet
= {
908 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_DISCONNECT
),
913 // 14b get and print UID only (general info)
914 clearCommandBuffer();
915 PacketResponseNG resp
;
916 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
917 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
919 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
924 int status
= resp
.oldarg
[0];
927 iso14b_card_select_t card
;
928 memcpy(&card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
929 PrintAndLogEx(NORMAL
, "");
930 PrintAndLogEx(SUCCESS
, " UID : " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
931 PrintAndLogEx(SUCCESS
, " ATQB : %s", sprint_hex(card
.atqb
, sizeof(card
.atqb
)));
932 PrintAndLogEx(SUCCESS
, " CHIPID : %02X", card
.chipid
);
933 print_atqb_resp(card
.atqb
, card
.cid
);
937 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 ATTRIB fail");
941 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 CRC fail");
945 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-b card select failed");
952 static bool HF14B_ask_ct_reader(bool verbose
) {
954 iso14b_raw_cmd_t packet
= {
955 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_CTS
| ISO14B_DISCONNECT
),
960 // 14b get and print UID only (general info)
961 clearCommandBuffer();
962 PacketResponseNG resp
;
963 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
964 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
965 if (verbose
) PrintAndLogEx(WARNING
, "timeout while waiting for reply");
969 int status
= resp
.oldarg
[0];
973 print_ct_general_info(resp
.data
.asBytes
);
977 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 CTS wrong length");
981 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 CTS CRC fail");
985 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-b CTS select failed");
992 // test for other 14b type tags (mimic another reader - don't have tags to identify)
993 static bool HF14B_other_reader(bool verbose
) {
995 iso14b_raw_cmd_t
*packet
= (iso14b_raw_cmd_t
*)calloc(1, sizeof(iso14b_raw_cmd_t
) + 4);
996 if (packet
== NULL
) {
997 PrintAndLogEx(FAILED
, "failed to allocate memory");
1000 packet
->flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_RAW
| ISO14B_APPEND_CRC
);
1001 packet
->timeout
= 0;
1003 memcpy(packet
->raw
, "\x00\x0b\x3f\x80", 4);
1005 // 14b get and print UID only (general info)
1007 clearCommandBuffer();
1008 PacketResponseNG resp
;
1009 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
) + packet
->rawlen
);
1010 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
1012 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
1015 switch_off_field_14b();
1018 int status
= resp
.oldarg
[0];
1019 PrintAndLogEx(DEBUG
, "status %d", status
);
1022 PrintAndLogEx(SUCCESS
, "\n14443-3b tag found:");
1023 PrintAndLogEx(SUCCESS
, "unknown tag type answered to a 0x000b3f80 command ans:");
1024 switch_off_field_14b();
1027 } else if (status
> 0) {
1028 PrintAndLogEx(SUCCESS
, "\n14443-3b tag found:");
1029 PrintAndLogEx(SUCCESS
, "unknown tag type answered to a 0x000b3f80 command ans:");
1030 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(resp
.data
.asBytes
, status
));
1031 switch_off_field_14b();
1037 packet
->raw
[0] = ISO14443B_AUTHENTICATE
;
1038 clearCommandBuffer();
1039 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
) + packet
->rawlen
);
1040 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
1042 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
1044 switch_off_field_14b();
1048 status
= resp
.oldarg
[0];
1049 PrintAndLogEx(DEBUG
, "status %d", status
);
1052 PrintAndLogEx(SUCCESS
, "\n14443-3b tag found:");
1053 PrintAndLogEx(SUCCESS
, "Unknown tag type answered to a 0x0A command ans:");
1054 switch_off_field_14b();
1057 } else if (status
> 0) {
1058 PrintAndLogEx(SUCCESS
, "\n14443-3b tag found:");
1059 PrintAndLogEx(SUCCESS
, "unknown tag type answered to a 0x0A command ans:");
1060 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(resp
.data
.asBytes
, status
));
1061 switch_off_field_14b();
1066 packet
->raw
[0] = ISO14443B_RESET
;
1067 clearCommandBuffer();
1068 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
) + packet
->rawlen
);
1070 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
1072 PrintAndLogEx(WARNING
, "timeout while waiting for reply");
1074 switch_off_field_14b();
1077 status
= resp
.oldarg
[0];
1078 PrintAndLogEx(DEBUG
, "status %d", status
);
1081 PrintAndLogEx(SUCCESS
, "\n14443-3b tag found:");
1082 PrintAndLogEx(SUCCESS
, "Unknown tag type answered to a 0x0C command ans:");
1083 switch_off_field_14b();
1085 } else if (status
> 0) {
1086 PrintAndLogEx(SUCCESS
, "\n14443-3b tag found:");
1087 PrintAndLogEx(SUCCESS
, "unknown tag type answered to a 0x0C command ans:");
1088 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(resp
.data
.asBytes
, status
));
1089 switch_off_field_14b();
1093 switch_off_field_14b();
1097 // menu command to get and print general info about all known 14b chips
1098 static int CmdHF14BReader(const char *Cmd
) {
1099 CLIParserContext
*ctx
;
1100 CLIParserInit(&ctx
, "hf 14b reader",
1101 "Act as a 14443B reader to identify a tag",
1105 void *argtable
[] = {
1107 arg_lit0("s", "silent", "silent (no messages)"),
1108 arg_lit0("@", NULL
, "optional - continuous reader mode"),
1111 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1112 bool verbose
= (arg_get_lit(ctx
, 1) == false);
1113 bool cm
= arg_get_lit(ctx
, 2);
1117 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
1120 return readHF14B(cm
, verbose
);
1123 // Read SRI512|SRIX4K block
1124 static int CmdHF14BSriRdBl(const char *Cmd
) {
1126 CLIParserContext
*ctx
;
1127 CLIParserInit(&ctx
, "hf 14b rdbl",
1128 "Read SRI512 | SRIX4K block",
1129 "hf 14b rdbl -b 06\n"
1132 void *argtable
[] = {
1134 arg_int0("b", "block", "<dec>", "block number"),
1137 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1138 int blockno
= arg_get_int_def(ctx
, 1, -1);
1142 iso14b_card_select_t card;
1143 if (get_14b_UID(&card) == false) {
1144 PrintAndLogEx(WARNING, "no tag found");
1148 if (card.uidlen != 8) {
1149 PrintAndLogEx(FAILED, "current read command only work with SRI4K / SRI512 tags");
1156 uint8_t cardtype = get_st_cardsize(card.uid);
1157 uint8_t blocks = (cardtype == 1) ? 0x7F : 0x0F;
1163 payload
.blockno
= blockno
;
1165 PacketResponseNG resp
;
1166 clearCommandBuffer();
1167 SendCommandNG(CMD_HF_SRI_READ
, (uint8_t *)&payload
, sizeof(payload
));
1168 if (WaitForResponseTimeout(CMD_HF_SRI_READ
, &resp
, TIMEOUT
) == false) {
1169 return PM3_ETIMEOUT
;
1171 if (resp
.status
== PM3_SUCCESS
) {
1172 PrintAndLogEx(SUCCESS
, "block %02u : " _GREEN_("%s") " | " _GREEN_("%s"), blockno
, sprint_hex(resp
.data
.asBytes
, resp
.length
), sprint_ascii(resp
.data
.asBytes
, resp
.length
));
1177 // New command to write a SRI512/SRIX4K tag.
1178 static int CmdHF14BWriteSri(const char *Cmd
) {
1180 * For SRIX4K blocks 00 - 7F
1181 * hf 14b raw --sr -c --data [09 $srix4kwblock $srix4kwdata
1183 * For SR512 blocks 00 - 0F
1184 * hf 14b raw --sr -c --data [09 $sr512wblock $sr512wdata]
1186 * Special block FF = otp_lock_reg block.
1190 CLIParserContext
*ctx
;
1191 CLIParserInit(&ctx
, "hf 14b sriwrite",
1192 "Write data to a SRI512 or SRIX4K block",
1193 "hf 14b sriwrite --4k -b 100 -d 11223344\n"
1194 "hf 14b sriwrite --4k --sb -d 11223344 --> special block write\n"
1195 "hf 14b sriwrite --512 -b 15 -d 11223344\n"
1196 "hf 14b sriwrite --512 --sb -d 11223344 --> special block write\n"
1199 void *argtable
[] = {
1201 arg_int0("b", "block", "<dec>", "block number"),
1202 arg_str1("d", "data", "<hex>", "4 hex bytes"),
1203 arg_lit0(NULL
, "512", "target SRI 512 tag"),
1204 arg_lit0(NULL
, "4k", "target SRIX 4k tag"),
1205 arg_lit0(NULL
, "sb", "special block write at end of memory (0xFF)"),
1208 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1209 int blockno
= arg_get_int_def(ctx
, 1, -1);
1211 uint8_t data
[4] = {0, 0, 0, 0};
1212 int res
= CLIParamHexToBuf(arg_get_str(ctx
, 2), data
, sizeof(data
), &dlen
);
1218 bool use_sri512
= arg_get_lit(ctx
, 3);
1219 bool use_srix4k
= arg_get_lit(ctx
, 4);
1220 bool special
= arg_get_lit(ctx
, 5);
1223 if (dlen
!= sizeof(data
)) {
1224 PrintAndLogEx(FAILED
, "data must be 4 hex bytes, got %d", dlen
);
1228 if (use_sri512
+ use_srix4k
> 1) {
1229 PrintAndLogEx(FAILED
, "Select only one card type");
1233 if (use_srix4k
&& blockno
> 0x7F) {
1234 PrintAndLogEx(FAILED
, "block number out of range, max 127 (0x7F)");
1238 if (use_sri512
&& blockno
> 0x0F) {
1239 PrintAndLogEx(FAILED
, "block number out of range, max 15 (0x0F)");
1243 // special block at end of memory
1246 PrintAndLogEx(SUCCESS
, "[%s] Write special block %02X [ " _YELLOW_("%s")" ]",
1247 (use_srix4k
) ? "SRIX4K" : "SRI512",
1249 sprint_hex(data
, sizeof(data
))
1252 PrintAndLogEx(SUCCESS
, "[%s] Write block %02X [ " _YELLOW_("%s")" ]",
1253 (use_srix4k
) ? "SRIX4K" : "SRI512",
1255 sprint_hex(data
, sizeof(data
))
1260 memset(str
, 0x00, sizeof(str
));
1261 sprintf(str
, "--sr -c --data %02x%02x%02x%02x%02x%02x", ISO14443B_WRITE_BLK
, blockno
, data
[0], data
[1], data
[2], data
[3]);
1262 return CmdHF14BCmdRaw(str
);
1265 // need to write to file
1266 static int CmdHF14BDump(const char *Cmd
) {
1268 CLIParserContext
*ctx
;
1269 CLIParserInit(&ctx
, "hf 14b dump",
1270 "This command dumps the contents of a ISO-14443-B tag and save it to file\n"
1271 "Tries to autodetect cardtype, memory size defaults to SRI4K",
1273 "hf 14b dump -f myfilename\n"
1276 void *argtable
[] = {
1278 arg_strx0("f", "file", "<filename>", "(optional) filename, if no <name> UID will be used as filename"),
1281 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1284 char filename
[FILE_PATH_SIZE
] = {0};
1285 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
1288 iso14b_card_select_t card
;
1289 if (get_14b_UID(&card
) == false) {
1290 PrintAndLogEx(WARNING
, "no tag found");
1294 if (card
.uidlen
!= 8) {
1295 PrintAndLogEx(FAILED
, "current dump command only work with SRI4K / SRI512 tags");
1302 uint8_t cardtype
= get_st_cardsize(card
.uid
);
1304 uint16_t cardsize
= 0;
1308 cardsize
= (512 / 8) + 4;
1313 cardsize
= (4096 / 8) + 4;
1318 uint8_t chipid
= get_st_chipid(card
.uid
);
1319 PrintAndLogEx(SUCCESS
, "found a " _GREEN_("%s") " tag", get_st_chip_model(chipid
));
1321 // detect blocksize from card :)
1322 PrintAndLogEx(INFO
, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card
.uid
, card
.uidlen
, 8), card
.uidlen
));
1324 iso14b_raw_cmd_t
*packet
= (iso14b_raw_cmd_t
*)calloc(1, sizeof(iso14b_raw_cmd_t
) + 2);
1325 if (packet
== NULL
) {
1326 PrintAndLogEx(FAILED
, "failed to allocate memory");
1329 packet
->flags
= (ISO14B_CONNECT
| ISO14B_SELECT_SR
);
1330 packet
->timeout
= 0;
1333 clearCommandBuffer();
1334 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
));
1335 PacketResponseNG resp
;
1339 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, 2000)) {
1340 status
= resp
.oldarg
[0];
1342 PrintAndLogEx(FAILED
, "failed to select arg0[%" PRId64
"]", resp
.oldarg
[0]);
1344 return switch_off_field_14b();
1348 PrintAndLogEx(INFO
, "." NOLF
);
1350 uint8_t data
[cardsize
];
1351 memset(data
, 0, sizeof(data
));
1352 uint16_t blocknum
= 0;
1354 for (int retry
= 0; retry
< 5; retry
++) {
1356 // set up the read command
1357 packet
->flags
= (ISO14B_APPEND_CRC
| ISO14B_RAW
);
1359 packet
->raw
[0] = ISO14443B_READ_BLK
;
1360 packet
->raw
[1] = blocknum
& 0xFF;
1362 clearCommandBuffer();
1363 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
) + 2);
1364 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, 2000)) {
1366 status
= resp
.oldarg
[0];
1368 PrintAndLogEx(FAILED
, "retrying one more time");
1372 uint16_t len
= (resp
.oldarg
[1] & 0xFFFF);
1373 uint8_t *recv
= resp
.data
.asBytes
;
1375 if (check_crc(CRC_14443_B
, recv
, len
) == false) {
1376 PrintAndLogEx(FAILED
, "crc fail, retrying one more time");
1382 if (blocknum
== 0xFF) {
1383 // we reserved space for this block after 0x0F and 0x7F, ie 0x10, 0x80
1384 memcpy(data
+ (blocks
* 4), recv
, 4);
1387 memcpy(data
+ (blocknum
* 4), recv
, 4);
1392 if (blocknum
> blocks
) {
1393 // read config block
1397 PrintAndLogEx(NORMAL
, "." NOLF
);
1403 PrintAndLogEx(NORMAL
, "");
1405 if (blocknum
!= 0xFF) {
1406 PrintAndLogEx(FAILED
, "dump failed");
1407 return switch_off_field_14b();
1410 PrintAndLogEx(DEBUG
, "systemblock : %s", sprint_hex(data
+ (blocks
* 4), 4));
1411 PrintAndLogEx(DEBUG
, " otp lock : %02x %02x", data
[(blocks
* 4)], data
[(blocks
* 4) + 1]);
1414 PrintAndLogEx(INFO
, " block# | data |lck| ascii");
1415 PrintAndLogEx(INFO
, "---------+--------------+---+----------");
1417 for (int i
= 0; i
<= blocks
; i
++) {
1419 "%3d/0x%02X | %s | %s | %s",
1422 sprint_hex(data
+ (i
* 4), 4),
1423 get_st_lock_info(chipid
, data
+ (blocks
* 4), i
),
1424 sprint_ascii(data
+ (i
* 4), 4)
1429 "%3d/0x%02X | %s | %s | %s",
1432 sprint_hex(data
+ (0xFF * 4), 4),
1433 get_st_lock_info(chipid
, data
+ (blocks
* 4), 0xFF),
1434 sprint_ascii(data
+ (0xFF * 4), 4)
1436 PrintAndLogEx(INFO
, "---------+--------------+---+----------");
1437 PrintAndLogEx(NORMAL
, "");
1441 PrintAndLogEx(INFO
, "using UID as filename");
1442 char *fptr
= filename
;
1443 fptr
+= sprintf(fptr
, "hf-14b-");
1444 FillFileNameByUID(fptr
, SwapEndian64(card
.uid
, card
.uidlen
, 8), "-dump", card
.uidlen
);
1447 size_t datalen
= (blocks
+ 1) * 4;
1448 saveFile(filename
, ".bin", data
, datalen
);
1449 saveFileEML(filename
, data
, datalen
, 4);
1450 saveFileJSON(filename
, jsf14b
, data
, datalen
, NULL
);
1451 return switch_off_field_14b();
1455 static uint32_t srix4kEncode(uint32_t value) {
1459 // 4 bytes : 00 1A 20 01
1460 // only the lower crumbs.
1461 uint8_t block = (value & 0xFF);
1463 uint8_t valuebytes[] = {0, 0, 0};
1465 num_to_bytes(value, 3, valuebytes);
1468 // Crumb swapping of value.
1469 uint8_t temp[] = {0, 0};
1470 temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14) << 2 | CRUMB(value, 6)) << 4;
1471 temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12) << 2 | CRUMB(value, 4);
1472 temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10) << 2 | CRUMB(value, 2)) << 4;
1473 temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8) << 2 | CRUMB(value, 0);
1476 uint32_t chksum = 0xFF - block;
1478 // chksum is reduced by each nibbles of value.
1479 for (i = 0; i < 3; ++i) {
1480 chksum -= NIBBLE_HIGH(valuebytes[i]);
1481 chksum -= NIBBLE_LOW(valuebytes[i]);
1484 // base4 conversion and left shift twice
1486 uint8_t base4[] = {0, 0, 0, 0};
1487 while (chksum != 0) {
1488 base4[i--] = (chksum % 4 << 2);
1492 // merge scambled and chksum parts
1494 (NIBBLE_LOW(base4[0]) << 28) |
1495 (NIBBLE_HIGH(temp[0]) << 24) |
1497 (NIBBLE_LOW(base4[1]) << 20) |
1498 (NIBBLE_LOW(temp[0]) << 16) |
1500 (NIBBLE_LOW(base4[2]) << 12) |
1501 (NIBBLE_HIGH(temp[1]) << 8) |
1503 (NIBBLE_LOW(base4[3]) << 4) |
1504 NIBBLE_LOW(temp[1]);
1506 PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue);
1510 static uint32_t srix4kDecode(uint32_t value) {
1522 static uint32_t srix4kDecodeCounter(uint32_t num) {
1523 uint32_t value = ~num;
1528 static uint32_t srix4kGetMagicbytes(uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19) {
1529 #define MASK 0xFFFFFFFF;
1530 uint32_t uid32 = uid & MASK;
1531 uint32_t counter = srix4kDecodeCounter(block6);
1532 uint32_t decodedBlock18 = srix4kDecode(block18);
1533 uint32_t decodedBlock19 = srix4kDecode(block19);
1534 uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1;
1536 uint32_t result = (uid32 * doubleBlock * counter) & MASK;
1537 PrintAndLogEx(SUCCESS, "Magic bytes | %08X", result);
1541 static int srix4kValid(const char *Cmd) {
1542 (void)Cmd; // Cmd is not used so far
1544 uint64_t uid = 0xD00202501A4532F9;
1545 uint32_t block6 = 0xFFFFFFFF;
1546 uint32_t block18 = 0xC04F42C5;
1547 uint32_t block19 = 0xC1484807;
1548 uint32_t block21 = 0xD1BCABA4;
1550 uint32_t test_b18 = 0x00313918;
1551 uint32_t test_b18_enc = srix4kEncode(test_b18);
1552 //uint32_t test_b18_dec = srix4kDecode(test_b18_enc);
1553 PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc, "");
1555 uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19);
1556 PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21);
1561 int select_card_14443b_4(bool disconnect
, iso14b_card_select_t
*card
) {
1563 memset(card
, 0, sizeof(iso14b_card_select_t
));
1565 switch_off_field_14b();
1567 iso14b_raw_cmd_t packet
= {
1568 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
),
1572 // Anticollision + SELECT STD card
1573 PacketResponseNG resp
;
1574 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
1575 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
1576 PrintAndLogEx(INFO
, "Trying 14B Select SRx");
1578 // Anticollision + SELECT SR card
1579 packet
.flags
= (ISO14B_CONNECT
| ISO14B_SELECT_SR
);
1580 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
1581 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
1582 PrintAndLogEx(INFO
, "Trying 14B Select CTS");
1584 // Anticollision + SELECT ASK C-Ticket card
1585 packet
.flags
= (ISO14B_CONNECT
| ISO14B_SELECT_CTS
);
1586 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
1587 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
1588 PrintAndLogEx(ERR
, "connection timeout");
1589 switch_off_field_14b();
1596 int status
= resp
.oldarg
[0];
1598 PrintAndLogEx(ERR
, "No card in field.");
1599 switch_off_field_14b();
1602 SetISODEPState(ISODEP_NFCB
);
1603 apdu_frame_length
= 0;
1604 // get frame length from ATS in card data structure
1605 iso14b_card_select_t
*vcard
= (iso14b_card_select_t
*) resp
.data
.asBytes
;
1606 // uint8_t fsci = vcard->atqb[1] & 0x0f;
1607 // if (fsci < ARRAYLEN(ats_fsc)) {
1608 // apdu_frame_length = ats_fsc[fsci];
1612 memcpy(card
, vcard
, sizeof(iso14b_card_select_t
));
1616 switch_off_field_14b();
1621 static int handle_14b_apdu(bool chainingin
, uint8_t *datain
, int datainlen
,
1622 bool activateField
, uint8_t *dataout
, int maxdataoutlen
,
1623 int *dataoutlen
, bool *chainingout
, int user_timeout
) {
1625 *chainingout
= false;
1627 if (activateField
) {
1628 // select with no disconnect and set frameLength
1629 int selres
= select_card_14443b_4(false, NULL
);
1630 if (selres
!= PM3_SUCCESS
)
1634 iso14b_raw_cmd_t
*packet
= (iso14b_raw_cmd_t
*)calloc(1, sizeof(iso14b_raw_cmd_t
) + datainlen
);
1635 if (packet
== NULL
) {
1636 PrintAndLogEx(FAILED
, "APDU: failed to allocate memory");
1639 packet
->flags
= (ISO14B_CONNECT
| ISO14B_APDU
);
1640 packet
->timeout
= 0;
1644 packet
->flags
= (ISO14B_SEND_CHAINING
| ISO14B_APDU
);
1646 if (user_timeout
> 0) {
1647 packet
->flags
|= ISO14B_SET_TIMEOUT
;
1648 if (user_timeout
> MAX_14B_TIMEOUT_MS
) {
1649 user_timeout
= MAX_14B_TIMEOUT_MS
;
1650 PrintAndLogEx(INFO
, "set timeout to 4.9 seconds. The max we can wait for response");
1654 packet
->timeout
= (uint32_t)((13560 / 128) * user_timeout
);
1657 // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
1658 // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
1659 // here length PM3_CMD_DATA_SIZE=512
1661 packet
->rawlen
= datainlen
;
1662 memcpy(packet
->raw
, datain
, datainlen
);
1663 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
) + packet
->rawlen
);
1665 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
));
1668 PacketResponseNG resp
;
1669 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, MAX(APDU_TIMEOUT
, user_timeout
)) == false) {
1670 PrintAndLogEx(ERR
, "APDU: reply timeout");
1671 return PM3_ETIMEOUT
;
1674 int rlen
= resp
.oldarg
[0];
1675 int dlen
= rlen
- 2;
1680 *dataoutlen
+= dlen
;
1682 if (maxdataoutlen
&& *dataoutlen
> maxdataoutlen
) {
1683 PrintAndLogEx(ERR
, "APDU: buffer too small(%d), needs %d bytes", maxdataoutlen
, *dataoutlen
);
1688 uint8_t res
= resp
.oldarg
[1];
1689 if ((res
& 0xF2) == 0xA2) {
1691 *chainingout
= true;
1696 PrintAndLogEx(ERR
, "APDU: no APDU response");
1700 // check apdu length
1701 if (rlen
== 0 || rlen
== 1) {
1702 PrintAndLogEx(ERR
, "APDU: small APDU response, len %d", rlen
);
1706 memcpy(dataout
, resp
.data
.asBytes
, dlen
);
1709 if ((res
& 0x10) != 0) {
1710 *chainingout
= true;
1715 int exchange_14b_apdu(uint8_t *datain
, int datainlen
, bool activate_field
,
1716 bool leave_signal_on
, uint8_t *dataout
, int maxdataoutlen
,
1717 int *dataoutlen
, int user_timeout
) {
1720 bool chaining
= false;
1723 // 3 byte here - 1b framing header, 2b crc16
1724 if (apdu_in_framing_enable
&&
1725 ((apdu_frame_length
&& (datainlen
> apdu_frame_length
- 3)) || (datainlen
> PM3_CMD_DATA_SIZE
- 3))) {
1728 bool v_activate_field
= activate_field
;
1731 int vlen
= MIN(apdu_frame_length
- 3, datainlen
- clen
);
1732 bool chainBlockNotLast
= ((clen
+ vlen
) < datainlen
);
1735 res
= handle_14b_apdu(chainBlockNotLast
, &datain
[clen
], vlen
, v_activate_field
, dataout
, maxdataoutlen
, dataoutlen
, &chaining
, user_timeout
);
1737 if (leave_signal_on
== false)
1738 switch_off_field_14b();
1743 // TODO check this one...
1744 // check R-block ACK
1745 // *dataoutlen!=0. 'A && (!A || B)' is equivalent to 'A && B'
1746 if ((*dataoutlen
== 0) && (chaining
!= chainBlockNotLast
)) {
1747 if (leave_signal_on
== false) {
1748 switch_off_field_14b();
1754 v_activate_field
= false;
1756 if (clen
!= datainlen
)
1757 PrintAndLogEx(ERR
, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen
, clen
, *dataoutlen
);
1760 } while (clen
< datainlen
);
1764 res
= handle_14b_apdu(false, datain
, datainlen
, activate_field
, dataout
, maxdataoutlen
, dataoutlen
, &chaining
, user_timeout
);
1765 if (res
!= PM3_SUCCESS
) {
1766 if (leave_signal_on
== false) {
1767 switch_off_field_14b();
1774 // I-block with chaining
1775 res
= handle_14b_apdu(false, NULL
, 0, false, &dataout
[*dataoutlen
], maxdataoutlen
, dataoutlen
, &chaining
, user_timeout
);
1776 if (res
!= PM3_SUCCESS
) {
1777 if (leave_signal_on
== false) {
1778 switch_off_field_14b();
1784 if (leave_signal_on
== false) {
1785 switch_off_field_14b();
1791 // ISO14443-4. 7. Half-duplex block transmission protocol
1792 static int CmdHF14BAPDU(const char *Cmd
) {
1793 uint8_t data
[PM3_CMD_DATA_SIZE
];
1795 uint8_t header
[PM3_CMD_DATA_SIZE
];
1797 bool activate_field
= false;
1798 bool leave_signal_on
= false;
1799 bool decode_TLV
= false;
1800 bool decode_APDU
= false;
1801 bool make_APDU
= false;
1802 bool extended_APDU
= false;
1805 CLIParserContext
*ctx
;
1806 CLIParserInit(&ctx
, "hf 14b apdu",
1807 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL).\n"
1808 "works with all apdu types from ISO 7816-4:2013",
1809 "hf 14b apdu -s -d 94a40800043f000002\n"
1810 "hf 14b apdu -s --decode -d 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
1811 "hf 14b apdu -sm 00A40400 -l 256 -d 325041592E5359532E4444463031 -> encode standard apdu\n"
1812 "hf 14b apdu -sm 00A40400 -el 65536 -d 325041592E5359532E4444463031 -> encode extended apdu\n");
1814 void *argtable
[] = {
1816 arg_lit0("s", "select", "activate field and select card"),
1817 arg_lit0("k", "keep", "leave the signal field ON after receive response"),
1818 arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
1819 arg_lit0(NULL
, "decode", "decode apdu request if it possible"),
1820 arg_str0("m", "make", "<hex>", "make apdu with head from this field and data from data field.\n"
1821 " must be 4 bytes: <CLA INS P1 P2>"),
1822 arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
1823 arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
1824 arg_strx1("d", "data", "<hex>", "<APDU | data> if `m` parameter included"),
1825 arg_int0(NULL
, "timeout", "<dec>", "timeout in ms"),
1828 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1830 activate_field
= arg_get_lit(ctx
, 1);
1831 leave_signal_on
= arg_get_lit(ctx
, 2);
1832 decode_TLV
= arg_get_lit(ctx
, 3);
1833 decode_APDU
= arg_get_lit(ctx
, 4);
1835 CLIGetHexWithReturn(ctx
, 5, header
, &headerlen
);
1836 make_APDU
= headerlen
> 0;
1837 if (make_APDU
&& headerlen
!= 4) {
1838 PrintAndLogEx(ERR
, "header length must be 4 bytes instead of %d", headerlen
);
1843 extended_APDU
= arg_get_lit(ctx
, 6);
1844 le
= arg_get_int_def(ctx
, 7, 0);
1847 uint8_t apdudata
[PM3_CMD_DATA_SIZE
] = {0};
1848 int apdudatalen
= 0;
1850 CLIGetHexBLessWithReturn(ctx
, 8, apdudata
, &apdudatalen
, 1 + 2);
1853 apdu
.cla
= header
[0];
1854 apdu
.ins
= header
[1];
1855 apdu
.p1
= header
[2];
1856 apdu
.p2
= header
[3];
1858 apdu
.lc
= apdudatalen
;
1859 apdu
.data
= apdudata
;
1861 apdu
.extended_apdu
= extended_APDU
;
1864 if (APDUEncode(&apdu
, data
, &datalen
)) {
1865 PrintAndLogEx(ERR
, "can't make apdu with provided parameters.");
1871 if (extended_APDU
) {
1872 PrintAndLogEx(ERR
, "make mode not set but here `e` option.");
1877 PrintAndLogEx(ERR
, "make mode not set but here `l` option.");
1882 // len = data + PCB(1b) + CRC(2b)
1883 CLIGetHexBLessWithReturn(ctx
, 8, data
, &datalen
, 1 + 2);
1885 int user_timeout
= arg_get_int_def(ctx
, 9, -1);
1888 PrintAndLogEx(NORMAL
, ">>>>[%s%s%s] %s",
1889 activate_field
? "sel" : "",
1890 leave_signal_on
? " keep" : "",
1891 decode_TLV
? " TLV" : "",
1892 sprint_hex(data
, datalen
)
1897 if (APDUDecode(data
, datalen
, &apdu
) == 0)
1900 PrintAndLogEx(WARNING
, "can't decode APDU.");
1903 int res
= exchange_14b_apdu(data
, datalen
, activate_field
, leave_signal_on
, data
, PM3_CMD_DATA_SIZE
, &datalen
, user_timeout
);
1904 if (res
!= PM3_SUCCESS
) {
1908 PrintAndLogEx(NORMAL
, "<<<< %s", sprint_hex(data
, datalen
));
1909 PrintAndLogEx(SUCCESS
, "APDU response: " _YELLOW_("%02x %02x") " - %s", data
[datalen
- 2], data
[datalen
- 1], GetAPDUCodeDescription(data
[datalen
- 2], data
[datalen
- 1]));
1912 if (decode_TLV
&& datalen
> 4) {
1913 TLVPrintFromBuffer(data
, datalen
- 2);
1919 int CmdHF14BNdefRead(const char *Cmd
) {
1921 CLIParserContext
*ctx
;
1922 CLIParserInit(&ctx
, "hf 14b ndefread",
1923 "Print NFC Data Exchange Format (NDEF)",
1926 void *argtable
[] = {
1930 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1933 bool activate_field
= true;
1934 bool keep_field_on
= true;
1935 uint8_t response
[PM3_CMD_DATA_SIZE
];
1938 // --------------- Select NDEF Tag application ----------------
1939 uint8_t aSELECT_AID
[80];
1940 int aSELECT_AID_n
= 0;
1941 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
1942 int res
= exchange_14b_apdu(aSELECT_AID
, aSELECT_AID_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
, -1);
1952 uint16_t sw
= get_sw(response
, resplen
);
1954 PrintAndLogEx(ERR
, "Selecting NDEF aid failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
1959 activate_field
= false;
1960 keep_field_on
= true;
1961 // --------------- Send CC select ----------------
1962 // --------------- Read binary ----------------
1964 // --------------- NDEF file reading ----------------
1965 uint8_t aSELECT_FILE_NDEF
[30];
1966 int aSELECT_FILE_NDEF_n
= 0;
1967 param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF
, sizeof(aSELECT_FILE_NDEF
), &aSELECT_FILE_NDEF_n
);
1968 res
= exchange_14b_apdu(aSELECT_FILE_NDEF
, aSELECT_FILE_NDEF_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
, -1);
1972 sw
= get_sw(response
, resplen
);
1974 PrintAndLogEx(ERR
, "Selecting NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
1979 // --------------- Read binary ----------------
1980 uint8_t aREAD_NDEF
[30];
1981 int aREAD_NDEF_n
= 0;
1982 param_gethex_to_eol("00b0000002", 0, aREAD_NDEF
, sizeof(aREAD_NDEF
), &aREAD_NDEF_n
);
1983 res
= exchange_14b_apdu(aREAD_NDEF
, aREAD_NDEF_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
, -1);
1988 sw
= get_sw(response
, resplen
);
1990 PrintAndLogEx(ERR
, "reading NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
1994 // take offset from response
1995 uint8_t offset
= response
[1];
1997 // --------------- Read binary w offset ----------------
1998 keep_field_on
= false;
2000 param_gethex_to_eol("00b00002", 0, aREAD_NDEF
, sizeof(aREAD_NDEF
), &aREAD_NDEF_n
);
2001 aREAD_NDEF
[4] = offset
;
2002 res
= exchange_14b_apdu(aREAD_NDEF
, aREAD_NDEF_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
, -1);
2007 sw
= get_sw(response
, resplen
);
2009 PrintAndLogEx(ERR
, "reading NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2014 res
= NDEFRecordsDecodeAndPrint(response
+ 2, resplen
- 4);
2017 switch_off_field_14b();
2021 static command_t CommandTable
[] = {
2022 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
2023 {"apdu", CmdHF14BAPDU
, IfPm3Iso14443b
, "Send ISO 14443-4 APDU to tag"},
2024 {"dump", CmdHF14BDump
, IfPm3Iso14443b
, "Read all memory pages of an ISO-14443-B tag, save to file"},
2025 {"info", CmdHF14Binfo
, IfPm3Iso14443b
, "Tag information"},
2026 {"list", CmdHF14BList
, AlwaysAvailable
, "List ISO-14443-B history"},
2027 {"ndefread", CmdHF14BNdefRead
, IfPm3Iso14443b
, "Read NDEF file on tag"},
2028 {"raw", CmdHF14BCmdRaw
, IfPm3Iso14443b
, "Send raw hex data to tag"},
2029 {"reader", CmdHF14BReader
, IfPm3Iso14443b
, "Act as a ISO-14443-B reader to identify a tag"},
2030 // {"restore", CmdHF14BRestore, IfPm3Iso14443b, "Restore from file to all memory pages of an ISO-14443-B tag"},
2031 {"sim", CmdHF14BSim
, IfPm3Iso14443b
, "Fake ISO ISO-14443-B tag"},
2032 {"sniff", CmdHF14BSniff
, IfPm3Iso14443b
, "Eavesdrop ISO-14443-B"},
2033 {"rdbl", CmdHF14BSriRdBl
, IfPm3Iso14443b
, "Read SRI512/SRIX4x block"},
2034 {"sriwrite", CmdHF14BWriteSri
, IfPm3Iso14443b
, "Write data to a SRI512 or SRIX4K tag"},
2035 // {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"},
2036 {NULL
, NULL
, NULL
, NULL
}
2039 static int CmdHelp(const char *Cmd
) {
2040 (void)Cmd
; // Cmd is not used so far
2041 CmdsHelp(CommandTable
);
2045 int CmdHF14B(const char *Cmd
) {
2046 clearCommandBuffer();
2047 return CmdsParse(CommandTable
, Cmd
);
2050 // get and print all info known about any known 14b tag
2051 int infoHF14B(bool verbose
, bool do_aid_search
) {
2053 // try std 14b (atqb)
2054 if (HF14B_Std_Info(verbose
, do_aid_search
))
2058 if (HF14B_ST_Info(verbose
, do_aid_search
))
2061 // try unknown 14b read commands (to be identified later)
2062 // could be read of calypso, CEPAS, moneo, or pico pass.
2063 if (verbose
) PrintAndLogEx(FAILED
, "no 14443-B tag found");
2064 return PM3_EOPABORTED
;
2067 // get and print general info about all known 14b chips
2068 int readHF14B(bool loop
, bool verbose
) {
2070 // try std 14b (atqb)
2071 if (HF14B_std_reader(verbose
))
2074 // try ST Microelectronics 14b
2075 if (HF14B_st_reader(verbose
))
2079 if (HF14B_ask_ct_reader(verbose
))
2082 // try unknown 14b read commands (to be identified later)
2083 // could be read of calypso, CEPAS, moneo, or pico pass.
2084 if (HF14B_other_reader(verbose
))
2087 } while (loop
&& kbd_enter_pressed() == false);
2090 PrintAndLogEx(FAILED
, "no ISO 14443-B tag found");
2092 return PM3_EOPABORTED
;