1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
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
11 //-----------------------------------------------------------------------------
12 // High frequency commands
13 //-----------------------------------------------------------------------------
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
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
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.",
62 arg_lit0("v", "verbose", "verbose output"),
65 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
67 bool verbose
= arg_get_lit(ctx
, 1);
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");
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");
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");
98 infoHF14A4Applications(verbose
);
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");
112 PrintAndLogEx(INPLACE
, " Searching for iCLASS / PicoPass tag...");
114 if (read_iclass_csn(false, false) == PM3_SUCCESS
) {
115 PrintAndLogEx(SUCCESS
, "\nValid " _GREEN_("iCLASS tag / PicoPass tag") " found\n");
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");
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");
138 // 14b is the longest test
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");
149 PrintAndLogEx(INPLACE
, " Searching for FeliCa tag...");
151 if (read_felica_uid(false, false) == PM3_SUCCESS
) {
152 PrintAndLogEx(SUCCESS
, "\nValid " _GREEN_("ISO 18092 / FeliCa tag") " found\n");
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");
170 if (res
!= PM3_SUCCESS
) {
171 PrintAndLogEx(WARNING
, _RED_("No known/supported 13.56 MHz tags found"));
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.",
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"),
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);
204 if ((is_bar
+ is_mix
+ is_value
) > 1) {
205 PrintAndLogEx(ERR
, "Select only one output style");
209 barMode_t style
= session
.bar_mode
;
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");
230 uint32_t max
= 0xFFFF;
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()) {
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");
248 if ((resp
.status
== PM3_EOPABORTED
) || (resp
.length
!= sizeof(uint16_t))) {
249 PrintAndLogEx(NORMAL
, "");
253 uint16_t volt
= resp
.data
.asDwords
[0] & 0xFFFF;
261 print_progress(volt
, max
, style
);
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");
270 PrintAndLogEx(NORMAL
, "\x1b%c[2K\r", 30);
271 PrintAndLogEx(INFO
, "Done.");
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.",
287 "hf sniff --sp 1000 --st 0 -> skip 1000 pairs, skip 0 triggers"
291 arg_u64_0(NULL
, "sp", "<dec>", "skip sample pairs"),
292 arg_u64_0(NULL
, "st", "<dec>", "skip number of triggers"),
295 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
298 uint32_t samplesToSkip
;
299 uint32_t triggersToSkip
;
302 params
.samplesToSkip
= arg_get_u32_def(ctx
, 1, 0);
303 params
.triggersToSkip
= arg_get_u32_def(ctx
, 2, 0);
306 clearCommandBuffer();
307 SendCommandNG(CMD_HF_SNIFF
, (uint8_t *)¶ms
, sizeof(params
));
311 if (kbd_enter_pressed()) {
312 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
313 PrintAndLogEx(INFO
, "User aborted");
317 PacketResponseNG resp
;
318 if (WaitForResponseTimeout(CMD_HF_SNIFF
, &resp
, 1000)) {
320 if (resp
.status
== PM3_EOPABORTED
) {
321 PrintAndLogEx(INFO
, "Button pressed, user aborted");
324 if (resp
.status
== PM3_SUCCESS
) {
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");
351 PrintAndLogEx(INFO
, "Done.");
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.");
365 for (size_t i
= 0; i
< FPGA_TRACE_SIZE
; i
++) {
366 GraphBuffer
[i
] = ((int)buf
[i
]) - 128;
369 GraphTraceLen
= FPGA_TRACE_SIZE
;
373 // remove signal offset
378 RepaintGraphWindow();
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");
392 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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
);