1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2020 iceman
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 CryptoRF commands (ISO14443B)
9 //-----------------------------------------------------------------------------
11 #include "cmdhfcryptorf.h"
14 #include "fileutils.h"
16 #include "cmdparser.h" // command_t
17 #include "comms.h" // clearCommandBuffer
20 #include "protocols.h" // definitions of ISO14B protocol
22 #include "cliparser.h" // cliparsing
26 #ifndef CRYPTORF_MEM_SIZE
27 # define CRYPTORF_MEM_SIZE 1024
30 static int CmdHelp(const char *Cmd
);
32 static iso14b_card_select_t last_known_card
;
33 static void set_last_known_card(iso14b_card_select_t card
) {
34 last_known_card
= card
;
37 static int switch_off_field_cryptorf(void) {
38 SetISODEPState(ISODEP_INACTIVE
);
39 iso14b_raw_cmd_t packet
= {
40 .flags
= ISO14B_DISCONNECT
,
45 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
49 static int CmdHFCryptoRFList(const char *Cmd
) {
50 return CmdTraceListAlias(Cmd
, "hf cryptorf", "cryptorf");
53 static int CmdHFCryptoRFSim(const char *Cmd
) {
54 CLIParserContext
*ctx
;
55 CLIParserInit(&ctx
, "hf cryptorf sim",
56 "Simulate a CryptoRF tag\n"
57 _RED_("not implemented"),
64 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
68 SendCommandNG(CMD_HF_CRYPTORF_SIM
, NULL
, 0);
72 static int CmdHFCryptoRFSniff(const char *Cmd
) {
73 CLIParserContext
*ctx
;
74 CLIParserInit(&ctx
, "hf cryptorf sniff",
75 "Sniff the communication reader and tag",
83 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
87 SendCommandNG(CMD_HF_ISO14443B_SNIFF
, NULL
, 0);
89 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog");
90 PrintAndLogEx(HINT
, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing");
94 static bool get_14b_UID(iso14b_card_select_t
*card
) {
102 iso14b_raw_cmd_t packet
= {
103 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_DISCONNECT
),
107 clearCommandBuffer();
108 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
109 PacketResponseNG resp
;
110 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
)) {
111 if (resp
.oldarg
[0] == 0) {
112 memcpy(card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
119 PrintAndLogEx(FAILED
, "command execution timeout");
124 // Print extented information about tag.
125 static int infoHFCryptoRF(bool verbose
) {
126 iso14b_raw_cmd_t packet
= {
127 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_DISCONNECT
),
131 // 14b get and print UID only (general info)
132 clearCommandBuffer();
133 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
134 PacketResponseNG resp
;
135 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, TIMEOUT
) == false) {
137 PrintAndLogEx(WARNING
, "command execution timeout");
139 switch_off_field_cryptorf();
143 iso14b_card_select_t card
;
144 memcpy(&card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
146 uint64_t status
= resp
.oldarg
[0];
150 PrintAndLogEx(NORMAL
, "");
151 PrintAndLogEx(SUCCESS
, " UID : %s", sprint_hex(card
.uid
, card
.uidlen
));
152 PrintAndLogEx(SUCCESS
, " ATQB : %s", sprint_hex(card
.atqb
, sizeof(card
.atqb
)));
153 PrintAndLogEx(SUCCESS
, " CHIPID : %02X", card
.chipid
);
156 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 ATTRIB fail");
159 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-3 CRC fail");
162 if (verbose
) PrintAndLogEx(FAILED
, "ISO 14443-b card select failed");
168 static int CmdHFCryptoRFInfo(const char *Cmd
) {
169 CLIParserContext
*ctx
;
170 CLIParserInit(&ctx
, "hf cryptorf info",
171 "Act as a CryptoRF reader.",
176 arg_lit0("v", "verbose", "verbose output"),
179 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
180 bool verbose
= arg_get_lit(ctx
, 1);
182 int res
= infoHFCryptoRF(verbose
);
183 if (res
!= PM3_SUCCESS
&& verbose
) {
184 PrintAndLogEx(FAILED
, "no CryptoRF / ISO14443-B tag found");
189 // get and print general info cryptoRF
190 int readHFCryptoRF(bool loop
, bool verbose
) {
194 iso14b_raw_cmd_t packet
= {
195 .flags
= (ISO14B_CONNECT
| ISO14B_SELECT_STD
| ISO14B_DISCONNECT
),
199 clearCommandBuffer();
200 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
));
201 PacketResponseNG resp
;
202 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000)) {
204 uint8_t status
= resp
.oldarg
[0] & 0xFF;
211 // when not in continuous mode
213 if (verbose
) PrintAndLogEx(WARNING
, "cryptoRF / ISO14443-b card select failed");
214 res
= PM3_EOPABORTED
;
219 iso14b_card_select_t card
;
220 memcpy(&card
, (iso14b_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14b_card_select_t
));
221 PrintAndLogEx(NORMAL
, "");
222 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex_inrow(card
.uid
, card
.uidlen
));
223 set_last_known_card(card
);
225 } while (loop
&& kbd_enter_pressed() == false);
231 static int CmdHFCryptoRFReader(const char *Cmd
) {
232 CLIParserContext
*ctx
;
233 CLIParserInit(&ctx
, "hf cryptorf reader",
234 "Act as a cryptoRF reader. Look for cryptoRF tags until Enter or the pm3 button is pressed",
235 "hf cryptorf reader -@ -> continuous reader mode"
240 arg_lit0("@", NULL
, "optional - continuous reader mode"),
243 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
244 bool cm
= arg_get_lit(ctx
, 1);
248 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
250 return readHFCryptoRF(cm
, false);
253 // need to write to file
254 static int CmdHFCryptoRFDump(const char *Cmd
) {
255 CLIParserContext
*ctx
;
256 CLIParserInit(&ctx
, "hf cryptorf dump",
257 "Dump all memory from a CryptoRF tag (512/4096 bit size)",
263 arg_str0("f", "file", "<filename>", "filename to save dump to"),
264 arg_lit0(NULL
, "64", "64byte / 512bit memory"),
265 arg_lit0(NULL
, "512", "512byte / 4096bit memory"),
268 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
270 char filename
[FILE_PATH_SIZE
] = {0};
271 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
273 bool m64
= arg_get_lit(ctx
, 2);
274 bool m512
= arg_get_lit(ctx
, 3);
277 if (m512
+ m64
> 1) {
278 PrintAndLogEx(INFO
, "Select only one card memory size");
282 uint16_t cardsize
= 0;
285 cardsize
= (512 / 8) + 4;
289 cardsize
= (4096 / 8) + 4;
293 iso14b_card_select_t card
;
294 if (get_14b_UID(&card
) == false) {
295 PrintAndLogEx(WARNING
, "No tag found.");
299 // detect blocksize from card :)
300 PrintAndLogEx(INFO
, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
303 iso14b_raw_cmd_t
*packet
= (iso14b_raw_cmd_t
*)calloc(1, sizeof(iso14b_raw_cmd_t
) + 2);
304 if (packet
== NULL
) {
305 PrintAndLogEx(FAILED
, "failed to allocate memory");
308 packet
->flags
= (ISO14B_CONNECT
| ISO14B_SELECT_SR
);
312 clearCommandBuffer();
313 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)packet
, sizeof(iso14b_raw_cmd_t
));
314 PacketResponseNG resp
;
318 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, 2000)) {
319 status
= resp
.oldarg
[0];
321 PrintAndLogEx(FAILED
, "failed to select %" PRId64
"]", resp
.oldarg
[0]);
323 return switch_off_field_cryptorf();
327 PrintAndLogEx(INFO
, "." NOLF
);
329 uint8_t data
[cardsize
];
330 memset(data
, 0, sizeof(data
));
331 uint16_t blocknum
= 0;
333 for (int retry
= 0; retry
< 5; retry
++) {
335 // set up the read command
336 packet
->flags
= (ISO14B_APPEND_CRC
| ISO14B_RAW
);
338 packet
->raw
[0] = ISO14443B_READ_BLK
;
339 packet
->raw
[1] = blocknum
& 0xFF;
341 clearCommandBuffer();
342 SendCommandNG(CMD_HF_ISO14443B_COMMAND
, (uint8_t *)&packet
, sizeof(iso14b_raw_cmd_t
) + 2);
343 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND
, &resp
, 2000)) {
345 status
= resp
.oldarg
[0];
347 PrintAndLogEx(FAILED
, "retrying one more time");
351 uint16_t len
= (resp
.oldarg
[1] & 0xFFFF);
352 uint8_t *recv
= resp
.data
.asBytes
;
354 if (check_crc(CRC_14443_B
, recv
, len
) == false) {
355 PrintAndLogEx(FAILED
, "crc fail, retrying one more time");
359 memcpy(data
+ (blocknum
* 4), resp
.data
.asBytes
, 4);
362 if (blocknum
== 0xFF) {
368 if (blocknum
> blocks
) {
373 PrintAndLogEx(NORMAL
, "." NOLF
);
379 PrintAndLogEx(NORMAL
, "");
381 if (blocknum
!= 0xFF) {
382 PrintAndLogEx(FAILED
, "dump failed");
383 return switch_off_field_cryptorf();
386 PrintAndLogEx(INFO
, "block# | data | ascii");
387 PrintAndLogEx(INFO
, "---------+--------------+----------");
389 for (int i
= 0; i
<= blocks
; i
++) {
391 "%3d/0x%02X | %s | %s",
394 sprint_hex(data
+ (i
* 4), 4),
395 sprint_ascii(data
+ (i
* 4), 4)
398 PrintAndLogEx(INFO
, "---------+--------------+----------");
399 PrintAndLogEx(NORMAL
, "");
401 size_t datalen
= (blocks
+ 1) * 4;
404 PrintAndLogEx(INFO
, "Using UID as filename");
405 char *fptr
= filename
;
406 fptr
+= sprintf(fptr
, "hf-cryptorf-");
407 FillFileNameByUID(fptr
, card
.uid
, "-dump", card
.uidlen
);
410 saveFileEML(filename
, data
, datalen
, 4);
411 saveFile(filename
, ".bin", data
, datalen
);
413 return switch_off_field_cryptorf();
416 static int CmdHFCryptoRFELoad(const char *Cmd
) {
418 CLIParserContext
*ctx
;
419 CLIParserInit(&ctx
, "hf cryptorf eload",
420 "Loads CryptoRF tag dump into emulator memory on device",
421 "hf cryptorf eload -f hf-cryptorf-0102030405-dump.bin\n"
426 arg_str1("f", "file", "<filename>", "filename of dump"),
429 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
431 char filename
[FILE_PATH_SIZE
] = {0};
432 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
436 PrintAndLogEx(ERR
, "Error: Please specify a filename");
440 size_t datalen
= CRYPTORF_MEM_SIZE
;
442 uint8_t *data
= calloc(datalen
, sizeof(uint8_t));
444 PrintAndLogEx(WARNING
, "Fail, cannot allocate memory");
448 if (loadFile_safe(filename
, ".bin", (void **)&data
, &datalen
) != PM3_SUCCESS
) {
450 PrintAndLogEx(WARNING
, "Error, reading file");
454 PrintAndLogEx(SUCCESS
, "Uploading to emulator memory");
456 uint32_t bytes_sent
= 0;
459 uint32_t bytes_remaining = bytes_read;
461 while (bytes_remaining > 0) {
462 uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining);
463 if (bytes_in_packet == bytes_remaining) {
464 // Disable fast mode on last packet
465 conn.block_after_ACK = false;
467 clearCommandBuffer();
468 SendCommandMIX(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
469 bytes_remaining -= bytes_in_packet;
470 bytes_sent += bytes_in_packet;
474 PrintAndLogEx(SUCCESS
, "sent %d bytes of data to device emulator memory", bytes_sent
);
478 static int CmdHFCryptoRFESave(const char *Cmd
) {
480 CLIParserContext
*ctx
;
481 CLIParserInit(&ctx
, "hf cryptorf esave",
482 "Save emulator memory to bin/eml/json file\n"
483 "if filename is not supplied, UID will be used.",
484 "hf cryptorf esave\n"
485 "hf cryptorf esave -f filename"
489 arg_str0("f", "file", "<filename>", "filename of dumpfile"),
492 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
495 char filename
[FILE_PATH_SIZE
] = {0};
496 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
499 size_t numofbytes
= CRYPTORF_MEM_SIZE
;
502 uint8_t *data
= calloc(numofbytes
, sizeof(uint8_t));
504 PrintAndLogEx(WARNING
, "Fail, cannot allocate memory");
508 // download emulator memory
509 PrintAndLogEx(SUCCESS
, "Reading emulator memory...");
510 if (GetFromDevice(BIG_BUF_EML
, data
, numofbytes
, 0, NULL
, 0, NULL
, 2500, false) == false) {
511 PrintAndLogEx(WARNING
, "Fail, transfer from device time-out");
516 // user supplied filename?
518 PrintAndLogEx(INFO
, "Using UID as filename");
519 char *fptr
= filename
;
520 fptr
+= sprintf(fptr
, "hf-cryptorf-");
521 FillFileNameByUID(fptr
, data
, "-dump", 4);
524 saveFile(filename
, ".bin", data
, numofbytes
);
526 saveFileEML(filename
, data
, numofbytes
, 8);
528 saveFileJSON(filename
, jsfRaw
, data
, numofbytes
, NULL
);
533 static command_t CommandTable
[] = {
534 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
535 {"dump", CmdHFCryptoRFDump
, IfPm3Iso14443b
, "Read all memory pages of an CryptoRF tag, save to file"},
536 {"info", CmdHFCryptoRFInfo
, IfPm3Iso14443b
, "Tag information"},
537 {"list", CmdHFCryptoRFList
, AlwaysAvailable
, "List ISO 14443B history"},
538 {"reader", CmdHFCryptoRFReader
, IfPm3Iso14443b
, "Act as a CryptoRF reader to identify a tag"},
539 {"sim", CmdHFCryptoRFSim
, IfPm3Iso14443b
, "Fake CryptoRF tag"},
540 {"sniff", CmdHFCryptoRFSniff
, IfPm3Iso14443b
, "Eavesdrop CryptoRF"},
541 {"eload", CmdHFCryptoRFELoad
, AlwaysAvailable
, "Load binary dump to emulator memory"},
542 {"esave", CmdHFCryptoRFESave
, AlwaysAvailable
, "Save emulator memory to binary file"},
543 {NULL
, NULL
, NULL
, NULL
}
546 static int CmdHelp(const char *Cmd
) {
547 (void)Cmd
; // Cmd is not used so far
548 CmdsHelp(CommandTable
);
552 int CmdHFCryptoRF(const char *Cmd
) {
553 clearCommandBuffer();
554 return CmdsParse(CommandTable
, Cmd
);