1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // 2011, 2017 - 2019 Merlok
4 // 2014, Peter Fillmore
5 // 2015, 2016, 2017 Iceman
7 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
8 // at your option, any later version. See the LICENSE.txt file for the text of
10 //-----------------------------------------------------------------------------
11 // High frequency ISO14443A commands
12 //-----------------------------------------------------------------------------
16 #include "cmdparser.h" // command_t
17 #include "commonutil.h" // ARRAYLEN
18 #include "comms.h" // clearCommandBuffer
20 #include "cliparser.h"
23 #include "iso7816/iso7816core.h"
24 #include "emv/emvcore.h"
27 #include "util_posix.h" // msclock
28 #include "aidsearch.h"
29 #include "cmdhf.h" // handle HF plot
30 #include "cliparser.h"
31 #include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A
32 #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
33 #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
34 #include "cmdnfc.h" // print_type4_cc_info
36 bool APDUInFramingEnable
= true;
38 static int CmdHelp(const char *Cmd
);
39 static int waitCmd(bool i_select
, uint32_t timeout
, bool verbose
);
41 static const manufactureName manufactureMapping
[] = {
42 // ID, "Vendor Country"
43 { 0x01, "Motorola UK" },
44 { 0x02, "ST Microelectronics SA France" },
45 { 0x03, "Hitachi, Ltd Japan" },
46 { 0x04, "NXP Semiconductors Germany" },
47 { 0x05, "Infineon Technologies AG Germany" },
48 { 0x06, "Cylink USA" },
49 { 0x07, "Texas Instrument France" },
50 { 0x08, "Fujitsu Limited Japan" },
51 { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" },
52 { 0x0A, "NEC Japan" },
53 { 0x0B, "Oki Electric Industry Co. Ltd Japan" },
54 { 0x0C, "Toshiba Corp. Japan" },
55 { 0x0D, "Mitsubishi Electric Corp. Japan" },
56 { 0x0E, "Samsung Electronics Co. Ltd Korea" },
57 { 0x0F, "Hynix / Hyundai, Korea" },
58 { 0x10, "LG-Semiconductors Co. Ltd Korea" },
59 { 0x11, "Emosyn-EM Microelectronics USA" },
60 { 0x12, "INSIDE Technology France" },
61 { 0x13, "ORGA Kartensysteme GmbH Germany" },
62 { 0x14, "SHARP Corporation Japan" },
63 { 0x15, "ATMEL France" },
64 { 0x16, "EM Microelectronic-Marin SA Switzerland" },
65 { 0x17, "KSW Microtec GmbH Germany" },
66 { 0x18, "ZMD AG Germany" },
67 { 0x19, "XICOR, Inc. USA" },
68 { 0x1A, "Sony Corporation Japan" },
69 { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" },
70 { 0x1C, "Emosyn USA" },
71 { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" },
72 { 0x1E, "Magellan Technology Pty Limited Australia" },
73 { 0x1F, "Melexis NV BO Switzerland" },
74 { 0x20, "Renesas Technology Corp. Japan" },
75 { 0x21, "TAGSYS France" },
76 { 0x22, "Transcore USA" },
77 { 0x23, "Shanghai belling corp., ltd. China" },
78 { 0x24, "Masktech Germany Gmbh Germany" },
79 { 0x25, "Innovision Research and Technology Plc UK" },
80 { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" },
81 { 0x27, "Cypak AB Sweden" },
82 { 0x28, "Ricoh Japan" },
83 { 0x29, "ASK France" },
84 { 0x2A, "Unicore Microsystems, LLC Russian Federation" },
85 { 0x2B, "Dallas Semiconductor/Maxim USA" },
86 { 0x2C, "Impinj, Inc. USA" },
87 { 0x2D, "RightPlug Alliance USA" },
88 { 0x2E, "Broadcom Corporation USA" },
89 { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" },
90 { 0x30, "BeeDar Technology Inc. USA" },
91 { 0x31, "RFIDsec Denmark" },
92 { 0x32, "Schweizer Electronic AG Germany" },
93 { 0x33, "AMIC Technology Corp Taiwan" },
94 { 0x34, "Mikron JSC Russia" },
95 { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" },
96 { 0x36, "IDS Microchip AG Switzerland" },
97 { 0x37, "Thinfilm - Kovio USA" },
98 { 0x38, "HMT Microelectronic Ltd Switzerland" },
99 { 0x39, "Silicon Craft Technology Thailand" },
100 { 0x3A, "Advanced Film Device Inc. Japan" },
101 { 0x3B, "Nitecrest Ltd UK" },
102 { 0x3C, "Verayo Inc. USA" },
103 { 0x3D, "HID Global USA" },
104 { 0x3E, "Productivity Engineering Gmbh Germany" },
105 { 0x3F, "Austriamicrosystems AG (reserved) Austria" },
106 { 0x40, "Gemalto SA France" },
107 { 0x41, "Renesas Electronics Corporation Japan" },
108 { 0x42, "3Alogics Inc Korea" },
109 { 0x43, "Top TroniQ Asia Limited Hong Kong" },
110 { 0x44, "Gentag Inc. USA" },
111 { 0x45, "Invengo Information Technology Co.Ltd China" },
112 { 0x46, "Guangzhou Sysur Microelectronics, Inc China" },
113 { 0x47, "CEITEC S.A. Brazil" },
114 { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" },
115 { 0x49, "MediaTek Inc Taiwan" },
116 { 0x4A, "Angstrem PJSC Russia" },
117 { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" },
118 { 0x4C, "LEGIC Identsystems AG Switzerland" },
119 { 0x4D, "Balluff GmbH Germany" },
120 { 0x4E, "Oberthur Technologies France" },
121 { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" },
122 { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" },
123 { 0x51, "Giesecke & Devrient GmbH Germany" },
124 { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" },
125 { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" },
126 { 0x54, "Intel Corporation USA" },
127 { 0x55, "Microsensys GmbH Germany" },
128 { 0x56, "Sonix Technology Co., Ltd. Taiwan" },
129 { 0x57, "Qualcomm Technologies Inc USA" },
130 { 0x58, "Realtek Semiconductor Corp Taiwan" },
131 { 0x59, "Freevision Technologies Co. Ltd China" },
132 { 0x5A, "Giantec Semiconductor Inc. China" },
133 { 0x5B, "JSC Angstrem-T Russia" },
134 { 0x5C, "STARCHIP France" },
135 { 0x5D, "SPIRTECH France" },
136 { 0x5E, "GANTNER Electronic GmbH Austria" },
137 { 0x5F, "Nordic Semiconductor Norway" },
138 { 0x60, "Verisiti Inc USA" },
139 { 0x61, "Wearlinks Technology Inc. China" },
140 { 0x62, "Userstar Information Systems Co., Ltd Taiwan" },
141 { 0x63, "Pragmatic Printing Ltd. UK" },
142 { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico - LSI-TEC Brazil" },
143 { 0x65, "Tendyron Corporation China" },
144 { 0x66, "MUTO Smart Co., Ltd. Korea" },
145 { 0x67, "ON Semiconductor USA" },
146 { 0x68, "TUBITAK BILGEM Turkey" },
147 { 0x69, "Huada Semiconductor Co., Ltd China" },
148 { 0x6A, "SEVENEY France" },
149 { 0x6B, "ISSM France" },
150 { 0x6C, "Wisesec Ltd Israel" },
151 { 0x7C, "DB HiTek Co Ltd Korea" },
152 { 0x7D, "SATO Vicinity Australia" },
153 { 0x7E, "Holtek Taiwan" },
154 { 0x00, "no tag-info available" } // must be the last entry
157 // get a product description based on the UID
159 // returns description of the best match
160 const char *getTagInfo(uint8_t uid
) {
164 for (i
= 0; i
< ARRAYLEN(manufactureMapping
); ++i
)
165 if (uid
== manufactureMapping
[i
].uid
)
166 return manufactureMapping
[i
].desc
;
168 //No match, return default
169 return manufactureMapping
[ARRAYLEN(manufactureMapping
) - 1].desc
;
172 static const hintAIDListT hintAIDList
[] = {
173 // AID, AID len, name, hint - how to use
174 { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "hf fido" },
175 { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" },
176 { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" },
177 { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "hf emv" },
178 { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "hf emv" },
179 { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "hf cipurse" },
180 { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "hf mfdes" },
183 // iso14a apdu input frame length
184 static uint16_t g_frame_len
= 0;
185 uint16_t atsFSC
[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
187 static int CmdHF14AList(const char *Cmd
) {
188 return CmdTraceListAlias(Cmd
, "hf 14a", "14a");
191 int hf14a_getconfig(hf14a_config
*config
) {
192 if (!session
.pm3_present
) return PM3_ENOTTY
;
197 clearCommandBuffer();
199 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG
, NULL
, 0);
200 PacketResponseNG resp
;
201 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG
, &resp
, 2000)) {
202 PrintAndLogEx(WARNING
, "command execution time out");
205 memcpy(config
, resp
.data
.asBytes
, sizeof(hf14a_config
));
209 int hf14a_setconfig(hf14a_config
*config
, bool verbose
) {
210 if (!session
.pm3_present
) return PM3_ENOTTY
;
212 clearCommandBuffer();
213 if (config
!= NULL
) {
214 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG
, (uint8_t *)config
, sizeof(hf14a_config
));
216 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG
, NULL
, 0);
219 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG
, NULL
, 0);
225 static int hf_14a_config_example(void) {
226 PrintAndLogEx(NORMAL
, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:");
227 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 1k 4b UID")":");
228 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
229 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869"));
230 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
231 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 4k 4b UID")":");
232 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
233 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344441802006263646566676869"));
234 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
235 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 1k 7b UID")":");
236 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip"));
237 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566084400626364656667"));
238 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
239 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 4k 7b UID")":");
240 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa forcce --bcc ignore --cl2 force --cl3 skip --rats skip"));
241 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566184200626364656667"));
242 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
243 PrintAndLogEx(NORMAL
, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":");
244 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip -rats skip"));
245 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mfu setuid --uid 04112233445566"));
246 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
249 static int CmdHf14AConfig(const char *Cmd
) {
250 if (!session
.pm3_present
) return PM3_ENOTTY
;
252 CLIParserContext
*ctx
;
253 CLIParserInit(&ctx
, "hf 14a config",
254 "Configure 14a settings (use with caution)",
255 "hf 14a config -> Print current configuration\n"
256 "hf 14a config --std -> Reset default configuration (follow standard)\n"
257 "hf 14a config --atqa std -> Follow standard\n"
258 "hf 14a config --atqa force -> Force execution of anticollision\n"
259 "hf 14a config --atqa skip -> Skip anticollision\n"
260 "hf 14a config --bcc std -> Follow standard\n"
261 "hf 14a config --bcc fix -> Fix bad BCC in anticollision\n"
262 "hf 14a config --bcc ignore -> Ignore bad BCC and use it as such\n"
263 "hf 14a config --cl2 std -> Follow standard\n"
264 "hf 14a config --cl2 force -> Execute CL2\n"
265 "hf 14a config --cl2 skip -> Skip CL2\n"
266 "hf 14a config --cl3 std -> Follow standard\n"
267 "hf 14a config --cl3 force -> Execute CL3\n"
268 "hf 14a config --cl3 skip -> Skip CL3\n"
269 "hf 14a config --rats std -> Follow standard\n"
270 "hf 14a config --rats force -> Execute RATS\n"
271 "hf 14a config --rats skip -> Skip RATS");
275 arg_str0(NULL
, "atqa", "<std|force|skip>", "Configure ATQA<>anticollision behavior"),
276 arg_str0(NULL
, "bcc", "<std|fix|ignore>", "Configure BCC behavior"),
277 arg_str0(NULL
, "cl2", "<std|force|skip>", "Configure SAK<>CL2 behavior"),
278 arg_str0(NULL
, "cl3", "<std|force|skip>", "Configure SAK<>CL3 behavior"),
279 arg_str0(NULL
, "rats", "<std|force|skip>", "Configure RATS behavior"),
280 arg_lit0(NULL
, "std", "Reset default configuration: follow all standard"),
281 arg_lit0("v", "verbose", "verbose output, also prints examples for reviving Gen2 cards"),
284 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
285 bool defaults
= arg_get_lit(ctx
, 6);
288 int atqa
= defaults
? 0 : -1;
289 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)value
, sizeof(value
), &vlen
);
291 if (strcmp(value
, "std") == 0) atqa
= 0;
292 else if (strcmp(value
, "force") == 0) atqa
= 1;
293 else if (strcmp(value
, "skip") == 0) atqa
= 2;
295 PrintAndLogEx(ERR
, "atqa argument must be 'std', 'force', or 'skip'");
300 int bcc
= defaults
? 0 : -1;
301 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)value
, sizeof(value
), &vlen
);
303 if (strcmp(value
, "std") == 0) bcc
= 0;
304 else if (strcmp(value
, "fix") == 0) bcc
= 1;
305 else if (strcmp(value
, "ignore") == 0) bcc
= 2;
307 PrintAndLogEx(ERR
, "bcc argument must be 'std', 'fix', or 'ignore'");
312 int cl2
= defaults
? 0 : -1;
313 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)value
, sizeof(value
), &vlen
);
315 if (strcmp(value
, "std") == 0) cl2
= 0;
316 else if (strcmp(value
, "force") == 0) cl2
= 1;
317 else if (strcmp(value
, "skip") == 0) cl2
= 2;
319 PrintAndLogEx(ERR
, "cl2 argument must be 'std', 'force', or 'skip'");
324 int cl3
= defaults
? 0 : -1;
325 CLIParamStrToBuf(arg_get_str(ctx
, 4), (uint8_t *)value
, sizeof(value
), &vlen
);
327 if (strcmp(value
, "std") == 0) cl3
= 0;
328 else if (strcmp(value
, "force") == 0) cl3
= 1;
329 else if (strcmp(value
, "skip") == 0) cl3
= 2;
331 PrintAndLogEx(ERR
, "cl3 argument must be 'std', 'force', or 'skip'");
336 int rats
= defaults
? 0 : -1;
337 CLIParamStrToBuf(arg_get_str(ctx
, 5), (uint8_t *)value
, sizeof(value
), &vlen
);
339 if (strcmp(value
, "std") == 0) rats
= 0;
340 else if (strcmp(value
, "force") == 0) rats
= 1;
341 else if (strcmp(value
, "skip") == 0) rats
= 2;
343 PrintAndLogEx(ERR
, "rats argument must be 'std', 'force', or 'skip'");
349 bool verbose
= arg_get_lit(ctx
, 7);
354 if (strlen(Cmd
) == 0) {
355 return hf14a_setconfig(NULL
, verbose
);
359 hf_14a_config_example();
362 hf14a_config config
= {
363 .forceanticol
= atqa
,
370 return hf14a_setconfig(&config
, verbose
);
373 int Hf14443_4aGetCardData(iso14a_card_select_t
*card
) {
374 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
, 0, 0, NULL
, 0);
376 PacketResponseNG resp
;
377 WaitForResponse(CMD_ACK
, &resp
);
379 memcpy(card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
381 uint64_t select_status
= resp
.oldarg
[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
383 if (select_status
== 0) {
384 PrintAndLogEx(ERR
, "E->iso14443a card select failed");
388 if (select_status
== 2) {
389 PrintAndLogEx(ERR
, "E->Card doesn't support iso14443-4 mode");
393 if (select_status
== 3) {
394 PrintAndLogEx(INFO
, "E->Card doesn't support standard iso14443-3 anticollision");
395 PrintAndLogEx(SUCCESS
, "\tATQA : %02x %02x", card
->atqa
[1], card
->atqa
[0]);
399 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(card
->uid
, card
->uidlen
));
400 PrintAndLogEx(SUCCESS
, "ATQA: %02x %02x", card
->atqa
[1], card
->atqa
[0]);
401 PrintAndLogEx(SUCCESS
, " SAK: %02x [%" PRIu64
"]", card
->sak
, resp
.oldarg
[0]);
402 if (card
->ats_len
< 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
403 PrintAndLogEx(INFO
, "E-> Error ATS length(%d) : %s", card
->ats_len
, sprint_hex(card
->ats
, card
->ats_len
));
407 PrintAndLogEx(SUCCESS
, " ATS: %s", sprint_hex(card
->ats
, card
->ats_len
));
411 static int CmdHF14AReader(const char *Cmd
) {
412 CLIParserContext
*ctx
;
413 CLIParserInit(&ctx
, "hf 14a reader",
414 "Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
415 "hf 14a reader -@ -> Continuous mode");
419 arg_lit0("k", "keep", "keep the field active after command executed"),
420 arg_lit0("s", "silent", "silent (no messages)"),
421 arg_lit0(NULL
, "drop", "just drop the signal field"),
422 arg_lit0(NULL
, "skip", "ISO14443-3 select only (skip RATS)"),
423 arg_lit0("@", NULL
, "continuous reader mode"),
426 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
428 bool disconnectAfter
= true;
429 if (arg_get_lit(ctx
, 1)) {
430 disconnectAfter
= false;
433 bool silent
= arg_get_lit(ctx
, 2);
435 uint32_t cm
= ISO14A_CONNECT
;
436 if (arg_get_lit(ctx
, 3)) {
437 cm
&= ~ISO14A_CONNECT
;
440 if (arg_get_lit(ctx
, 4)) {
441 cm
|= ISO14A_NO_RATS
;
444 bool continuous
= arg_get_lit(ctx
, 5);
448 int res
= PM3_SUCCESS
;
450 if (!disconnectAfter
)
451 cm
|= ISO14A_NO_DISCONNECT
;
453 PrintAndLogEx(INFO
, "Press " _GREEN_("Enter") " to exit");
456 clearCommandBuffer();
457 SendCommandMIX(CMD_HF_ISO14443A_READER
, cm
, 0, 0, NULL
, 0);
459 if (ISO14A_CONNECT
& cm
) {
460 PacketResponseNG resp
;
461 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
462 if (!silent
) PrintAndLogEx(WARNING
, "iso14443a card select failed");
468 iso14a_card_select_t card
;
469 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
475 3: proprietary Anticollision
477 uint64_t select_status
= resp
.oldarg
[0];
479 if (select_status
== 0) {
480 if (!silent
) PrintAndLogEx(WARNING
, "iso14443a card select failed");
486 if (select_status
== 3) {
487 if (!(silent
&& continuous
)) {
488 PrintAndLogEx(INFO
, "Card doesn't support standard iso14443-3 anticollision");
489 PrintAndLogEx(SUCCESS
, "ATQA: %02x %02x", card
.atqa
[1], card
.atqa
[0]);
495 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
496 if (!(silent
&& continuous
)) {
497 PrintAndLogEx(SUCCESS
, "ATQA: " _GREEN_("%02x %02x"), card
.atqa
[1], card
.atqa
[0]);
498 PrintAndLogEx(SUCCESS
, " SAK: " _GREEN_("%02x [%" PRIu64
"]"), card
.sak
, resp
.oldarg
[0]);
500 if (card
.ats_len
>= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
501 PrintAndLogEx(SUCCESS
, " ATS: " _GREEN_("%s"), sprint_hex(card
.ats
, card
.ats_len
));
504 if (!disconnectAfter
) {
505 if (!silent
) PrintAndLogEx(SUCCESS
, "Card is selected. You can now start sending commands");
510 res
= handle_hf_plot();
511 if (res
!= PM3_SUCCESS
) {
516 if (kbd_enter_pressed()) {
520 } while (continuous
);
522 if (disconnectAfter
) {
523 if (silent
== false) {
524 PrintAndLogEx(INFO
, "field dropped.");
534 static int CmdHF14AInfo(const char *Cmd
) {
536 bool do_nack_test
= false;
537 bool do_aid_search
= false;
539 CLIParserContext
*ctx
;
540 CLIParserInit(&ctx
, "hf 14a info",
541 "This command makes more extensive tests against a ISO14443a tag in order to collect information",
542 "hf 14a info -nsv -> shows full information about the card\n");
546 arg_lit0("v", "verbose", "adds some information to results"),
547 arg_lit0("n", "nacktest", "test for nack bug"),
548 arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
551 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
553 verbose
= arg_get_lit(ctx
, 1);
554 do_nack_test
= arg_get_lit(ctx
, 2);
555 do_aid_search
= arg_get_lit(ctx
, 3);
559 infoHF14A(verbose
, do_nack_test
, do_aid_search
);
563 // Collect ISO14443 Type A UIDs
564 static int CmdHF14ACUIDs(const char *Cmd
) {
565 CLIParserContext
*ctx
;
566 CLIParserInit(&ctx
, "hf 14a cuids",
567 "Collect n>0 ISO14443-a UIDs in one go",
568 "hf 14a cuids -n 5 --> Collect 5 UIDs");
572 arg_int0("n", "num", "<dec>", "Number of UIDs to collect"),
575 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
577 // requested number of UIDs
578 // collect at least 1 (e.g. if no parameter was given)
579 int n
= arg_get_int_def(ctx
, 1, 1);
583 uint64_t t1
= msclock();
584 PrintAndLogEx(SUCCESS
, "collecting %d UIDs", n
);
587 for (int i
= 0; i
< n
; i
++) {
589 if (kbd_enter_pressed()) {
590 PrintAndLogEx(WARNING
, "aborted via keyboard!\n");
594 // execute anticollision procedure
595 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
597 PacketResponseNG resp
;
598 WaitForResponse(CMD_ACK
, &resp
);
600 iso14a_card_select_t
*card
= (iso14a_card_select_t
*) resp
.data
.asBytes
;
602 // check if command failed
603 if (resp
.oldarg
[0] == 0) {
604 PrintAndLogEx(WARNING
, "card select failed.");
607 for (uint16_t m
= 0; m
< card
->uidlen
; m
++) {
608 sprintf(&uid_string
[2 * m
], "%02X", card
->uid
[m
]);
610 PrintAndLogEx(SUCCESS
, "%s", uid_string
);
613 PrintAndLogEx(SUCCESS
, "end: %" PRIu64
" seconds", (msclock() - t1
) / 1000);
617 // ## simulate iso14443a tag
618 int CmdHF14ASim(const char *Cmd
) {
619 CLIParserContext
*ctx
;
620 CLIParserInit(&ctx
, "hf 14a sim",
621 "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID",
622 "hf 14a sim -t 1 --uid 11223344 -> MIFARE Classic 1k\n"
623 "hf 14a sim -t 2 -> MIFARE Ultralight\n"
624 "hf 14a sim -t 3 -> MIFARE Desfire\n"
625 "hf 14a sim -t 4 -> ISO/IEC 14443-4\n"
626 "hf 14a sim -t 5 -> MIFARE Tnp3xxx\n"
627 "hf 14a sim -t 6 -> MIFARE Mini\n"
628 "hf 14a sim -t 7 -> AMIIBO (NTAG 215), pack 0x8080\n"
629 "hf 14a sim -t 8 -> MIFARE Classic 4k\n"
630 "hf 14a sim -t 9 -> FM11RF005SH Shanghai Metro\n"
631 "hf 14a sim -t 10 -> ST25TA IKEA Rothult\n");
635 arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
636 arg_str0("u", "uid", "<hex>", "4, 7 or 10 byte UID"),
637 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
638 arg_lit0("x", NULL
, "Performs the 'reader attack', nr/ar attack against a reader"),
639 arg_lit0(NULL
, "sk", "Fill simulator keys from found keys"),
640 arg_lit0("v", "verbose", "verbose output"),
643 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
645 int tagtype
= arg_get_int(ctx
, 1);
648 uint8_t uid
[10] = {0};
649 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
652 bool useUIDfromEML
= true;
657 flags
|= FLAG_10B_UID_IN_DATA
;
660 flags
|= FLAG_7B_UID_IN_DATA
;
663 flags
|= FLAG_4B_UID_IN_DATA
;
666 PrintAndLogEx(ERR
, "Please specify a 4, 7, or 10 byte UID");
670 PrintAndLogEx(SUCCESS
, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len
, sprint_hex(uid
, uid_len
));
671 useUIDfromEML
= false;
674 uint8_t exitAfterNReads
= arg_get_int(ctx
, 3);
676 if (arg_get_lit(ctx
, 4)) {
677 flags
|= FLAG_NR_AR_ATTACK
;
680 bool setEmulatorMem
= arg_get_lit(ctx
, 5);
681 bool verbose
= arg_get_lit(ctx
, 6);
685 sector_t
*k_sector
= NULL
;
686 uint8_t k_sectorsCount
= 40;
689 flags
|= FLAG_UID_IN_EMUL
;
699 payload
.tagtype
= tagtype
;
700 payload
.flags
= flags
;
701 payload
.exitAfter
= exitAfterNReads
;
702 memcpy(payload
.uid
, uid
, uid_len
);
704 clearCommandBuffer();
705 SendCommandNG(CMD_HF_ISO14443A_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
706 PacketResponseNG resp
;
708 PrintAndLogEx(INFO
, "Press pm3-button to abort simulation");
709 bool keypress
= kbd_enter_pressed();
712 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE
, &resp
, 1500) == 0) continue;
713 if (resp
.status
!= PM3_SUCCESS
) break;
715 if ((flags
& FLAG_NR_AR_ATTACK
) != FLAG_NR_AR_ATTACK
) break;
717 nonces_t
*data
= (nonces_t
*)resp
.data
.asBytes
;
718 readerAttack(k_sector
, k_sectorsCount
, data
[0], setEmulatorMem
, verbose
);
720 keypress
= kbd_enter_pressed();
723 if (keypress
&& (flags
& FLAG_NR_AR_ATTACK
) == FLAG_NR_AR_ATTACK
) {
724 // inform device to break the sim loop since client has exited
725 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
728 if (resp
.status
== PM3_EOPABORTED
&& ((flags
& FLAG_NR_AR_ATTACK
) == FLAG_NR_AR_ATTACK
))
729 showSectorTable(k_sector
, k_sectorsCount
);
731 PrintAndLogEx(INFO
, "Done");
735 int CmdHF14ASniff(const char *Cmd
) {
736 CLIParserContext
*ctx
;
737 CLIParserInit(&ctx
, "hf 14a sniff",
738 "Collect data from the field and save into command buffer.\n"
739 "Buffer accessible from command 'hf 14a list'",
740 " hf 14a sniff -c -r");
744 arg_lit0("c", "card", "triggered by first data from card"),
745 arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ,WUP,...)"),
748 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
752 if (arg_get_lit(ctx
, 1)) {
756 if (arg_get_lit(ctx
, 2)) {
762 clearCommandBuffer();
763 SendCommandNG(CMD_HF_ISO14443A_SNIFF
, (uint8_t *)¶m
, sizeof(uint8_t));
767 int ExchangeRAW14a(uint8_t *datain
, int datainlen
, bool activateField
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
, bool silentMode
) {
768 static uint8_t responseNum
= 0;
773 PacketResponseNG resp
;
776 // Anticollision + SELECT card
777 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
778 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
779 if (!silentMode
) PrintAndLogEx(ERR
, "Proxmark3 connection timeout.");
784 if (resp
.oldarg
[0] == 0) {
785 if (!silentMode
) PrintAndLogEx(ERR
, "No card in field.");
789 if (resp
.oldarg
[0] != 1 && resp
.oldarg
[0] != 2) {
790 if (!silentMode
) PrintAndLogEx(ERR
, "Card not in iso14443-4. res=%" PRId64
".", resp
.oldarg
[0]);
794 if (resp
.oldarg
[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
796 uint8_t rats
[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
797 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_DISCONNECT
, 2, 0, rats
, sizeof(rats
));
798 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
799 if (!silentMode
) PrintAndLogEx(ERR
, "Proxmark3 connection timeout.");
803 if (resp
.oldarg
[0] == 0) { // ats_len
804 if (!silentMode
) PrintAndLogEx(ERR
, "Can't get ATS.");
811 cmdc
|= ISO14A_NO_DISCONNECT
;
813 uint8_t data
[PM3_CMD_DATA_SIZE
] = { 0x0a | responseNum
, 0x00};
815 memcpy(&data
[2], datain
, datainlen
& 0xFFFF);
816 SendCommandOLD(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| cmdc
, (datainlen
& 0xFFFF) + 2, 0, data
, (datainlen
& 0xFFFF) + 2);
819 PacketResponseNG resp
;
821 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
822 recv
= resp
.data
.asBytes
;
823 int iLen
= resp
.oldarg
[0];
826 if (!silentMode
) PrintAndLogEx(ERR
, "No card response.");
830 *dataoutlen
= iLen
- 2;
834 if (maxdataoutlen
&& *dataoutlen
> maxdataoutlen
) {
835 if (!silentMode
) PrintAndLogEx(ERR
, "Buffer too small(%d). Needs %d bytes", *dataoutlen
, maxdataoutlen
);
839 if (recv
[0] != data
[0]) {
840 if (!silentMode
) PrintAndLogEx(ERR
, "iso14443-4 framing error. Card send %2x must be %2x", dataout
[0], data
[0]);
844 memcpy(dataout
, &recv
[2], *dataoutlen
);
848 if (!silentMode
) PrintAndLogEx(ERR
, "ISO 14443A CRC error.");
853 if (!silentMode
) PrintAndLogEx(ERR
, "Reply timeout.");
860 int SelectCard14443A_4(bool disconnect
, bool verbose
, iso14a_card_select_t
*card
) {
862 // global vars should be prefixed with g_
866 memset(card
, 0, sizeof(iso14a_card_select_t
));
871 // Anticollision + SELECT card
872 PacketResponseNG resp
;
873 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
874 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
875 PrintAndLogEx(WARNING
, "Command execute timeout");
880 if (resp
.oldarg
[0] == 0) {
882 PrintAndLogEx(FAILED
, "No card in field");
884 return PM3_ECARDEXCHANGE
;
887 if (resp
.oldarg
[0] != 1 && resp
.oldarg
[0] != 2) {
888 PrintAndLogEx(WARNING
, "Card not in iso14443-4, res=%" PRId64
".", resp
.oldarg
[0]);
889 return PM3_ECARDEXCHANGE
;
892 if (resp
.oldarg
[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
894 uint8_t rats
[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
895 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_DISCONNECT
, sizeof(rats
), 0, rats
, sizeof(rats
));
896 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
897 PrintAndLogEx(WARNING
, "Command execute timeout");
901 if (resp
.oldarg
[0] == 0) { // ats_len
903 PrintAndLogEx(FAILED
, "Can't get ATS");
905 return PM3_ECARDEXCHANGE
;
908 // get frame length from ATS in data field
909 if (resp
.oldarg
[0] > 1) {
910 uint8_t fsci
= resp
.data
.asBytes
[1] & 0x0f;
911 if (fsci
< ARRAYLEN(atsFSC
)) {
912 g_frame_len
= atsFSC
[fsci
];
916 // get frame length from ATS in card data structure
917 iso14a_card_select_t
*vcard
= (iso14a_card_select_t
*) resp
.data
.asBytes
;
918 if (vcard
->ats_len
> 1) {
919 uint8_t fsci
= vcard
->ats
[1] & 0x0f;
920 if (fsci
< ARRAYLEN(atsFSC
)) {
921 g_frame_len
= atsFSC
[fsci
];
926 memcpy(card
, vcard
, sizeof(iso14a_card_select_t
));
930 SetISODEPState(ISODEP_NFCA
);
939 static int CmdExchangeAPDU(bool chainingin
, uint8_t *datain
, int datainlen
, bool activateField
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
, bool *chainingout
) {
940 *chainingout
= false;
943 // select with no disconnect and set g_frame_len
944 int selres
= SelectCard14443A_4(false, true, NULL
);
945 if (selres
!= PM3_SUCCESS
)
951 cmdc
= ISO14A_SEND_CHAINING
;
953 // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
954 // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
955 // here length PM3_CMD_DATA_SIZE=512
956 // timeout must be authomatically set by "get ATS"
958 SendCommandOLD(CMD_HF_ISO14443A_READER
, ISO14A_APDU
| ISO14A_NO_DISCONNECT
| cmdc
, (datainlen
& 0x1FF), 0, datain
, datainlen
& 0x1FF);
960 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_APDU
| ISO14A_NO_DISCONNECT
| cmdc
, 0, 0, NULL
, 0);
962 PacketResponseNG resp
;
964 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
965 uint8_t *recv
= resp
.data
.asBytes
;
966 int iLen
= resp
.oldarg
[0];
967 uint8_t res
= resp
.oldarg
[1];
974 if (maxdataoutlen
&& *dataoutlen
> maxdataoutlen
) {
975 PrintAndLogEx(ERR
, "APDU: Buffer too small(%d), needs %d bytes", *dataoutlen
, maxdataoutlen
);
976 return PM3_EAPDU_FAIL
;
980 if ((res
& 0xF2) == 0xA2) {
987 PrintAndLogEx(ERR
, "APDU: No APDU response");
988 return PM3_EAPDU_FAIL
;
992 if (iLen
< 2 && iLen
>= 0) {
993 PrintAndLogEx(ERR
, "APDU: Small APDU response, len %d", iLen
);
994 return PM3_EAPDU_FAIL
;
999 PrintAndLogEx(ERR
, "APDU: Block type mismatch");
1000 return PM3_EAPDU_FAIL
;
1003 memcpy(dataout
, recv
, dlen
);
1006 if ((res
& 0x10) != 0) {
1007 *chainingout
= true;
1012 PrintAndLogEx(ERR
, "APDU: ISO 14443A CRC error");
1013 return PM3_EAPDU_FAIL
;
1016 PrintAndLogEx(ERR
, "APDU: Reply timeout");
1017 return PM3_EAPDU_FAIL
;
1023 int ExchangeAPDU14a(uint8_t *datain
, int datainlen
, bool activateField
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
1025 bool chaining
= false;
1028 // 3 byte here - 1b framing header, 2b crc16
1029 if (APDUInFramingEnable
&&
1030 ((g_frame_len
&& (datainlen
> g_frame_len
- 3)) || (datainlen
> PM3_CMD_DATA_SIZE
- 3))) {
1034 bool vActivateField
= activateField
;
1037 int vlen
= MIN(g_frame_len
- 3, datainlen
- clen
);
1038 bool chainBlockNotLast
= ((clen
+ vlen
) < datainlen
);
1041 res
= CmdExchangeAPDU(chainBlockNotLast
, &datain
[clen
], vlen
, vActivateField
, dataout
, maxdataoutlen
, dataoutlen
, &chaining
);
1042 if (res
!= PM3_SUCCESS
) {
1043 if (leaveSignalON
== false)
1049 // check R-block ACK
1050 //TODO check this one...
1051 if ((*dataoutlen
== 0) && (chaining
!= chainBlockNotLast
)) {
1052 if (leaveSignalON
== false)
1059 vActivateField
= false;
1061 if (clen
!= datainlen
) {
1062 PrintAndLogEx(ERR
, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen
, clen
, *dataoutlen
);
1066 } while (clen
< datainlen
);
1069 res
= CmdExchangeAPDU(false, datain
, datainlen
, activateField
, dataout
, maxdataoutlen
, dataoutlen
, &chaining
);
1070 if (res
!= PM3_SUCCESS
) {
1071 if (leaveSignalON
== false) {
1079 // I-block with chaining
1080 res
= CmdExchangeAPDU(false, NULL
, 0, false, &dataout
[*dataoutlen
], maxdataoutlen
, dataoutlen
, &chaining
);
1081 if (res
!= PM3_SUCCESS
) {
1082 if (leaveSignalON
== false) {
1089 if (leaveSignalON
== false) {
1096 // ISO14443-4. 7. Half-duplex block transmission protocol
1097 static int CmdHF14AAPDU(const char *Cmd
) {
1098 uint8_t data
[PM3_CMD_DATA_SIZE
];
1100 uint8_t header
[PM3_CMD_DATA_SIZE
];
1102 bool activateField
= false;
1103 bool leaveSignalON
= false;
1104 bool decodeTLV
= false;
1105 bool decodeAPDU
= false;
1106 bool makeAPDU
= false;
1107 bool extendedAPDU
= false;
1110 CLIParserContext
*ctx
;
1111 CLIParserInit(&ctx
, "hf 14a apdu",
1112 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
1113 "hf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"
1114 "hf 14a apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
1115 "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
1116 "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
1118 void *argtable
[] = {
1120 arg_lit0("s", "select", "activate field and select card"),
1121 arg_lit0("k", "keep", "keep signal field ON after receive"),
1122 arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
1123 arg_lit0("d", "decapdu", "decode apdu request if it possible"),
1124 arg_str0("m", "make", "<head (CLA INS P1 P2) hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
1125 arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
1126 arg_int0("l", "le", "<Le (int)>", "Le apdu parameter if `m` parameter included"),
1127 arg_strx1(NULL
, NULL
, "<APDU (hex) | data (hex)>", "data if `m` parameter included"),
1130 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1132 activateField
= arg_get_lit(ctx
, 1);
1133 leaveSignalON
= arg_get_lit(ctx
, 2);
1134 decodeTLV
= arg_get_lit(ctx
, 3);
1135 decodeAPDU
= arg_get_lit(ctx
, 4);
1137 CLIGetHexWithReturn(ctx
, 5, header
, &headerlen
);
1138 makeAPDU
= headerlen
> 0;
1139 if (makeAPDU
&& headerlen
!= 4) {
1140 PrintAndLogEx(ERR
, "header length must be 4 bytes instead of %d", headerlen
);
1144 extendedAPDU
= arg_get_lit(ctx
, 6);
1145 le
= arg_get_int_def(ctx
, 7, 0);
1148 uint8_t apdudata
[PM3_CMD_DATA_SIZE
] = {0};
1149 int apdudatalen
= 0;
1151 CLIGetHexBLessWithReturn(ctx
, 8, apdudata
, &apdudatalen
, 1 + 2);
1154 apdu
.cla
= header
[0];
1155 apdu
.ins
= header
[1];
1156 apdu
.p1
= header
[2];
1157 apdu
.p2
= header
[3];
1159 apdu
.lc
= apdudatalen
;
1160 apdu
.data
= apdudata
;
1162 apdu
.extended_apdu
= extendedAPDU
;
1165 if (APDUEncode(&apdu
, data
, &datalen
)) {
1166 PrintAndLogEx(ERR
, "can't make apdu with provided parameters.");
1173 PrintAndLogEx(ERR
, "make mode not set but here `e` option.");
1178 PrintAndLogEx(ERR
, "make mode not set but here `l` option.");
1183 // len = data + PCB(1b) + CRC(2b)
1184 CLIGetHexBLessWithReturn(ctx
, 8, data
, &datalen
, 1 + 2);
1188 PrintAndLogEx(SUCCESS
, "( " _YELLOW_("%s%s%s")" )",
1189 activateField
? "select" : "",
1190 leaveSignalON
? ", keep" : "",
1191 decodeTLV
? ", TLV" : ""
1193 PrintAndLogEx(SUCCESS
, ">>> %s", sprint_hex_inrow(data
, datalen
));
1198 if (APDUDecode(data
, datalen
, &apdu
) == 0)
1201 PrintAndLogEx(WARNING
, "can't decode APDU.");
1204 int res
= ExchangeAPDU14a(data
, datalen
, activateField
, leaveSignalON
, data
, PM3_CMD_DATA_SIZE
, &datalen
);
1205 if (res
!= PM3_SUCCESS
)
1208 PrintAndLogEx(SUCCESS
, "<<< %s | %s", sprint_hex_inrow(data
, datalen
), sprint_ascii(data
, datalen
));
1209 PrintAndLogEx(SUCCESS
, "<<< status: %02x %02x - %s", data
[datalen
- 2], data
[datalen
- 1], GetAPDUCodeDescription(data
[datalen
- 2], data
[datalen
- 1]));
1212 if (decodeTLV
&& datalen
> 4) {
1213 TLVPrintFromBuffer(data
, datalen
- 2);
1219 static int CmdHF14ACmdRaw(const char *Cmd
) {
1220 CLIParserContext
*ctx
;
1221 CLIParserInit(&ctx
, "hf 14a raw",
1222 "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
1223 "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
1224 "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
1227 void *argtable
[] = {
1229 arg_lit0("a", NULL
, "active signal field ON without select"),
1230 arg_int0("b", NULL
, "<dec>", "number of bits to send. Useful for send partial byte"),
1231 arg_lit0("c", NULL
, "calculate and append CRC"),
1232 arg_lit0("k", NULL
, "keep signal field ON after receive"),
1233 arg_lit0("3", NULL
, "ISO14443-3 select only (skip RATS)"),
1234 arg_lit0("r", NULL
, "do not read response"),
1235 arg_lit0("s", NULL
, "active signal field ON with select"),
1236 arg_int0("t", "timeout", "<ms>", "timeout in milliseconds"),
1237 arg_lit0("v", "verbose", "Verbose output"),
1238 arg_lit0(NULL
, "topaz", "use Topaz protocol to send command"),
1239 arg_strx1(NULL
, NULL
, "<hex>", "raw bytes to send"),
1242 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1244 bool active
= arg_get_lit(ctx
, 1);
1245 uint16_t numbits
= (uint16_t)arg_get_int_def(ctx
, 2, 0);
1246 bool crc
= arg_get_lit(ctx
, 3);
1247 bool keep_field_on
= arg_get_lit(ctx
, 4);
1248 bool no_rats
= arg_get_lit(ctx
, 5);
1249 bool reply
= (arg_get_lit(ctx
, 6) == false);
1250 bool active_select
= arg_get_lit(ctx
, 7);
1251 uint32_t timeout
= (uint32_t)arg_get_int_def(ctx
, 8, 0);
1252 bool verbose
= arg_get_lit(ctx
, 9);
1253 bool topazmode
= arg_get_lit(ctx
, 10);
1256 uint8_t data
[PM3_CMD_DATA_SIZE
];
1257 CLIGetHexWithReturn(ctx
, 11, data
, &datalen
);
1260 bool bTimeout
= (timeout
) ? true : false;
1262 // ensure we can add 2byte crc to input data
1263 if (datalen
>= sizeof(data
) + 2) {
1265 PrintAndLogEx(FAILED
, "Buffer is full, we can't add CRC to your data");
1270 if (crc
&& datalen
> 0 && datalen
< sizeof(data
) - 2) {
1271 uint8_t first
, second
;
1273 compute_crc(CRC_14443_B
, data
, datalen
, &first
, &second
);
1275 compute_crc(CRC_14443_A
, data
, datalen
, &first
, &second
);
1277 data
[datalen
++] = first
;
1278 data
[datalen
++] = second
;
1282 if (active
|| active_select
) {
1283 flags
|= ISO14A_CONNECT
;
1285 flags
|= ISO14A_NO_SELECT
;
1288 uint32_t argtimeout
= 0;
1290 #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
1291 flags
|= ISO14A_SET_TIMEOUT
;
1292 if (timeout
> MAX_TIMEOUT
) {
1293 timeout
= MAX_TIMEOUT
;
1294 PrintAndLogEx(INFO
, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
1296 argtimeout
= 13560000 / 1000 / (8 * 16) * timeout
; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
1299 if (keep_field_on
) {
1300 flags
|= ISO14A_NO_DISCONNECT
;
1304 flags
|= ISO14A_RAW
;
1308 flags
|= ISO14A_TOPAZMODE
;
1311 flags
|= ISO14A_NO_RATS
;
1314 // Max buffer is PM3_CMD_DATA_SIZE
1315 datalen
= (datalen
> PM3_CMD_DATA_SIZE
) ? PM3_CMD_DATA_SIZE
: datalen
;
1317 clearCommandBuffer();
1318 SendCommandOLD(CMD_HF_ISO14443A_READER
, flags
, (datalen
& 0xFFFF) | ((uint32_t)(numbits
<< 16)), argtimeout
, data
, datalen
& 0xFFFF);
1323 res
= waitCmd(true, timeout
, verbose
);
1324 if (res
== PM3_SUCCESS
&& datalen
> 0)
1325 waitCmd(false, timeout
, verbose
);
1330 static int waitCmd(bool i_select
, uint32_t timeout
, bool verbose
) {
1331 PacketResponseNG resp
;
1333 if (WaitForResponseTimeout(CMD_ACK
, &resp
, timeout
+ 1500)) {
1334 uint16_t len
= (resp
.oldarg
[0] & 0xFFFF);
1336 len
= (resp
.oldarg
[1] & 0xFFFF);
1339 PrintAndLogEx(SUCCESS
, "Card selected. UID[%u]:", len
);
1345 PrintAndLogEx(WARNING
, "Can't select card.");
1349 PrintAndLogEx(SUCCESS
, "received " _YELLOW_("%u") " bytes", len
);
1357 uint8_t *data
= resp
.data
.asBytes
;
1359 if (i_select
== false && len
>= 3) {
1360 bool crc
= check_crc(CRC_14443_A
, data
, len
);
1364 (crc
) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
1369 PrintAndLogEx(SUCCESS
, "%s[ %s ]", sprint_hex(data
, len
- 2), s
);
1371 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(data
, len
));
1375 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
1376 return PM3_ETIMEOUT
;
1381 static int CmdHF14AAntiFuzz(const char *Cmd
) {
1383 CLIParserContext
*ctx
;
1384 CLIParserInit(&ctx
, "hf 14a antifuzz",
1385 "Tries to fuzz the ISO14443a anticollision phase",
1386 "hf 14a antifuzz -4\n");
1388 void *argtable
[] = {
1390 arg_lit0("4", NULL
, "4 byte uid"),
1391 arg_lit0("7", NULL
, "7 byte uid"),
1392 arg_lit0(NULL
, "10", "10 byte uid"),
1395 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1400 param
.flag
= FLAG_4B_UID_IN_DATA
;
1402 if (arg_get_lit(ctx
, 2))
1403 param
.flag
= FLAG_7B_UID_IN_DATA
;
1404 if (arg_get_lit(ctx
, 3))
1405 param
.flag
= FLAG_10B_UID_IN_DATA
;
1408 clearCommandBuffer();
1409 SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ
, (uint8_t *)¶m
, sizeof(param
));
1413 static int CmdHF14AChaining(const char *Cmd
) {
1415 CLIParserContext
*ctx
;
1416 CLIParserInit(&ctx
, "hf 14a chaining",
1417 "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
1418 "hf 14a chaining disable -> disable chaining\n"
1419 "hf 14a chaining -> show chaining enable/disable state\n");
1421 void *argtable
[] = {
1423 arg_str0(NULL
, NULL
, "<enable/disable or 0/1>", NULL
),
1426 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1428 struct arg_str
*str
= arg_get_str(ctx
, 1);
1429 int len
= arg_get_str_len(ctx
, 1);
1431 if (len
&& (!strcmp(str
->sval
[0], "enable") || !strcmp(str
->sval
[0], "1")))
1432 APDUInFramingEnable
= true;
1434 if (len
&& (!strcmp(str
->sval
[0], "disable") || !strcmp(str
->sval
[0], "0")))
1435 APDUInFramingEnable
= false;
1439 PrintAndLogEx(INFO
, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable
? "enabled" : "disabled");
1444 static void printTag(const char *tag
) {
1445 PrintAndLogEx(SUCCESS
, " " _YELLOW_("%s"), tag
);
1457 } nxp_mifare_type_t
;
1459 // Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
1460 static int detect_nxp_card(uint8_t sak
, uint16_t atqa
, uint64_t select_status
) {
1463 PrintAndLogEx(SUCCESS
, "Possible types:");
1465 if ((sak
& 0x02) != 0x02) {
1466 if ((sak
& 0x19) == 0x19) {
1467 printTag("MIFARE Classic 2K");
1469 } else if ((sak
& 0x38) == 0x38) {
1470 printTag("SmartMX with MIFARE Classic 4K");
1472 } else if ((sak
& 0x18) == 0x18) {
1473 if (select_status
== 1) {
1474 if ((atqa
& 0x0040) == 0x0040) {
1475 printTag("MIFARE Plus EV1 4K CL2 in SL1");
1476 printTag("MIFARE Plus S 4K CL2 in SL1");
1477 printTag("MIFARE Plus X 4K CL2 in SL1");
1479 printTag("MIFARE Plus EV1 4K in SL1");
1480 printTag("MIFARE Plus S 4K in SL1");
1481 printTag("MIFARE Plus X 4K in SL1");
1486 if ((atqa
& 0x0040) == 0x0040) {
1487 printTag("MIFARE Classic 4K CL2");
1489 printTag("MIFARE Classic 4K");
1494 } else if ((sak
& 0x09) == 0x09) {
1495 if ((atqa
& 0x0040) == 0x0040) {
1496 printTag("MIFARE Mini 0.3K CL2");
1498 printTag("MIFARE Mini 0.3K");
1502 } else if ((sak
& 0x28) == 0x28) {
1503 printTag("SmartMX with MIFARE Classic 1K");
1505 } else if ((sak
& 0x08) == 0x08) {
1506 if (select_status
== 1) {
1507 if ((atqa
& 0x0040) == 0x0040) {
1508 printTag("MIFARE Plus EV1 2K CL2 in SL1");
1509 printTag("MIFARE Plus S 2K CL2 in SL1");
1510 printTag("MIFARE Plus X 2K CL2 in SL1");
1511 printTag("MIFARE Plus SE 1K CL2");
1513 printTag("MIFARE Plus EV1 2K in SL1");
1514 printTag("MIFARE Plus S 2K in SL1");
1515 printTag("MIFARE Plus X 2K in SL1");
1516 printTag("MIFARE Plus SE 1K");
1521 if ((atqa
& 0x0040) == 0x0040) {
1522 printTag("MIFARE Classic 1K CL2");
1524 printTag("MIFARE Classic 1K");
1529 } else if ((sak
& 0x11) == 0x11) {
1530 printTag("MIFARE Plus 4K in SL2");
1532 } else if ((sak
& 0x10) == 0x10) {
1533 printTag("MIFARE Plus 2K in SL2");
1535 } else if ((sak
& 0x01) == 0x01) {
1536 printTag("TNP3xxx (TagNPlay, Activision Game Appliance)");
1538 } else if ((sak
& 0x24) == 0x24) {
1539 printTag("MIFARE DESFire CL1");
1540 printTag("MIFARE DESFire EV1 CL1");
1542 } else if ((sak
& 0x20) == 0x20) {
1543 if (select_status
== 1) {
1544 if ((atqa
& 0x0040) == 0x0040) {
1545 if ((atqa
& 0x0300) == 0x0300) {
1546 printTag("MIFARE DESFire CL2");
1547 printTag("MIFARE DESFire EV1 256B/2K/4K/8K CL2");
1548 printTag("MIFARE DESFire EV2 2K/4K/8K/16K/32K");
1549 printTag("MIFARE DESFire EV3 2K/4K/8K");
1550 printTag("MIFARE DESFire Light 640B");
1552 printTag("MIFARE Plus EV1 2K/4K CL2 in SL3");
1553 printTag("MIFARE Plus S 2K/4K CL2 in SL3");
1554 printTag("MIFARE Plus X 2K/4K CL2 in SL3");
1555 printTag("MIFARE Plus SE 1K CL2");
1560 if ((atqa
& 0x0001) == 0x0001) {
1561 printTag("HID SEOS (smartmx / javacard)");
1564 printTag("MIFARE Plus EV1 2K/4K in SL3");
1565 printTag("MIFARE Plus S 2K/4K in SL3");
1566 printTag("MIFARE Plus X 2K/4K in SL3");
1567 printTag("MIFARE Plus SE 1K");
1572 printTag("NTAG 4xx");
1575 } else if ((sak
& 0x04) == 0x04) {
1576 printTag("Any MIFARE CL1");
1579 printTag("MIFARE Ultralight");
1580 printTag("MIFARE Ultralight C");
1581 printTag("MIFARE Ultralight EV1");
1582 printTag("MIFARE Ultralight Nano");
1583 printTag("MIFARE Hospitality");
1584 printTag("NTAG 2xx");
1585 type
|= MTULTRALIGHT
;
1589 if (type
== MTNONE
) {
1590 PrintAndLogEx(WARNING
, " failed to fingerprint");
1601 const uid_label_name uid_label_map
[] = {
1603 {0x02, 0x84, "M24SR64-Y"},
1604 {0x02, 0xA3, "25TA02KB-P"},
1605 {0x02, 0xC4, "25TA64K"},
1606 {0x02, 0xE3, "25TA02KB"},
1607 {0x02, 0xE4, "25TA512B"},
1608 {0x02, 0xF3, "25TA02KB-D"},
1609 {0x11, 0x22, "NTAG21x Modifiable"},
1610 {0x00, 0x00, "None"}
1613 static void getTagLabel(uint8_t uid0
, uint8_t uid1
) {
1615 while (uid_label_map
[i
].uid0
!= 0x00) {
1616 if ((uid_label_map
[i
].uid0
== uid0
) && (uid_label_map
[i
].uid1
== uid1
)) {
1617 PrintAndLogEx(SUCCESS
, _YELLOW_(" %s"), uid_label_map
[i
].desc
);
1624 int infoHF14A(bool verbose
, bool do_nack_test
, bool do_aid_search
) {
1625 clearCommandBuffer();
1626 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
1627 PacketResponseNG resp
;
1628 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
1629 if (verbose
) PrintAndLogEx(WARNING
, "iso14443a card select failed");
1634 iso14a_card_select_t card
;
1635 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
1641 3: proprietary Anticollision
1643 uint64_t select_status
= resp
.oldarg
[0];
1645 if (select_status
== 0) {
1646 if (verbose
) PrintAndLogEx(WARNING
, "iso14443a card select failed");
1648 return select_status
;
1651 PrintAndLogEx(NORMAL
, "");
1653 if (select_status
== 3) {
1654 PrintAndLogEx(INFO
, "Card doesn't support standard iso14443-3 anticollision");
1655 PrintAndLogEx(SUCCESS
, "ATQA: %02x %02x", card
.atqa
[1], card
.atqa
[0]);
1657 return select_status
;
1661 PrintAndLogEx(INFO
, "--- " _CYAN_("ISO14443-a Information") "---------------------");
1664 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
1665 PrintAndLogEx(SUCCESS
, "ATQA: " _GREEN_("%02x %02x"), card
.atqa
[1], card
.atqa
[0]);
1666 PrintAndLogEx(SUCCESS
, " SAK: " _GREEN_("%02x [%" PRIu64
"]"), card
.sak
, resp
.oldarg
[0]);
1668 bool isMifareClassic
= true;
1669 bool isMifareDESFire
= false;
1670 bool isMifarePlus
= false;
1671 bool isMifareUltralight
= false;
1674 int nxptype
= MTNONE
;
1676 if (card
.uidlen
<= 4) {
1677 nxptype
= detect_nxp_card(card
.sak
, ((card
.atqa
[1] << 8) + card
.atqa
[0]), select_status
);
1679 isMifareClassic
= ((nxptype
& MTCLASSIC
) == MTCLASSIC
);
1680 isMifareDESFire
= ((nxptype
& MTDESFIRE
) == MTDESFIRE
);
1681 isMifarePlus
= ((nxptype
& MTPLUS
) == MTPLUS
);
1682 isMifareUltralight
= ((nxptype
& MTULTRALIGHT
) == MTULTRALIGHT
);
1684 if ((nxptype
& MTOTHER
) == MTOTHER
)
1685 isMifareClassic
= true;
1689 // Double & triple sized UID, can be mapped to a manufacturer.
1690 PrintAndLogEx(SUCCESS
, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card
.uid
[0]));
1692 switch (card
.uid
[0]) {
1697 nxptype
= detect_nxp_card(card
.sak
, ((card
.atqa
[1] << 8) + card
.atqa
[0]), select_status
);
1699 isMifareClassic
= ((nxptype
& MTCLASSIC
) == MTCLASSIC
);
1700 isMifareDESFire
= ((nxptype
& MTDESFIRE
) == MTDESFIRE
);
1701 isMifarePlus
= ((nxptype
& MTPLUS
) == MTPLUS
);
1702 isMifareUltralight
= ((nxptype
& MTULTRALIGHT
) == MTULTRALIGHT
);
1704 if ((nxptype
& MTOTHER
) == MTOTHER
)
1705 isMifareClassic
= true;
1708 case 0x05: // Infineon
1709 if ((card
.uid
[1] & 0xF0) == 0x10) {
1710 printTag("my-d(tm) command set SLE 66R04/16/32P, SLE 66R04/16/32S");
1711 } else if ((card
.uid
[1] & 0xF0) == 0x20) {
1712 printTag("my-d(tm) command set SLE 66R01/16/32P (Type 2 Tag)");
1713 } else if ((card
.uid
[1] & 0xF0) == 0x30) {
1714 printTag("my-d(tm) move lean SLE 66R01P/66R01PN");
1715 } else if ((card
.uid
[1] & 0xF0) == 0x70) {
1716 printTag("my-d(tm) move lean SLE 66R01L");
1718 isMifareUltralight
= true;
1719 isMifareClassic
= false;
1721 if (card
.sak
== 0x88) {
1722 printTag("Infineon MIFARE CLASSIC 1K");
1723 isMifareUltralight
= false;
1724 isMifareClassic
= true;
1726 getTagLabel(card
.uid
[0], card
.uid
[1]);
1729 if (memcmp(card
.uid
, "FSTN10m", 7) == 0) {
1730 isMifareClassic
= false;
1731 printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
1735 if (memcmp(card
.uid
, "WSDZ10m", 7) == 0) {
1736 isMifareClassic
= false;
1737 printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
1741 getTagLabel(card
.uid
[0], card
.uid
[1]);
1744 isMifareClassic
= false;
1746 // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc)
1749 uint32_t tagT
= GetHF14AMfU_Type();
1750 if (tagT
!= UL_ERROR
) {
1751 ul_print_type(tagT
, 0);
1752 isMifareUltralight
= true;
1753 printTag("MIFARE Ultralight/C/NTAG Compatible");
1755 printTag("Possible AZTEK (iso14443a compliant)");
1758 // reconnect for further tests
1759 clearCommandBuffer();
1760 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
1761 WaitForResponse(CMD_ACK
, &resp
);
1763 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
1765 select_status
= resp
.oldarg
[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
1767 if (select_status
== 0) {
1769 return select_status
;
1774 printTag("FM11RF005SH (Shanghai Metro)");
1778 printTag("JCOP 31/41");
1782 printTag("JCOP31 or JCOP41 v2.3.1");
1786 printTag("Nokia 6212 or 6131");
1790 printTag("Gemplus MPCOS");
1801 // try to request ATS even if tag claims not to support it
1802 if (select_status
== 2) {
1803 uint8_t rats
[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
1804 clearCommandBuffer();
1805 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_DISCONNECT
, 2, 0, rats
, sizeof(rats
));
1806 WaitForResponse(CMD_ACK
, &resp
);
1808 memcpy(card
.ats
, resp
.data
.asBytes
, resp
.oldarg
[0]);
1809 card
.ats_len
= resp
.oldarg
[0]; // note: ats_len includes CRC Bytes
1812 if (card
.ats_len
>= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
1814 PrintAndLogEx(INFO
, "-------------------------- " _CYAN_("ATS") " --------------------------");
1815 bool ta1
= 0, tb1
= 0, tc1
= 0;
1817 if (select_status
== 2) {
1818 PrintAndLogEx(INFO
, "--> SAK incorrectly claims that card doesn't support RATS <--");
1821 if (card
.ats
[0] != card
.ats_len
- 2) {
1822 PrintAndLogEx(WARNING
, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card
.ats_len
);
1825 PrintAndLogEx(SUCCESS
, "ATS: " _YELLOW_("%s")"[ %02x %02x ]", sprint_hex(card
.ats
, card
.ats_len
- 2), card
.ats
[card
.ats_len
- 1], card
.ats
[card
.ats_len
]);
1826 PrintAndLogEx(INFO
, " " _YELLOW_("%02x") "............... TL length is " _GREEN_("%d") " bytes", card
.ats
[0], card
.ats
[0]);
1828 if (card
.ats
[0] > 1) { // there is a format byte (T0)
1829 ta1
= (card
.ats
[1] & 0x10) == 0x10;
1830 tb1
= (card
.ats
[1] & 0x20) == 0x20;
1831 tc1
= (card
.ats
[1] & 0x40) == 0x40;
1832 int16_t fsci
= card
.ats
[1] & 0x0f;
1834 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
1835 "TC1 is%s present, FSCI is %d (FSC = %d)",
1837 (ta1
? "" : _RED_(" NOT")),
1838 (tb1
? "" : _RED_(" NOT")),
1839 (tc1
? "" : _RED_(" NOT")),
1841 fsci
< ARRAYLEN(atsFSC
) ? atsFSC
[fsci
] : -1
1846 char dr
[16], ds
[16];
1847 dr
[0] = ds
[0] = '\0';
1848 if (card
.ats
[pos
] & 0x10) strcat(ds
, "2, ");
1849 if (card
.ats
[pos
] & 0x20) strcat(ds
, "4, ");
1850 if (card
.ats
[pos
] & 0x40) strcat(ds
, "8, ");
1851 if (card
.ats
[pos
] & 0x01) strcat(dr
, "2, ");
1852 if (card
.ats
[pos
] & 0x02) strcat(dr
, "4, ");
1853 if (card
.ats
[pos
] & 0x04) strcat(dr
, "8, ");
1854 if (strlen(ds
) != 0) ds
[strlen(ds
) - 2] = '\0';
1855 if (strlen(dr
) != 0) dr
[strlen(dr
) - 2] = '\0';
1856 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
1857 "DR: [%s], DS: [%s]",
1859 ((card
.ats
[pos
] & 0x80) ? _RED_(" NOT") : ""),
1868 uint32_t sfgi
= card
.ats
[pos
] & 0x0F;
1869 uint32_t fwi
= card
.ats
[pos
] >> 4;
1871 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
1874 sfgi
? "" : "(not needed) ",
1875 sfgi
? (1 << 12) << sfgi
: 0,
1883 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
1885 (card
.ats
[pos
] & 0x01) ? "" : _RED_(" NOT"),
1886 (card
.ats
[pos
] & 0x02) ? "" : _RED_(" NOT")
1891 // ATS - Historial bytes and identify based on it
1892 if (card
.ats
[0] > pos
&& card
.ats
[0] <= card
.ats_len
- 2) {
1895 if (card
.ats
[0] - pos
>= 7) {
1897 snprintf(tip
, sizeof(tip
), " ");
1899 if ((card
.sak
& 0x70) == 0x40) { // and no GetVersion()..
1901 if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
1902 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
1904 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
1906 if ((card
.atqa
[0] & 0x02) == 0x02)
1907 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
1908 else if ((card
.atqa
[0] & 0x04) == 0x04)
1909 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
1911 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
1912 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
1914 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
1915 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
1918 } else { //SAK B4,5,6
1920 if ((card
.sak
& 0x20) == 0x20) { // and no GetVersion()..
1923 if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
1924 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
1925 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
1926 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
1927 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
1928 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
1929 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
1930 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
1933 if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
1934 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
1935 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
1936 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
1942 uint8_t calen
= card
.ats
[0] - pos
;
1943 PrintAndLogEx(NORMAL
, "");
1944 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("Historical bytes") " --------------------");
1946 if (card
.ats
[pos
] == 0xC1) {
1947 PrintAndLogEx(INFO
, " %s%s", sprint_hex(card
.ats
+ pos
, calen
), tip
);
1948 PrintAndLogEx(SUCCESS
, " C1..................... Mifare or (multiple) virtual cards of various type");
1949 PrintAndLogEx(SUCCESS
, " %02x.................. length is " _YELLOW_("%d") " bytes", card
.ats
[pos
+ 1], card
.ats
[pos
+ 1]);
1950 switch (card
.ats
[pos
+ 2] & 0xf0) {
1952 PrintAndLogEx(SUCCESS
, " 1x............... MIFARE DESFire");
1953 isMifareDESFire
= true;
1954 isMifareClassic
= false;
1955 isMifarePlus
= false;
1958 PrintAndLogEx(SUCCESS
, " 2x............... MIFARE Plus");
1959 isMifarePlus
= true;
1960 isMifareDESFire
= false;
1961 isMifareClassic
= false;
1964 switch (card
.ats
[pos
+ 2] & 0x0f) {
1966 PrintAndLogEx(SUCCESS
, " x0............... < 1 kByte");
1969 PrintAndLogEx(SUCCESS
, " x1............... 1 kByte");
1972 PrintAndLogEx(SUCCESS
, " x2............... 2 kByte");
1975 PrintAndLogEx(SUCCESS
, " x3............... 4 kByte");
1978 PrintAndLogEx(SUCCESS
, " x4............... 8 kByte");
1981 switch (card
.ats
[pos
+ 3] & 0xf0) {
1983 PrintAndLogEx(SUCCESS
, " 0x............ Engineering sample");
1986 PrintAndLogEx(SUCCESS
, " 2x............ Released");
1989 switch (card
.ats
[pos
+ 3] & 0x0f) {
1991 PrintAndLogEx(SUCCESS
, " x0............ Generation 1");
1994 PrintAndLogEx(SUCCESS
, " x1............ Generation 2");
1997 PrintAndLogEx(SUCCESS
, " x2............ Generation 3");
2000 switch (card
.ats
[pos
+ 4] & 0x0f) {
2002 PrintAndLogEx(SUCCESS
, " x0......... Only VCSL supported");
2005 PrintAndLogEx(SUCCESS
, " x1......... VCS, VCSL, and SVC supported");
2008 PrintAndLogEx(SUCCESS
, " xE......... no VCS command supported");
2012 PrintAndLogEx(SUCCESS
, " %s", sprint_hex_inrow(card
.ats
+ pos
, calen
));
2016 if (do_aid_search
) {
2018 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("AID Search") " --------------------");
2020 json_t
*root
= AIDSearchInit(verbose
);
2023 bool ActivateField
= true;
2024 for (size_t elmindx
= 0; elmindx
< json_array_size(root
); elmindx
++) {
2026 if (kbd_enter_pressed()) {
2030 json_t
*data
= AIDSearchGetElm(root
, elmindx
);
2031 uint8_t vaid
[200] = {0};
2033 if (!AIDGetFromElm(data
, vaid
, sizeof(vaid
), &vaidlen
) || !vaidlen
)
2037 uint8_t result
[1024] = {0};
2038 size_t resultlen
= 0;
2039 int res
= Iso7816Select(CC_CONTACTLESS
, ActivateField
, true, vaid
, vaidlen
, result
, sizeof(result
), &resultlen
, &sw
);
2040 ActivateField
= false;
2044 uint8_t dfname
[200] = {0};
2045 size_t dfnamelen
= 0;
2046 if (resultlen
> 3) {
2047 struct tlvdb
*tlv
= tlvdb_parse_multi(result
, resultlen
);
2049 // 0x84 Dedicated File (DF) Name
2050 const struct tlv
*dfnametlv
= tlvdb_get_tlv(tlvdb_find_full(tlv
, 0x84));
2052 dfnamelen
= dfnametlv
->len
;
2053 memcpy(dfname
, dfnametlv
->value
, dfnamelen
);
2059 if (sw
== 0x9000 || sw
== 0x6283 || sw
== 0x6285) {
2061 if (verbose
) PrintAndLogEx(SUCCESS
, "Application ( " _GREEN_("ok") " )");
2063 if (verbose
) PrintAndLogEx(WARNING
, "Application ( " _RED_("blocked") " )");
2066 PrintAIDDescriptionBuf(root
, vaid
, vaidlen
, verbose
);
2069 if (dfnamelen
== vaidlen
) {
2070 if (memcmp(dfname
, vaid
, vaidlen
) == 0) {
2071 if (verbose
) PrintAndLogEx(INFO
, "(DF) Name found and equal to AID");
2073 PrintAndLogEx(INFO
, "(DF) Name not equal to AID: %s :", sprint_hex(dfname
, dfnamelen
));
2074 PrintAIDDescriptionBuf(root
, dfname
, dfnamelen
, verbose
);
2077 PrintAndLogEx(INFO
, "(DF) Name not equal to AID: %s :", sprint_hex(dfname
, dfnamelen
));
2078 PrintAIDDescriptionBuf(root
, dfname
, dfnamelen
, verbose
);
2081 if (verbose
) PrintAndLogEx(INFO
, "(DF) Name not found");
2084 if (verbose
) PrintAndLogEx(SUCCESS
, "----------------------------------------------------");
2091 if (verbose
== false && found
)
2092 PrintAndLogEx(INFO
, "----------------------------------------------------");
2096 PrintAndLogEx(INFO
, "proprietary non iso14443-4 card found, RATS not supported");
2097 if ((card
.sak
& 0x20) == 0x20) {
2098 PrintAndLogEx(INFO
, "--> SAK incorrectly claims that card supports RATS <--");
2103 if (isMifareClassic
) {
2104 isMagic
= detect_mf_magic(true);
2106 if (isMifareUltralight
) {
2107 isMagic
= (detect_mf_magic(false) == MAGIC_NTAG21X
);
2109 if (isMifareClassic
) {
2110 int res
= detect_classic_static_nonce();
2111 if (res
== NONCE_STATIC
)
2112 PrintAndLogEx(SUCCESS
, "Static nonce: " _YELLOW_("yes"));
2114 if (res
== NONCE_FAIL
&& verbose
)
2115 PrintAndLogEx(SUCCESS
, "Static nonce: " _RED_("read failed"));
2117 if (res
== NONCE_NORMAL
) {
2120 res
= detect_classic_prng();
2122 PrintAndLogEx(SUCCESS
, "Prng detection: " _GREEN_("weak"));
2124 PrintAndLogEx(SUCCESS
, "Prng detection: " _YELLOW_("hard"));
2126 PrintAndLogEx(FAILED
, "Prng detection: " _RED_("fail"));
2129 detect_classic_nackbug(false);
2132 uint8_t signature
[32] = {0};
2133 res
= detect_mfc_ev1_signature(signature
);
2134 if (res
== PM3_SUCCESS
) {
2135 mfc_ev1_print_signature(card
.uid
, card
.uidlen
, signature
, sizeof(signature
));
2138 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mf`") " commands");
2141 if (isMifareUltralight
)
2142 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu info`"));
2144 if (isMifarePlus
&& isMagic
== 0 && isEMV
== false)
2145 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfp info`"));
2147 if (isMifareDESFire
&& isMagic
== 0 && isEMV
== false)
2148 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfdes info`"));
2151 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf st info`"));
2154 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`emv search -s`"));
2156 PrintAndLogEx(NORMAL
, "");
2158 return select_status
;
2161 int infoHF14A4Applications(bool verbose
) {
2162 bool cardFound
[ARRAYLEN(hintAIDList
)] = {0};
2163 bool ActivateField
= true;
2165 for (int i
= 0; i
< ARRAYLEN(hintAIDList
); i
++) {
2167 uint8_t result
[1024] = {0};
2168 size_t resultlen
= 0;
2169 int res
= Iso7816Select(CC_CONTACTLESS
, ActivateField
, true, (uint8_t *)hintAIDList
[i
].aid
, hintAIDList
[i
].aid_length
, result
, sizeof(result
), &resultlen
, &sw
);
2170 ActivateField
= false;
2174 if (sw
== 0x9000 || sw
== 0x6283 || sw
== 0x6285) {
2177 PrintAndLogEx(INFO
, "----------------- " _CYAN_("Short AID search") " -----------------");
2183 PrintAndLogEx(SUCCESS
, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList
[i
].desc
);
2184 cardFound
[i
] = true;
2187 PrintAndLogEx(WARNING
, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList
[i
].desc
);
2194 PrintAndLogEx(INFO
, "---------------------------------------------------");
2196 PrintAndLogEx(INFO
, "Short AID search:");
2198 if (found
>= ARRAYLEN(hintAIDList
) - 1) {
2199 PrintAndLogEx(HINT
, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card.");
2201 for (int i
= 0; i
< ARRAYLEN(hintAIDList
); i
++) {
2202 if (cardFound
[i
] && strlen(hintAIDList
[i
].hint
))
2203 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("%s") " commands", hintAIDList
[i
].hint
);
2212 static uint16_t get_sw(uint8_t *d
, uint8_t n
) {
2217 return d
[n
] * 0x0100 + d
[n
+ 1];
2220 static uint64_t inc_sw_error_occurence(uint16_t sw
, uint64_t all_sw
[256][256]) {
2221 uint8_t sw1
= (uint8_t)(sw
>> 8);
2222 uint8_t sw2
= (uint8_t)(0xff & sw
);
2223 if (sw1
== 0x90 && sw2
== 0x00) {
2224 return 0; // Don't count successes.
2226 if (sw1
== 0x6d && sw2
== 0x00) {
2227 return 0xffffffffffffffffULL
; // Always max "Instruction not supported".
2229 return ++all_sw
[sw1
][sw2
];
2232 static int CmdHf14AFindapdu(const char *Cmd
) {
2233 // TODO: Option to select AID/File (and skip INS 0xA4).
2234 // TODO: Check all instructions with extended APDUs if the card support it.
2235 // TODO: Option to reset tag before every command.
2236 CLIParserContext
*ctx
;
2237 CLIParserInit(&ctx
, "hf 14a apdufind",
2238 "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands.\n"
2239 "It loops all 256 possible values for each byte.\n"
2240 "The loop oder is INS -> P1/P2 (alternating) -> CLA.\n"
2241 "Tag must be on antenna before running.",
2243 "hf 14a apdufind --cla 80\n"
2244 "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le\n"
2247 void *argtable
[] = {
2249 arg_str0("c", "cla", "<hex>", "Start value of CLASS (1 hex byte)"),
2250 arg_str0("i", "ins", "<hex>", "Start value of INSTRUCTION (1 hex byte)"),
2251 arg_str0(NULL
, "p1", "<hex>", "Start value of P1 (1 hex byte)"),
2252 arg_str0(NULL
, "p2", "<hex>", "Start value of P2 (1 hex byte)"),
2253 arg_u64_0("r", "reset", "<number>", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"),
2254 arg_u64_0("e", "error-limit", "<number>", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."),
2255 arg_strx0("s", "skip-ins", "<hex>", "Do not test an instructions (can be specifed multiple times)"),
2256 arg_lit0("l", "with-le", "Serach for APDUs with Le=0 (case 2S) as well"),
2257 arg_lit0("v", "verbose", "Verbose output"),
2260 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2263 uint8_t cla_arg
[1] = {0};
2264 CLIGetHexWithReturn(ctx
, 1, cla_arg
, &cla_len
);
2266 uint8_t ins_arg
[1] = {0};
2267 CLIGetHexWithReturn(ctx
, 2, ins_arg
, &ins_len
);
2269 uint8_t p1_arg
[1] = {0};
2270 CLIGetHexWithReturn(ctx
, 3, p1_arg
, &p1_len
);
2272 uint8_t p2_arg
[1] = {0};
2273 CLIGetHexWithReturn(ctx
, 4, p2_arg
, &p2_len
);
2274 uint64_t reset_time
= arg_get_u64_def(ctx
, 5, 5 * 60);
2275 uint64_t error_limit
= arg_get_u64_def(ctx
, 6, 512);
2276 int ignore_ins_len
= 0;
2277 uint8_t ignore_ins_arg
[250] = {0};
2278 CLIGetHexWithReturn(ctx
, 7, ignore_ins_arg
, &ignore_ins_len
);
2279 bool with_le
= arg_get_lit(ctx
, 8);
2280 bool verbose
= arg_get_lit(ctx
, 9);
2284 bool activate_field
= true;
2285 bool keep_field_on
= true;
2286 uint8_t cla
= cla_arg
[0];
2287 uint8_t ins
= ins_arg
[0];
2288 uint8_t p1
= p1_arg
[0];
2289 uint8_t p2
= p2_arg
[0];
2290 uint8_t response
[PM3_CMD_DATA_SIZE
];
2292 uint8_t aSELECT_AID
[80];
2293 int aSELECT_AID_n
= 0;
2295 // Check if the tag reponds to APDUs.
2296 PrintAndLogEx(INFO
, "Sending a test APDU (select file command) to check if the tag is responding to APDU");
2297 param_gethex_to_eol("00a404000aa000000440000101000100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
2298 int res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, true, false, response
, sizeof(response
), &response_n
);
2299 if (res
!= PM3_SUCCESS
) {
2300 PrintAndLogEx(FAILED
, "Tag did not respond to a test APDU (select file command). Aborting");
2303 PrintAndLogEx(SUCCESS
, "Got response. Starting the APDU finder [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2304 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
2307 bool skip_ins
= false;
2308 uint64_t all_sw
[256][256] = { { 0 } };
2309 uint64_t sw_occurences
= 0;
2310 uint64_t t_start
= msclock();
2311 uint64_t t_last_reset
= msclock();
2318 // Exit (was the Enter key pressed)?
2319 if (kbd_enter_pressed()) {
2320 PrintAndLogEx(INFO
, "User interrupted detected. Aborting");
2324 // Skip/Ignore this instrctuion?
2325 for (int i
= 0; i
< ignore_ins_len
; i
++) {
2326 if (ins
== ignore_ins_arg
[i
]) {
2337 PrintAndLogEx(INFO
, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2340 // Send APDU without Le (case 1) and with Le = 0 (case 2S), if "with-le" was set.
2341 uint8_t command
[5] = {cla
, ins
, p1
, p2
, 0x00};
2343 for (int i
= 0; i
< 1 + with_le
; i
++) {
2345 res
= ExchangeAPDU14a(command
, command_n
+ i
, activate_field
, keep_field_on
, response
, sizeof(response
), &response_n
);
2346 if (res
!= PM3_SUCCESS
) {
2348 activate_field
= true;
2351 uint16_t sw
= get_sw(response
, response_n
);
2352 sw_occurences
= inc_sw_error_occurence(sw
, all_sw
);
2355 if (sw_occurences
< error_limit
) {
2356 logLevel_t log_level
= INFO
;
2358 log_level
= SUCCESS
;
2360 PrintAndLogEx(log_level
, "Got response for APDU \"%s\": %04X (%s)", sprint_hex_inrow(command
, command_n
+ i
),
2361 sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2362 if (response_n
> 2) {
2363 PrintAndLogEx(SUCCESS
, "Response data is: %s | %s", sprint_hex_inrow(response
, response_n
- 2),
2364 sprint_ascii(response
, response_n
- 2));
2368 activate_field
= false; // Do not reativate the filed until the next reset.
2369 } while (++ins
!= ins_arg
[0]);
2370 // Increment P1/P2 in an alternating fashion.
2377 // Check if re-selecting the card is needed.
2378 uint64_t t_since_last_reset
= ((msclock() - t_last_reset
) / 1000);
2379 if (t_since_last_reset
> reset_time
) {
2381 activate_field
= true;
2382 t_last_reset
= msclock();
2383 PrintAndLogEx(INFO
, "Last reset was %" PRIu64
" seconds ago. Reseting the tag to prevent timeout issues", t_since_last_reset
);
2385 PrintAndLogEx(INFO
, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2386 } while (p1
!= p1_arg
[0] || p2
!= p2_arg
[0]);
2388 PrintAndLogEx(INFO
, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2389 } while (cla
!= cla_arg
[0]);
2392 PrintAndLogEx(SUCCESS
, "Runtime: %" PRIu64
" seconds\n", (msclock() - t_start
) / 1000);
2397 int CmdHF14ANdefRead(const char *Cmd
) {
2398 CLIParserContext
*ctx
;
2399 CLIParserInit(&ctx
, "hf 14a ndefread",
2400 "Read NFC Data Exchange Format (NDEF) file on Type 4 NDEF tag",
2401 "hf 14a ndefread\n");
2403 void *argtable
[] = {
2407 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2410 bool activate_field
= true;
2411 bool keep_field_on
= true;
2412 uint8_t response
[PM3_CMD_DATA_SIZE
];
2414 bool backward_compatibility_v1
= false;
2416 // --------------- Select NDEF Tag application ----------------
2417 uint8_t aSELECT_AID
[80];
2418 int aSELECT_AID_n
= 0;
2419 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
2420 int res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2421 if (res
!= PM3_SUCCESS
) {
2431 uint16_t sw
= get_sw(response
, resplen
);
2433 // Try NDEF Type 4 Tag v1.0
2434 param_gethex_to_eol("00a4040007d2760000850100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
2435 res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2436 if (res
!= PM3_SUCCESS
) {
2445 sw
= get_sw(response
, resplen
);
2447 PrintAndLogEx(ERR
, "Selecting NDEF aid failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2451 backward_compatibility_v1
= true;
2454 activate_field
= false;
2455 keep_field_on
= true;
2457 // --------------- CC file reading ----------------
2459 uint8_t aSELECT_FILE_CC
[30];
2460 int aSELECT_FILE_CC_n
= 0;
2461 if (backward_compatibility_v1
) {
2462 param_gethex_to_eol("00a4000002e103", 0, aSELECT_FILE_CC
, sizeof(aSELECT_FILE_CC
), &aSELECT_FILE_CC_n
);
2464 param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC
, sizeof(aSELECT_FILE_CC
), &aSELECT_FILE_CC_n
);
2466 res
= ExchangeAPDU14a(aSELECT_FILE_CC
, aSELECT_FILE_CC_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2467 if (res
!= PM3_SUCCESS
) {
2472 sw
= get_sw(response
, resplen
);
2474 PrintAndLogEx(ERR
, "Selecting CC file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2479 uint8_t aREAD_CC
[30];
2481 param_gethex_to_eol("00b000000f", 0, aREAD_CC
, sizeof(aREAD_CC
), &aREAD_CC_n
);
2482 res
= ExchangeAPDU14a(aREAD_CC
, aREAD_CC_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2483 if (res
!= PM3_SUCCESS
) {
2488 sw
= get_sw(response
, resplen
);
2490 PrintAndLogEx(ERR
, "reading CC file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2496 uint8_t cc_data
[resplen
- 2];
2497 memcpy(cc_data
, response
, sizeof(cc_data
));
2498 uint8_t file_id
[2] = {cc_data
[9], cc_data
[10]};
2500 print_type4_cc_info(cc_data
, sizeof(cc_data
));
2501 uint16_t max_rapdu_size
= (cc_data
[3] << 8 | cc_data
[4]) - 2;
2502 max_rapdu_size
= max_rapdu_size
< sizeof(response
) - 2 ? max_rapdu_size
: sizeof(response
) - 2;
2504 // --------------- NDEF file reading ----------------
2505 uint8_t aSELECT_FILE_NDEF
[30];
2506 int aSELECT_FILE_NDEF_n
= 0;
2507 if (backward_compatibility_v1
) {
2508 param_gethex_to_eol("00a4000002", 0, aSELECT_FILE_NDEF
, sizeof(aSELECT_FILE_NDEF
), &aSELECT_FILE_NDEF_n
);
2510 param_gethex_to_eol("00a4000c02", 0, aSELECT_FILE_NDEF
, sizeof(aSELECT_FILE_NDEF
), &aSELECT_FILE_NDEF_n
);
2512 memcpy(aSELECT_FILE_NDEF
+ aSELECT_FILE_NDEF_n
, file_id
, sizeof(file_id
));
2513 res
= ExchangeAPDU14a(aSELECT_FILE_NDEF
, aSELECT_FILE_NDEF_n
+ sizeof(file_id
), activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2514 if (res
!= PM3_SUCCESS
) {
2519 sw
= get_sw(response
, resplen
);
2521 PrintAndLogEx(ERR
, "Selecting NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2526 // read first 2 bytes to get NDEF length
2528 uint8_t aREAD_NDEF
[30];
2529 int aREAD_NDEF_n
= 0;
2530 param_gethex_to_eol("00b0000002", 0, aREAD_NDEF
, sizeof(aREAD_NDEF
), &aREAD_NDEF_n
);
2531 res
= ExchangeAPDU14a(aREAD_NDEF
, aREAD_NDEF_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2532 if (res
!= PM3_SUCCESS
) {
2537 sw
= get_sw(response
, resplen
);
2539 PrintAndLogEx(ERR
, "reading NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2543 uint16_t ndef_size
= (response
[0] << 8) + response
[1];
2544 uint16_t offset
= 2;
2545 uint8_t *ndef_file
= calloc(ndef_size
, sizeof(uint8_t));
2546 if (ndef_file
== NULL
) {
2547 PrintAndLogEx(ERR
, "Out of memory error in CmdHF14ANdef(). Aborting...\n");
2551 for (uint16_t i
= offset
; i
< ndef_size
+ offset
; i
+= max_rapdu_size
) {
2552 uint16_t segment_size
= max_rapdu_size
< ndef_size
+ offset
- i
? max_rapdu_size
: ndef_size
+ offset
- i
;
2553 keep_field_on
= i
< ndef_size
+ offset
- max_rapdu_size
;
2555 param_gethex_to_eol("00b00000", 0, aREAD_NDEF
, sizeof(aREAD_NDEF
), &aREAD_NDEF_n
);
2556 aREAD_NDEF
[2] = i
>> 8;
2557 aREAD_NDEF
[3] = i
& 0xFF;
2558 aREAD_NDEF
[4] = segment_size
;
2559 res
= ExchangeAPDU14a(aREAD_NDEF
, aREAD_NDEF_n
+ 1, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
2560 if (res
!= PM3_SUCCESS
) {
2565 sw
= get_sw(response
, resplen
);
2567 PrintAndLogEx(ERR
, "reading NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
2572 if (resplen
!= segment_size
+ 2) {
2573 PrintAndLogEx(ERR
, "reading NDEF file failed, expected %i bytes, got %i bytes.", segment_size
, resplen
- 2);
2578 memcpy(ndef_file
+ (i
- offset
), response
, segment_size
);
2580 NDEFRecordsDecodeAndPrint(ndef_file
, ndef_size
);
2585 static command_t CommandTable
[] = {
2586 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
2587 {"list", CmdHF14AList
, AlwaysAvailable
, "List ISO 14443-a history"},
2588 {"info", CmdHF14AInfo
, IfPm3Iso14443a
, "Tag information"},
2589 {"reader", CmdHF14AReader
, IfPm3Iso14443a
, "Act like an ISO14443-a reader"},
2590 {"ndefread", CmdHF14ANdefRead
, IfPm3Iso14443a
, "Read an NDEF file from ISO 14443-A Type 4 tag"},
2591 {"cuids", CmdHF14ACUIDs
, IfPm3Iso14443a
, "Collect n>0 ISO14443-a UIDs in one go"},
2592 {"sim", CmdHF14ASim
, IfPm3Iso14443a
, "Simulate ISO 14443-a tag"},
2593 {"sniff", CmdHF14ASniff
, IfPm3Iso14443a
, "sniff ISO 14443-a traffic"},
2594 {"apdu", CmdHF14AAPDU
, IfPm3Iso14443a
, "Send ISO 14443-4 APDU to tag"},
2595 {"chaining", CmdHF14AChaining
, IfPm3Iso14443a
, "Control ISO 14443-4 input chaining"},
2596 {"raw", CmdHF14ACmdRaw
, IfPm3Iso14443a
, "Send raw hex data to tag"},
2597 {"antifuzz", CmdHF14AAntiFuzz
, IfPm3Iso14443a
, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
2598 {"config", CmdHf14AConfig
, IfPm3Iso14443a
, "Configure 14a settings (use with caution)"},
2599 {"apdufind", CmdHf14AFindapdu
, IfPm3Iso14443a
, "Enumerate APDUs - CLA/INS/P1P2"},
2600 {NULL
, NULL
, NULL
, NULL
}
2603 static int CmdHelp(const char *Cmd
) {
2604 (void)Cmd
; // Cmd is not used so far
2605 CmdsHelp(CommandTable
);
2609 int CmdHF14A(const char *Cmd
) {
2610 clearCommandBuffer();
2611 return CmdsParse(CommandTable
, Cmd
);