fix little endian vs big endian in the macros... again... but this time correct
[RRG-proxmark3.git] / client / src / cmdhfcryptorf.c
blobbbfb00c0ef3f87b4f43d1c53083d2a434e68938c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2020 iceman
3 //
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
6 // the license.
7 //-----------------------------------------------------------------------------
8 // High frequency CryptoRF commands (ISO14443B)
9 //-----------------------------------------------------------------------------
11 #include "cmdhfcryptorf.h"
13 #include <ctype.h>
14 #include "fileutils.h"
16 #include "cmdparser.h" // command_t
17 #include "comms.h" // clearCommandBuffer
18 #include "cmdtrace.h"
19 #include "crc16.h"
20 #include "protocols.h" // definitions of ISO14B protocol
21 #include "iso14b.h"
22 #include "cliparser.h" // cliparsing
24 #define TIMEOUT 2000
26 #ifndef CRYPTORF_MEM_SIZE
27 # define CRYPTORF_MEM_SIZE 1024
28 #endif
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,
41 .timeout = 0,
42 .rawlen = 0,
44 clearCommandBuffer();
45 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
46 return PM3_SUCCESS;
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"),
58 "hf cryptorf sim");
60 void *argtable[] = {
61 arg_param_begin,
62 arg_param_end
64 CLIExecWithReturn(ctx, Cmd, argtable, false);
65 CLIParserFree(ctx);
67 clearCommandBuffer();
68 SendCommandNG(CMD_HF_CRYPTORF_SIM, NULL, 0);
69 return PM3_SUCCESS;
72 static int CmdHFCryptoRFSniff(const char *Cmd) {
73 CLIParserContext *ctx;
74 CLIParserInit(&ctx, "hf cryptorf sniff",
75 "Sniff the communication reader and tag",
76 "hf cryptorf sniff\n"
79 void *argtable[] = {
80 arg_param_begin,
81 arg_param_end
83 CLIExecWithReturn(ctx, Cmd, argtable, true);
84 CLIParserFree(ctx);
86 clearCommandBuffer();
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");
91 return PM3_SUCCESS;
94 static bool get_14b_UID(iso14b_card_select_t *card) {
96 if (card == NULL)
97 return false;
99 int8_t retry = 3;
100 while (retry--) {
102 iso14b_raw_cmd_t packet = {
103 .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT),
104 .timeout = 0,
105 .rawlen = 0,
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));
113 return true;
116 } // retry
118 if (retry <= 0)
119 PrintAndLogEx(FAILED, "command execution timeout");
121 return false;
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),
128 .timeout = 0,
129 .rawlen = 0,
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) {
136 if (verbose) {
137 PrintAndLogEx(WARNING, "command execution timeout");
139 switch_off_field_cryptorf();
140 return false;
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];
148 switch (status) {
149 case 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);
154 return PM3_SUCCESS;
155 case 2:
156 if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
157 break;
158 case 3:
159 if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
160 break;
161 default:
162 if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed");
163 break;
165 return PM3_ESOFT;
168 static int CmdHFCryptoRFInfo(const char *Cmd) {
169 CLIParserContext *ctx;
170 CLIParserInit(&ctx, "hf cryptorf info",
171 "Act as a CryptoRF reader.",
172 "hf cryptorf info");
174 void *argtable[] = {
175 arg_param_begin,
176 arg_lit0("v", "verbose", "verbose output"),
177 arg_param_end
179 CLIExecWithReturn(ctx, Cmd, argtable, true);
180 bool verbose = arg_get_lit(ctx, 1);
181 CLIParserFree(ctx);
182 int res = infoHFCryptoRF(verbose);
183 if (res != PM3_SUCCESS && verbose) {
184 PrintAndLogEx(FAILED, "no CryptoRF / ISO14443-B tag found");
186 return res;
189 // get and print general info cryptoRF
190 int readHFCryptoRF(bool loop, bool verbose) {
192 int res = PM3_ESOFT;
193 do {
194 iso14b_raw_cmd_t packet = {
195 .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT),
196 .timeout = 0,
197 .rawlen = 0,
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;
206 if (loop) {
207 if (status != 0) {
208 continue;
210 } else {
211 // when not in continuous mode
212 if (status != 0) {
213 if (verbose) PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed");
214 res = PM3_EOPABORTED;
215 break;
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);
227 DropField();
228 return res;
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"
238 void *argtable[] = {
239 arg_param_begin,
240 arg_lit0("@", NULL, "optional - continuous reader mode"),
241 arg_param_end
243 CLIExecWithReturn(ctx, Cmd, argtable, true);
244 bool cm = arg_get_lit(ctx, 1);
245 CLIParserFree(ctx);
247 if (cm) {
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)",
258 "hf cryptorf dump\n"
261 void *argtable[] = {
262 arg_param_begin,
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"),
266 arg_param_end
268 CLIExecWithReturn(ctx, Cmd, argtable, true);
269 int fnlen = 0;
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);
275 CLIParserFree(ctx);
277 if (m512 + m64 > 1) {
278 PrintAndLogEx(INFO, "Select only one card memory size");
279 return PM3_EINVARG;
282 uint16_t cardsize = 0;
283 uint8_t blocks = 0;
284 if (m64) {
285 cardsize = (512 / 8) + 4;
286 blocks = 0x0F;
288 if (m512) {
289 cardsize = (4096 / 8) + 4;
290 blocks = 0x7F;
293 iso14b_card_select_t card;
294 if (get_14b_UID(&card) == false) {
295 PrintAndLogEx(WARNING, "No tag found.");
296 return PM3_SUCCESS;
299 // detect blocksize from card :)
300 PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
302 // select tag
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");
306 return PM3_EMALLOC;
308 packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_SR);
309 packet->timeout = 0;
310 packet->rawlen = 0;
312 clearCommandBuffer();
313 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t));
314 PacketResponseNG resp;
316 // select
317 int status = 0;
318 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
319 status = resp.oldarg[0];
320 if (status < 0) {
321 PrintAndLogEx(FAILED, "failed to select %" PRId64 "]", resp.oldarg[0]);
322 free(packet);
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);
337 packet->rawlen = 2;
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];
346 if (status < 0) {
347 PrintAndLogEx(FAILED, "retrying one more time");
348 continue;
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");
356 continue;
359 memcpy(data + (blocknum * 4), resp.data.asBytes, 4);
361 // last read
362 if (blocknum == 0xFF) {
363 break;
366 retry = 0;
367 blocknum++;
368 if (blocknum > blocks) {
369 // read config block
370 blocknum = 0xFF;
373 PrintAndLogEx(NORMAL, "." NOLF);
374 fflush(stdout);
377 free(packet);
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++) {
390 PrintAndLogEx(INFO,
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;
403 if (fnlen < 1) {
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);
412 // json?
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"
424 void *argtable[] = {
425 arg_param_begin,
426 arg_str1("f", "file", "<filename>", "filename of dump"),
427 arg_param_end
429 CLIExecWithReturn(ctx, Cmd, argtable, false);
430 int fnlen = 0;
431 char filename[FILE_PATH_SIZE] = {0};
432 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
433 CLIParserFree(ctx);
435 if (fnlen == 0) {
436 PrintAndLogEx(ERR, "Error: Please specify a filename");
437 return PM3_EINVARG;
440 size_t datalen = CRYPTORF_MEM_SIZE;
441 // set up buffer
442 uint8_t *data = calloc(datalen, sizeof(uint8_t));
443 if (!data) {
444 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
445 return PM3_EMALLOC;
448 if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) {
449 free(data);
450 PrintAndLogEx(WARNING, "Error, reading file");
451 return PM3_EFILE;
454 PrintAndLogEx(SUCCESS, "Uploading to emulator memory");
456 uint32_t bytes_sent = 0;
458 //Send to device
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;
473 free(data);
474 PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent);
475 return PM3_SUCCESS;
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"
487 void *argtable[] = {
488 arg_param_begin,
489 arg_str0("f", "file", "<filename>", "filename of dumpfile"),
490 arg_param_end
492 CLIExecWithReturn(ctx, Cmd, argtable, true);
494 int fnlen = 0;
495 char filename[FILE_PATH_SIZE] = {0};
496 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
497 CLIParserFree(ctx);
499 size_t numofbytes = CRYPTORF_MEM_SIZE;
501 // set up buffer
502 uint8_t *data = calloc(numofbytes, sizeof(uint8_t));
503 if (data == NULL) {
504 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
505 return PM3_EMALLOC;
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");
512 free(data);
513 return PM3_ETIMEOUT;
516 // user supplied filename?
517 if (fnlen < 1) {
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);
525 //needs to change
526 saveFileEML(filename, data, numofbytes, 8);
527 //needs to change
528 saveFileJSON(filename, jsfRaw, data, numofbytes, NULL);
529 free(data);
530 return PM3_SUCCESS;
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);
549 return PM3_SUCCESS;
552 int CmdHFCryptoRF(const char *Cmd) {
553 clearCommandBuffer();
554 return CmdsParse(CommandTable, Cmd);