style
[RRG-proxmark3.git] / client / src / cmdhfcryptorf.c
blob05524a6a0ce8d93dd42d90614c1905bc4c5322d4
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // High frequency CryptoRF commands (ISO14443B)
17 //-----------------------------------------------------------------------------
19 #include "cmdhfcryptorf.h"
21 #include <ctype.h>
22 #include "fileutils.h"
24 #include "cmdparser.h" // command_t
25 #include "comms.h" // clearCommandBuffer
26 #include "cmdtrace.h"
27 #include "crc16.h"
28 #include "protocols.h" // definitions of ISO14B protocol
29 #include "iso14b.h"
30 #include "cliparser.h" // cliparsing
32 #define TIMEOUT 2000
34 #ifndef CRYPTORF_MEM_SIZE
35 # define CRYPTORF_MEM_SIZE 1024
36 #endif
38 static int CmdHelp(const char *Cmd);
40 static iso14b_card_select_t last_known_card;
41 static void set_last_known_card(iso14b_card_select_t card) {
42 last_known_card = card;
45 static int switch_off_field_cryptorf(void) {
46 SetISODEPState(ISODEP_INACTIVE);
47 iso14b_raw_cmd_t packet = {
48 .flags = ISO14B_DISCONNECT,
49 .timeout = 0,
50 .rawlen = 0,
52 clearCommandBuffer();
53 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
54 return PM3_SUCCESS;
57 static int CmdHFCryptoRFList(const char *Cmd) {
58 return CmdTraceListAlias(Cmd, "hf cryptorf", "cryptorf");
61 static int CmdHFCryptoRFSim(const char *Cmd) {
62 CLIParserContext *ctx;
63 CLIParserInit(&ctx, "hf cryptorf sim",
64 "Simulate a CryptoRF tag\n"
65 _RED_("not implemented"),
66 "hf cryptorf sim");
68 void *argtable[] = {
69 arg_param_begin,
70 arg_param_end
72 CLIExecWithReturn(ctx, Cmd, argtable, false);
73 CLIParserFree(ctx);
75 clearCommandBuffer();
76 SendCommandNG(CMD_HF_CRYPTORF_SIM, NULL, 0);
77 return PM3_SUCCESS;
80 static int CmdHFCryptoRFSniff(const char *Cmd) {
81 CLIParserContext *ctx;
82 CLIParserInit(&ctx, "hf cryptorf sniff",
83 "Sniff the communication between reader and tag",
84 "hf cryptorf sniff\n"
87 void *argtable[] = {
88 arg_param_begin,
89 arg_param_end
91 CLIExecWithReturn(ctx, Cmd, argtable, true);
92 CLIParserFree(ctx);
94 clearCommandBuffer();
95 SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0);
96 PacketResponseNG resp;
97 WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp);
99 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog");
100 PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing");
101 return PM3_SUCCESS;
104 static bool get_14b_UID(iso14b_card_select_t *card) {
106 if (card == NULL)
107 return false;
109 int8_t retry = 3;
110 while (retry--) {
112 iso14b_raw_cmd_t packet = {
113 .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT),
114 .timeout = 0,
115 .rawlen = 0,
117 clearCommandBuffer();
118 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
119 PacketResponseNG resp;
120 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
121 if (resp.status == PM3_SUCCESS) {
122 memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
123 return true;
126 } // retry
128 if (retry <= 0) {
129 PrintAndLogEx(FAILED, "command execution time out");
132 return false;
135 // Print extended information about tag.
136 static int infoHFCryptoRF(bool verbose) {
137 iso14b_raw_cmd_t packet = {
138 .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT),
139 .timeout = 0,
140 .rawlen = 0,
142 // 14b get and print UID only (general info)
143 clearCommandBuffer();
144 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
145 PacketResponseNG resp;
146 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) {
147 if (verbose) {
148 PrintAndLogEx(WARNING, "command execution time out");
150 switch_off_field_cryptorf();
151 return false;
154 switch (resp.status) {
155 case PM3_SUCCESS: {
156 iso14b_card_select_t card;
157 memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
158 PrintAndLogEx(NORMAL, "");
159 PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen));
160 PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb)));
161 PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid);
162 return PM3_SUCCESS;
164 case PM3_ELENGTH:
165 if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
166 break;
167 case PM3_ECRC:
168 if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
169 break;
170 default:
171 if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed");
172 break;
174 return PM3_ESOFT;
177 static int CmdHFCryptoRFInfo(const char *Cmd) {
178 CLIParserContext *ctx;
179 CLIParserInit(&ctx, "hf cryptorf info",
180 "Act as a CryptoRF reader.",
181 "hf cryptorf info");
183 void *argtable[] = {
184 arg_param_begin,
185 arg_lit0("v", "verbose", "verbose output"),
186 arg_param_end
188 CLIExecWithReturn(ctx, Cmd, argtable, true);
189 bool verbose = arg_get_lit(ctx, 1);
190 CLIParserFree(ctx);
191 int res = infoHFCryptoRF(verbose);
192 if (res != PM3_SUCCESS && verbose) {
193 PrintAndLogEx(FAILED, "no CryptoRF / ISO14443-B tag found");
195 return res;
198 // get and print general info cryptoRF
199 int readHFCryptoRF(bool loop, bool verbose) {
201 int res = PM3_ESOFT;
202 do {
203 iso14b_raw_cmd_t packet = {
204 .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT),
205 .timeout = 0,
206 .rawlen = 0,
208 clearCommandBuffer();
209 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t));
210 PacketResponseNG resp;
211 if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
213 if (loop) {
214 if (resp.status != PM3_SUCCESS) {
215 continue;
217 } else {
218 // when not in continuous mode
219 if (resp.status != PM3_SUCCESS) {
220 if (verbose) {
221 PrintAndLogEx(WARNING, "cryptoRF / ISO14443-b card select failed");
223 res = PM3_EOPABORTED;
224 break;
228 iso14b_card_select_t card;
229 memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t));
230 PrintAndLogEx(NORMAL, "");
231 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex_inrow(card.uid, card.uidlen));
232 set_last_known_card(card);
234 } while (loop && kbd_enter_pressed() == false);
236 DropField();
237 return res;
240 static int CmdHFCryptoRFReader(const char *Cmd) {
241 CLIParserContext *ctx;
242 CLIParserInit(&ctx, "hf cryptorf reader",
243 "Act as a cryptoRF reader. Look for cryptoRF tags until Enter or the pm3 button is pressed",
244 "hf cryptorf reader -@ -> continuous reader mode"
247 void *argtable[] = {
248 arg_param_begin,
249 arg_lit0("@", NULL, "optional - continuous reader mode"),
250 arg_param_end
252 CLIExecWithReturn(ctx, Cmd, argtable, true);
253 bool cm = arg_get_lit(ctx, 1);
254 CLIParserFree(ctx);
256 if (cm) {
257 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
259 return readHFCryptoRF(cm, false);
262 // need to write to file
263 static int CmdHFCryptoRFDump(const char *Cmd) {
264 CLIParserContext *ctx;
265 CLIParserInit(&ctx, "hf cryptorf dump",
266 "Dump all memory from a CryptoRF tag (512/4096 bit size)",
267 "hf cryptorf dump\n"
270 void *argtable[] = {
271 arg_param_begin,
272 arg_str0("f", "file", "<fn>", "filename to save dump to"),
273 arg_lit0(NULL, "64", "64byte / 512bit memory"),
274 arg_lit0(NULL, "512", "512byte / 4096bit memory"),
275 arg_param_end
277 CLIExecWithReturn(ctx, Cmd, argtable, true);
278 int fnlen = 0;
279 char filename[FILE_PATH_SIZE] = {0};
280 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
282 bool m64 = arg_get_lit(ctx, 2);
283 bool m512 = arg_get_lit(ctx, 3);
284 CLIParserFree(ctx);
286 if (m512 + m64 != 1) {
287 PrintAndLogEx(INFO, "Select only one card memory size");
288 return PM3_EINVARG;
291 uint16_t cardsize;
292 uint8_t blocks = 0;
293 if (m64) {
294 cardsize = (512 / 8) + 4;
295 blocks = 0x0F;
297 if (m512) {
298 cardsize = (4096 / 8) + 4;
299 blocks = 0x7F;
302 iso14b_card_select_t card;
303 if (get_14b_UID(&card) == false) {
304 PrintAndLogEx(WARNING, "No tag found.");
305 return PM3_SUCCESS;
308 // detect blocksize from card :)
309 PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
311 // select tag
312 iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t *)calloc(1, sizeof(iso14b_raw_cmd_t) + 2);
313 if (packet == NULL) {
314 PrintAndLogEx(FAILED, "failed to allocate memory");
315 return PM3_EMALLOC;
317 packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_SR);
318 packet->timeout = 0;
319 packet->rawlen = 0;
321 clearCommandBuffer();
322 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)packet, sizeof(iso14b_raw_cmd_t));
323 PacketResponseNG resp;
325 // select
326 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
327 if (resp.status != PM3_SUCCESS) {
328 PrintAndLogEx(FAILED, "failed to select %d]", resp.status);
329 free(packet);
330 return switch_off_field_cryptorf();
334 PrintAndLogEx(INFO, "." NOLF);
336 uint8_t data[cardsize];
337 memset(data, 0, sizeof(data));
338 uint16_t blocknum = 0;
340 for (int retry = 0; retry < 5; retry++) {
342 // set up the read command
343 packet->flags = (ISO14B_APPEND_CRC | ISO14B_RAW);
344 packet->rawlen = 2;
345 packet->raw[0] = ISO14443B_READ_BLK;
346 packet->raw[1] = blocknum & 0xFF;
348 clearCommandBuffer();
349 SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t *)&packet, sizeof(iso14b_raw_cmd_t) + 2);
350 if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) {
352 if (resp.status != PM3_SUCCESS) {
353 PrintAndLogEx(FAILED, "retrying one more time");
354 continue;
357 uint16_t len = resp.length;
358 uint8_t *recv = resp.data.asBytes;
360 if (check_crc(CRC_14443_B, recv, len) == false) {
361 PrintAndLogEx(FAILED, "crc fail, retrying one more time");
362 continue;
365 memcpy(data + (blocknum * 4), resp.data.asBytes, 4);
367 // last read
368 if (blocknum == 0xFF) {
369 break;
372 retry = 0;
373 blocknum++;
374 if (blocknum > blocks) {
375 // read config block
376 blocknum = 0xFF;
379 PrintAndLogEx(NORMAL, "." NOLF);
380 fflush(stdout);
383 free(packet);
385 PrintAndLogEx(NORMAL, "");
387 if (blocknum != 0xFF) {
388 PrintAndLogEx(FAILED, "dump failed");
389 return switch_off_field_cryptorf();
392 PrintAndLogEx(INFO, "block# | data | ascii");
393 PrintAndLogEx(INFO, "---------+--------------+----------");
395 for (int i = 0; i <= blocks; i++) {
396 PrintAndLogEx(INFO,
397 "%3d/0x%02X | %s | %s",
400 sprint_hex(data + (i * 4), 4),
401 sprint_ascii(data + (i * 4), 4)
404 PrintAndLogEx(INFO, "---------+--------------+----------");
405 PrintAndLogEx(NORMAL, "");
407 size_t datalen = (blocks + 1) * 4;
409 if (fnlen < 1) {
410 PrintAndLogEx(INFO, "Using UID as filename");
411 char *fptr = filename + snprintf(filename, sizeof(filename), "hf-cryptorf-");
412 FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen);
415 pm3_save_dump(filename, data, datalen, jsfCryptorf);
417 return switch_off_field_cryptorf();
420 static int CmdHFCryptoRFELoad(const char *Cmd) {
422 CLIParserContext *ctx;
423 CLIParserInit(&ctx, "hf cryptorf eload",
424 "Loads CryptoRF tag dump (bin/eml/json) into emulator memory on device",
425 "hf cryptorf eload -f hf-cryptorf-0102030405-dump.bin\n"
428 void *argtable[] = {
429 arg_param_begin,
430 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
431 arg_param_end
433 CLIExecWithReturn(ctx, Cmd, argtable, false);
434 int fnlen = 0;
435 char filename[FILE_PATH_SIZE] = {0};
436 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
437 CLIParserFree(ctx);
439 if (fnlen == 0) {
440 PrintAndLogEx(ERR, "Error: Please specify a filename");
441 return PM3_EINVARG;
444 size_t datalen = CRYPTORF_MEM_SIZE;
445 // set up buffer
446 uint8_t *data = calloc(datalen, sizeof(uint8_t));
447 if (data == NULL) {
448 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
449 return PM3_EMALLOC;
452 if (loadFile_safe(filename, ".bin", (void **)&data, &datalen) != PM3_SUCCESS) {
453 free(data);
454 PrintAndLogEx(WARNING, "Error, reading file");
455 return PM3_EFILE;
458 PrintAndLogEx(SUCCESS, "Uploading to emulator memory");
460 uint32_t bytes_sent = 0;
462 //Send to device
463 uint32_t bytes_remaining = bytes_read;
465 while (bytes_remaining > 0) {
466 uint32_t bytes_in_packet = MIN(PM3_CMD_DATA_SIZE, bytes_remaining);
467 if (bytes_in_packet == bytes_remaining) {
468 // Disable fast mode on last packet
469 g_conn.block_after_ACK = false;
471 clearCommandBuffer();
472 SendCommandMIX(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet);
473 bytes_remaining -= bytes_in_packet;
474 bytes_sent += bytes_in_packet;
477 free(data);
478 PrintAndLogEx(SUCCESS, "sent " _YELLOW_("%d") " bytes of data to device emulator memory", bytes_sent);
479 return PM3_SUCCESS;
482 static int CmdHFCryptoRFESave(const char *Cmd) {
484 CLIParserContext *ctx;
485 CLIParserInit(&ctx, "hf cryptorf esave",
486 "Save emulator memory to file (bin/json)\n"
487 "if filename is not supplied, UID will be used.",
488 "hf cryptorf esave\n"
489 "hf cryptorf esave -f filename"
491 void *argtable[] = {
492 arg_param_begin,
493 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
494 arg_param_end
496 CLIExecWithReturn(ctx, Cmd, argtable, true);
498 int fnlen = 0;
499 char filename[FILE_PATH_SIZE] = {0};
500 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
501 CLIParserFree(ctx);
503 size_t numofbytes = CRYPTORF_MEM_SIZE;
505 // set up buffer
506 uint8_t *data = calloc(numofbytes, sizeof(uint8_t));
507 if (data == NULL) {
508 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
509 return PM3_EMALLOC;
512 // download emulator memory
513 PrintAndLogEx(SUCCESS, "Reading emulator memory...");
514 if (GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false) == false) {
515 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
516 free(data);
517 return PM3_ETIMEOUT;
520 // user supplied filename?
521 if (fnlen < 1) {
522 PrintAndLogEx(INFO, "Using UID as filename");
523 char *fptr = filename + snprintf(filename, sizeof(filename), "hf-cryptorf-");
524 FillFileNameByUID(fptr, data, "-dump", 4);
527 pm3_save_dump(filename, data, numofbytes, jsfCryptorf);
528 free(data);
529 return PM3_SUCCESS;
532 static command_t CommandTable[] = {
533 {"help", CmdHelp, AlwaysAvailable, "This help"},
534 {"dump", CmdHFCryptoRFDump, IfPm3Iso14443b, "Read all memory pages of an CryptoRF tag, save to file"},
535 {"info", CmdHFCryptoRFInfo, IfPm3Iso14443b, "Tag information"},
536 {"list", CmdHFCryptoRFList, AlwaysAvailable, "List ISO 14443B history"},
537 {"reader", CmdHFCryptoRFReader, IfPm3Iso14443b, "Act as a CryptoRF reader to identify a tag"},
538 {"sim", CmdHFCryptoRFSim, IfPm3Iso14443b, "Fake CryptoRF tag"},
539 {"sniff", CmdHFCryptoRFSniff, IfPm3Iso14443b, "Eavesdrop CryptoRF"},
540 {"eload", CmdHFCryptoRFELoad, AlwaysAvailable, "Upload file into emulator memory"},
541 {"esave", CmdHFCryptoRFESave, AlwaysAvailable, "Save emulator memory to file"},
542 {NULL, NULL, NULL, NULL}
545 static int CmdHelp(const char *Cmd) {
546 (void)Cmd; // Cmd is not used so far
547 CmdsHelp(CommandTable);
548 return PM3_SUCCESS;
551 int CmdHFCryptoRF(const char *Cmd) {
552 clearCommandBuffer();
553 return CmdsParse(CommandTable, Cmd);