textual
[RRG-proxmark3.git] / client / src / cmdhf.c
blob8a7afeb2a1bdbeca3abbec7cd70fc29ea3892718
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // Merlok - 2017
4 // Doegox - 2019
5 // Iceman - 2019
6 // Piwi - 2019
7 //
8 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
9 // at your option, any later version. See the LICENSE.txt file for the text of
10 // the license.
11 //-----------------------------------------------------------------------------
12 // High frequency commands
13 //-----------------------------------------------------------------------------
14 #include "cmdhf.h"
16 #include <ctype.h> // tolower
17 #include "cmdparser.h" // command_t
18 #include "cliparser.h" // parse
19 #include "comms.h" // clearCommandBuffer
20 #include "lfdemod.h" // computeSignalProperties
21 #include "cmdhf14a.h" // ISO14443-A
22 #include "cmdhf14b.h" // ISO14443-B
23 #include "cmdhf15.h" // ISO15693
24 #include "cmdhfepa.h"
25 #include "cmdhfemrtd.h" // eMRTD
26 #include "cmdhflegic.h" // LEGIC
27 #include "cmdhficlass.h" // ICLASS
28 #include "cmdhfjooki.h" // MFU based Jooki
29 #include "cmdhfmf.h" // CLASSIC
30 #include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc
31 #include "cmdhfmfp.h" // Mifare Plus
32 #include "cmdhfmfdes.h" // DESFIRE
33 #include "cmdhftopaz.h" // TOPAZ
34 #include "cmdhffelica.h" // ISO18092 / FeliCa
35 #include "cmdhffido.h" // FIDO authenticators
36 #include "cmdhfcipurse.h" // CIPURSE transport cards
37 #include "cmdhfthinfilm.h" // Thinfilm
38 #include "cmdhflto.h" // LTO-CM
39 #include "cmdhfcryptorf.h" // CryptoRF
40 #include "cmdhfseos.h" // SEOS
41 #include "cmdhfst25ta.h" // ST25TA
42 #include "cmdhfwaveshare.h" // Waveshare
43 #include "cmdtrace.h" // trace list
44 #include "ui.h"
45 #include "proxgui.h"
46 #include "cmddata.h"
47 #include "graph.h"
48 #include "fpga.h"
50 static int CmdHelp(const char *Cmd);
52 int CmdHFSearch(const char *Cmd) {
54 CLIParserContext *ctx;
55 CLIParserInit(&ctx, "hf search",
56 "Will try to find a HF read out of the unknown tag.\n"
57 "Continues to search for all different HF protocols.",
58 "hf search"
60 void *argtable[] = {
61 arg_param_begin,
62 arg_lit0("v", "verbose", "verbose output"),
63 arg_param_end
65 CLIExecWithReturn(ctx, Cmd, argtable, true);
67 bool verbose = arg_get_lit(ctx, 1);
69 CLIParserFree(ctx);
71 int res = PM3_ESOFT;
73 PROMPT_CLEARLINE;
74 PrintAndLogEx(INPLACE, " Searching for ThinFilm tag...");
75 if (IfPm3NfcBarcode()) {
76 if (infoThinFilm(false) == PM3_SUCCESS) {
77 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Thinfilm tag") " found\n");
78 res = PM3_SUCCESS;
82 PROMPT_CLEARLINE;
83 PrintAndLogEx(INPLACE, " Searching for LTO-CM tag...");
84 if (IfPm3Iso14443a()) {
85 if (infoLTO(false) == PM3_SUCCESS) {
86 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LTO-CM tag") " found\n");
87 res = PM3_SUCCESS;
91 PROMPT_CLEARLINE;
92 PrintAndLogEx(INPLACE, " Searching for ISO14443-A tag...");
93 if (IfPm3Iso14443a()) {
94 if (infoHF14A(false, false, false) > 0) {
95 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-A tag") " found\n");
96 res = PM3_SUCCESS;
98 infoHF14A4Applications(verbose);
102 PROMPT_CLEARLINE;
103 PrintAndLogEx(INPLACE, " Searching for ISO15693 tag...");
104 if (IfPm3Iso15693()) {
105 if (readHF15Uid(false, false)) {
106 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 15693 tag") " found\n");
107 res = PM3_SUCCESS;
111 PROMPT_CLEARLINE;
112 PrintAndLogEx(INPLACE, " Searching for iCLASS / PicoPass tag...");
113 if (IfPm3Iclass()) {
114 if (read_iclass_csn(false, false) == PM3_SUCCESS) {
115 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iCLASS tag / PicoPass tag") " found\n");
116 res = PM3_SUCCESS;
120 PROMPT_CLEARLINE;
121 PrintAndLogEx(INPLACE, " Searching for LEGIC tag...");
122 if (IfPm3Legicrf()) {
123 if (readLegicUid(false, false) == PM3_SUCCESS) {
124 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC Prime tag") " found\n");
125 res = PM3_SUCCESS;
129 PROMPT_CLEARLINE;
130 PrintAndLogEx(INPLACE, " Searching for Topaz tag...");
131 if (IfPm3Iso14443a()) {
132 if (readTopazUid(false) == PM3_SUCCESS) {
133 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") " found\n");
134 res = PM3_SUCCESS;
138 // 14b is the longest test
139 PROMPT_CLEARLINE;
140 PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag...");
141 if (IfPm3Iso14443b()) {
142 if (readHF14B(false, false) == PM3_SUCCESS) {
143 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-B tag") " found\n");
144 res = PM3_SUCCESS;
148 PROMPT_CLEARLINE;
149 PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
150 if (IfPm3Felica()) {
151 if (read_felica_uid(false, false) == PM3_SUCCESS) {
152 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 18092 / FeliCa tag") " found\n");
153 res = PM3_SUCCESS;
159 PROMPT_CLEARLINE;
160 PrintAndLogEx(INPLACE, " Searching for CryptoRF tag...");
161 if (IfPm3Iso14443b()) {
162 if (readHFCryptoRF(false, false) == PM3_SUCCESS) {
163 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("CryptoRF tag") " found\n");
164 res = PM3_SUCCESS;
169 PROMPT_CLEARLINE;
170 if (res != PM3_SUCCESS) {
171 PrintAndLogEx(WARNING, _RED_("No known/supported 13.56 MHz tags found"));
172 res = PM3_ESOFT;
175 DropField();
176 return res;
179 int CmdHFTune(const char *Cmd) {
181 CLIParserContext *ctx;
182 CLIParserInit(&ctx, "hf tune",
183 "Continuously measure HF antenna tuning.\n"
184 "Press button or <Enter> to interrupt.",
185 "hf tune\n"
186 "hf tune --mix"
189 void *argtable[] = {
190 arg_param_begin,
191 arg_u64_0("n", "iter", "<dec>", "number of iterations (default: 0=infinite)"),
192 arg_lit0(NULL, "bar", "bar style"),
193 arg_lit0(NULL, "mix", "mixed style"),
194 arg_lit0(NULL, "value", "values style"),
195 arg_param_end
197 CLIExecWithReturn(ctx, Cmd, argtable, true);
198 uint32_t iter = arg_get_u32_def(ctx, 1, 0);
199 bool is_bar = arg_get_lit(ctx, 2);
200 bool is_mix = arg_get_lit(ctx, 3);
201 bool is_value = arg_get_lit(ctx, 4);
202 CLIParserFree(ctx);
204 if ((is_bar + is_mix + is_value) > 1) {
205 PrintAndLogEx(ERR, "Select only one output style");
206 return PM3_EINVARG;
209 barMode_t style = session.bar_mode;
210 if (is_bar)
211 style = STYLE_BAR;
212 if (is_mix)
213 style = STYLE_MIXED;
214 if (is_value)
215 style = STYLE_VALUE;
217 PrintAndLogEx(INFO, "Measuring HF antenna, click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit");
218 PacketResponseNG resp;
219 clearCommandBuffer();
221 uint8_t mode[] = {1};
222 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode));
223 if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) {
224 PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF initialization, aborting");
225 return PM3_ETIMEOUT;
228 mode[0] = 2;
230 uint32_t max = 0xFFFF;
231 bool first = true;
233 print_progress(0, max, style);
235 // loop forever (till button pressed) if iter = 0 (default)
236 for (uint8_t i = 0; iter == 0 || i < iter; i++) {
237 if (kbd_enter_pressed()) {
238 break;
241 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode));
242 if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) {
243 PrintAndLogEx(NORMAL, "");
244 PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF measure, aborting");
245 break;
248 if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint16_t))) {
249 PrintAndLogEx(NORMAL, "");
250 break;
253 uint16_t volt = resp.data.asDwords[0] & 0xFFFF;
254 if (first) {
255 max = (volt * 1.03);
256 first = false;
258 if (volt > max) {
259 max = (volt * 1.03);
261 print_progress(volt, max, style);
263 mode[0] = 3;
265 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_HF, mode, sizeof(mode));
266 if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_HF, &resp, 1000)) {
267 PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark HF shutdown, aborting");
268 return PM3_ETIMEOUT;
270 PrintAndLogEx(NORMAL, "\x1b%c[2K\r", 30);
271 PrintAndLogEx(INFO, "Done.");
272 return PM3_SUCCESS;
275 // Collects pars of u8,
276 // uses 16bit transfers from FPGA for speed
277 // Takes all available bigbuff memory
278 // data sample to download? Not sure what we can do with the data.
279 int CmdHFSniff(const char *Cmd) {
281 CLIParserContext *ctx;
282 CLIParserInit(&ctx, "hf sniff",
283 "The high frequency sniffer will assign all available memory on device for sniffed data.\n"
284 "Use `data samples` to download from device and `data plot` to visualize it.\n"
285 "Press button to quit the sniffing.",
286 "hf sniff\n"
287 "hf sniff --sp 1000 --st 0 -> skip 1000 pairs, skip 0 triggers"
289 void *argtable[] = {
290 arg_param_begin,
291 arg_u64_0(NULL, "sp", "<dec>", "skip sample pairs"),
292 arg_u64_0(NULL, "st", "<dec>", "skip number of triggers"),
293 arg_param_end
295 CLIExecWithReturn(ctx, Cmd, argtable, true);
297 struct {
298 uint32_t samplesToSkip;
299 uint32_t triggersToSkip;
300 } PACKED params;
302 params.samplesToSkip = arg_get_u32_def(ctx, 1, 0);
303 params.triggersToSkip = arg_get_u32_def(ctx, 2, 0);
304 CLIParserFree(ctx);
306 clearCommandBuffer();
307 SendCommandNG(CMD_HF_SNIFF, (uint8_t *)&params, sizeof(params));
309 for (;;) {
311 if (kbd_enter_pressed()) {
312 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
313 PrintAndLogEx(INFO, "User aborted");
314 break;
317 PacketResponseNG resp;
318 if (WaitForResponseTimeout(CMD_HF_SNIFF, &resp, 1000)) {
320 if (resp.status == PM3_EOPABORTED) {
321 PrintAndLogEx(INFO, "Button pressed, user aborted");
322 break;
324 if (resp.status == PM3_SUCCESS) {
326 struct r {
327 uint16_t len;
328 } PACKED;
329 struct r *retval = (struct r *)resp.data.asBytes;
331 PrintAndLogEx(INFO, "HF sniff (%u samples)", retval->len);
333 PrintAndLogEx(HINT, "Use `" _YELLOW_("data hpf") "` to remove offset");
334 PrintAndLogEx(HINT, "Use `" _YELLOW_("data plot") "` to view");
335 PrintAndLogEx(HINT, "Use `" _YELLOW_("data save") "` to save");
337 // download bigbuf_malloc:d.
338 // it reserve memory from the higher end.
339 // At the moment, sniff takes all free memory in bigbuff. If this changes,
340 // we can't start from beginning idx 0 but from that hi-to-start-of-allocated.
341 uint32_t start = pm3_capabilities.bigbuf_size - retval->len;
342 int res = getSamplesEx(start, start, false);
343 if (res != PM3_SUCCESS) {
344 PrintAndLogEx(WARNING, "failed to download samples to client");
345 return res;
347 break;
351 PrintAndLogEx(INFO, "Done.");
352 return PM3_SUCCESS;
355 int handle_hf_plot(void) {
357 uint8_t buf[FPGA_TRACE_SIZE];
359 PacketResponseNG response;
360 if (!GetFromDevice(FPGA_MEM, buf, FPGA_TRACE_SIZE, 0, NULL, 0, &response, 4000, true)) {
361 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
362 return PM3_ETIMEOUT;
365 for (size_t i = 0; i < FPGA_TRACE_SIZE; i++) {
366 GraphBuffer[i] = ((int)buf[i]) - 128;
369 GraphTraceLen = FPGA_TRACE_SIZE;
371 ShowGraphWindow();
373 // remove signal offset
374 CmdHpf("");
376 setClockGrid(0, 0);
377 DemodBufferLen = 0;
378 RepaintGraphWindow();
379 return PM3_SUCCESS;
382 int CmdHFPlot(const char *Cmd) {
383 CLIParserContext *ctx;
384 CLIParserInit(&ctx, "hf plot",
385 "Plots HF signal after RF signal path and A/D conversion.",
386 "This can be used after any hf command and will show the last few milliseconds of the HF signal.\n"
387 "Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n");
388 void *argtable[] = {
389 arg_param_begin,
390 arg_param_end
392 CLIExecWithReturn(ctx, Cmd, argtable, true);
393 CLIParserFree(ctx);
395 return handle_hf_plot();
398 static int CmdHFList(const char *Cmd) {
399 return CmdTraceListAlias(Cmd, "hf", "raw");
402 static command_t CommandTable[] = {
404 {"--------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("High Frequency") " -----------------------"},
405 {"14a", CmdHF14A, AlwaysAvailable, "{ ISO14443A RFIDs... }"},
406 {"14b", CmdHF14B, AlwaysAvailable, "{ ISO14443B RFIDs... }"},
407 {"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"},
408 // {"cryptorf", CmdHFCryptoRF, AlwaysAvailable, "{ CryptoRF RFIDs... }"},
409 {"cipurse", CmdHFCipurse, AlwaysAvailable, "{ Cipurse transport Cards... }"},
410 {"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"},
411 {"emrtd", CmdHFeMRTD, AlwaysAvailable, "{ Machine Readable Travel Document... }"},
412 {"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / FeliCa RFIDs... }"},
413 {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"},
414 {"jooki", CmdHF_Jooki, AlwaysAvailable, "{ Jooki RFIDs... }"},
415 {"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"},
416 {"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"},
417 {"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"},
418 {"mf", CmdHFMF, AlwaysAvailable, "{ MIFARE RFIDs... }"},
419 {"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"},
420 {"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"},
421 {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"},
422 {"seos", CmdHFSeos, AlwaysAvailable, "{ SEOS RFIDs... }"},
423 {"st25ta", CmdHFST25TA, AlwaysAvailable, "{ ST25TA RFIDs... }"},
424 {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"},
425 {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"},
426 {"waveshare", CmdHFWaveshare, AlwaysAvailable, "{ Waveshare NFC ePaper... }"},
427 {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
428 {"help", CmdHelp, AlwaysAvailable, "This help"},
429 {"list", CmdHFList, AlwaysAvailable, "List protocol data in trace buffer"},
430 {"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"},
431 {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"},
432 {"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"},
433 {"sniff", CmdHFSniff, IfPm3Hfsniff, "Generic HF Sniff"},
434 {NULL, NULL, NULL, NULL}
437 int CmdHF(const char *Cmd) {
438 clearCommandBuffer();
439 return CmdsParse(CommandTable, Cmd);
442 int CmdHelp(const char *Cmd) {
443 (void)Cmd; // Cmd is not used so far
444 CmdsHelp(CommandTable);
445 return PM3_SUCCESS;