1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // High frequency ISO14443A commands
17 //-----------------------------------------------------------------------------
21 #include "cmdparser.h" // command_t
22 #include "commonutil.h" // ARRAYLEN
23 #include "comms.h" // clearCommandBuffer
25 #include "cliparser.h"
28 #include "iso7816/iso7816core.h"
29 #include "emv/emvcore.h"
32 #include "util_posix.h" // msclock
33 #include "aidsearch.h"
34 #include "cmdhf.h" // handle HF plot
35 #include "cliparser.h"
36 #include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A
37 #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
38 #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
39 #include "cmdnfc.h" // print_type4_cc_info
40 #include "fileutils.h" // saveFile
41 #include "atrs.h" // getATRinfo
42 #include "desfire.h" // desfire enums
43 #include "mifare/desfirecore.h" // desfire context
44 #include "mifare/mifaredefault.h"
45 #include "preferences.h" // get/set device debug level
47 static bool g_apdu_in_framing_enable
= true;
48 bool Get_apdu_in_framing(void) {
49 return g_apdu_in_framing_enable
;
51 void Set_apdu_in_framing(bool v
) {
52 g_apdu_in_framing_enable
= v
;
55 static int CmdHelp(const char *Cmd
);
56 static int waitCmd(bool i_select
, uint32_t timeout
, bool verbose
);
59 static const iso14a_polling_frame_t WUPA_FRAME
= {
63 static const iso14a_polling_frame_t MAGWUPA1_FRAME
= {
67 static const iso14a_polling_frame_t MAGWUPA2_FRAME
= {
71 static const iso14a_polling_frame_t MAGWUPA3_FRAME
= {
75 static const iso14a_polling_frame_t MAGWUPA4_FRAME
= {
79 static const iso14a_polling_frame_t ECP_FRAME
= {
80 .frame
= { 0x6a, 0x02, 0xC8, 0x01, 0x00, 0x03, 0x00, 0x02, 0x79, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xD8},
87 static const manufactureName_t manufactureMapping
[] = {
88 // ID, "Vendor Country"
89 { 0x01, "Motorola UK" },
90 { 0x02, "ST Microelectronics SA France" },
91 { 0x03, "Hitachi, Ltd Japan" },
92 { 0x04, "NXP Semiconductors Germany" },
93 { 0x05, "Infineon Technologies AG Germany" },
94 { 0x06, "Cylink USA" },
95 { 0x07, "Texas Instrument France" },
96 { 0x08, "Fujitsu Limited Japan" },
97 { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" },
98 { 0x0A, "NEC Japan" },
99 { 0x0B, "Oki Electric Industry Co. Ltd Japan" },
100 { 0x0C, "Toshiba Corp. Japan" },
101 { 0x0D, "Mitsubishi Electric Corp. Japan" },
102 { 0x0E, "Samsung Electronics Co. Ltd Korea" },
103 { 0x0F, "Hynix / Hyundai, Korea" },
104 { 0x10, "LG-Semiconductors Co. Ltd Korea" },
105 { 0x11, "Emosyn-EM Microelectronics USA" },
106 { 0x12, "INSIDE Technology France" },
107 { 0x13, "ORGA Kartensysteme GmbH Germany" },
108 { 0x14, "SHARP Corporation Japan" },
109 { 0x15, "ATMEL France" },
110 { 0x16, "EM Microelectronic-Marin SA Switzerland" },
111 { 0x17, "KSW Microtec GmbH Germany" },
112 { 0x18, "ZMD AG Germany" },
113 { 0x19, "XICOR, Inc. USA" },
114 { 0x1A, "Sony Corporation Japan" },
115 { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" },
116 { 0x1C, "Emosyn USA" },
117 { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" },
118 { 0x1E, "Magellan Technology Pty Limited Australia" },
119 { 0x1F, "Melexis NV BO Switzerland" },
120 { 0x20, "Renesas Technology Corp. Japan" },
121 { 0x21, "TAGSYS France" },
122 { 0x22, "Transcore USA" },
123 { 0x23, "Shanghai belling corp., ltd. China" },
124 { 0x24, "Masktech Germany Gmbh Germany" },
125 { 0x25, "Innovision Research and Technology Plc UK" },
126 { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" },
127 { 0x27, "Cypak AB Sweden" },
128 { 0x28, "Ricoh Japan" },
129 { 0x29, "ASK France" },
130 { 0x2A, "Unicore Microsystems, LLC Russian Federation" },
131 { 0x2B, "Dallas Semiconductor/Maxim USA" },
132 { 0x2C, "Impinj, Inc. USA" },
133 { 0x2D, "RightPlug Alliance USA" },
134 { 0x2E, "Broadcom Corporation USA" },
135 { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" },
136 { 0x30, "BeeDar Technology Inc. USA" },
137 { 0x31, "RFIDsec Denmark" },
138 { 0x32, "Schweizer Electronic AG Germany" },
139 { 0x33, "AMIC Technology Corp Taiwan" },
140 { 0x34, "Mikron JSC Russia" },
141 { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" },
142 { 0x36, "IDS Microchip AG Switzerland" },
143 { 0x37, "Thinfilm - Kovio USA" },
144 { 0x38, "HMT Microelectronic Ltd Switzerland" },
145 { 0x39, "Silicon Craft Technology Thailand" },
146 { 0x3A, "Advanced Film Device Inc. Japan" },
147 { 0x3B, "Nitecrest Ltd UK" },
148 { 0x3C, "Verayo Inc. USA" },
149 { 0x3D, "HID Global USA" },
150 { 0x3E, "Productivity Engineering Gmbh Germany" },
151 { 0x3F, "Austriamicrosystems AG (reserved) Austria" },
152 { 0x40, "Gemalto SA France" },
153 { 0x41, "Renesas Electronics Corporation Japan" },
154 { 0x42, "3Alogics Inc Korea" },
155 { 0x43, "Top TroniQ Asia Limited Hong Kong" },
156 { 0x44, "Gentag Inc. USA" },
157 { 0x45, "Invengo Information Technology Co.Ltd China" },
158 { 0x46, "Guangzhou Sysur Microelectronics, Inc China" },
159 { 0x47, "CEITEC S.A. Brazil" },
160 { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" },
161 { 0x49, "MediaTek Inc Taiwan" },
162 { 0x4A, "Angstrem PJSC Russia" },
163 { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" },
164 { 0x4C, "LEGIC Identsystems AG Switzerland" },
165 { 0x4D, "Balluff GmbH Germany" },
166 { 0x4E, "Oberthur Technologies France" },
167 { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" },
168 { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" },
169 { 0x51, "Giesecke & Devrient GmbH Germany" },
170 { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" },
171 { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" },
172 { 0x54, "Intel Corporation USA" },
173 { 0x55, "Microsensys GmbH Germany" },
174 { 0x56, "Sonix Technology Co., Ltd. Taiwan" },
175 { 0x57, "Qualcomm Technologies Inc USA" },
176 { 0x58, "Realtek Semiconductor Corp Taiwan" },
177 { 0x59, "Freevision Technologies Co. Ltd China" },
178 { 0x5A, "Giantec Semiconductor Inc. China" },
179 { 0x5B, "JSC Angstrem-T Russia" },
180 { 0x5C, "STARCHIP France" },
181 { 0x5D, "SPIRTECH France" },
182 { 0x5E, "GANTNER Electronic GmbH Austria" },
183 { 0x5F, "Nordic Semiconductor Norway" },
184 { 0x60, "Verisiti Inc USA" },
185 { 0x61, "Wearlinks Technology Inc. China" },
186 { 0x62, "Userstar Information Systems Co., Ltd Taiwan" },
187 { 0x63, "Pragmatic Printing Ltd. UK" },
188 { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico - LSI-TEC Brazil" },
189 { 0x65, "Tendyron Corporation China" },
190 { 0x66, "MUTO Smart Co., Ltd. Korea" },
191 { 0x67, "ON Semiconductor USA" },
192 { 0x68, "TUBITAK BILGEM Turkey" },
193 { 0x69, "Huada Semiconductor Co., Ltd China" },
194 { 0x6A, "SEVENEY France" },
195 { 0x6B, "ISSM France" },
196 { 0x6C, "Wisesec Ltd Israel" },
197 { 0x7C, "DB HiTek Co Ltd Korea" },
198 { 0x7D, "SATO Vicinity Australia" },
199 { 0x7E, "Holtek Taiwan" },
200 { 0x00, "no tag-info available" } // must be the last entry
203 // get a product description based on the UID
205 // returns description of the best match
206 const char *getTagInfo(uint8_t uid
) {
208 for (int i
= 0; i
< ARRAYLEN(manufactureMapping
); ++i
) {
209 if (uid
== manufactureMapping
[i
].uid
) {
210 return manufactureMapping
[i
].desc
;
214 //No match, return default
215 return manufactureMapping
[ARRAYLEN(manufactureMapping
) - 1].desc
;
218 static const hintAIDList_t hintAIDList
[] = {
219 // AID, AID len, name, hint - how to use
220 { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "hf fido" },
221 { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" },
222 { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" },
223 { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "emv" },
224 { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "emv" },
225 { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "hf cipurse" },
226 { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "hf mfdes" },
227 { "\x4F\x53\x45\x2E\x56\x41\x53\x2E\x30\x31", 10, "Apple VAS", "hf vas"},
230 // iso14a apdu input frame length
231 static uint16_t gs_frame_len
= 0;
232 static uint8_t gs_frames_num
= 0;
233 static uint16_t atsFSC
[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
235 static int CmdHF14AList(const char *Cmd
) {
236 return CmdTraceListAlias(Cmd
, "hf 14a", "14a -c");
239 int hf14a_getconfig(hf14a_config
*config
) {
240 if (!g_session
.pm3_present
) return PM3_ENOTTY
;
245 clearCommandBuffer();
247 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG
, NULL
, 0);
248 PacketResponseNG resp
;
249 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG
, &resp
, 2000)) {
250 PrintAndLogEx(WARNING
, "command execution time out");
253 memcpy(config
, resp
.data
.asBytes
, sizeof(hf14a_config
));
257 int hf14a_setconfig(hf14a_config
*config
, bool verbose
) {
258 if (!g_session
.pm3_present
) return PM3_ENOTTY
;
260 clearCommandBuffer();
261 if (config
!= NULL
) {
262 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG
, (uint8_t *)config
, sizeof(hf14a_config
));
264 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG
, NULL
, 0);
267 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG
, NULL
, 0);
273 static int hf_14a_config_example(void) {
274 PrintAndLogEx(NORMAL
, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:");
275 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 1k 4b UID")":");
276 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
277 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869"));
278 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
279 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 4k 4b UID")":");
280 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
281 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344441802006263646566676869"));
282 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
283 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 1k 7b UID")":");
284 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip"));
285 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566084400626364656667"));
286 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
287 PrintAndLogEx(NORMAL
, _CYAN_(" MFC 4k 7b UID")":");
288 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip"));
289 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566184200626364656667"));
290 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
291 PrintAndLogEx(NORMAL
, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":");
292 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip -rats skip"));
293 PrintAndLogEx(NORMAL
, _YELLOW_(" hf mfu setuid --uid 04112233445566"));
294 PrintAndLogEx(NORMAL
, _YELLOW_(" hf 14a config --std"));
297 static int CmdHf14AConfig(const char *Cmd
) {
298 if (!g_session
.pm3_present
) return PM3_ENOTTY
;
300 CLIParserContext
*ctx
;
301 CLIParserInit(&ctx
, "hf 14a config",
302 "Configure 14a settings (use with caution)\n"
303 " `-v` also prints examples for reviving Gen2 cards",
304 "hf 14a config -> Print current configuration\n"
305 "hf 14a config --std -> Reset default configuration (follow standard)\n"
306 "hf 14a config --atqa std -> Follow standard\n"
307 "hf 14a config --atqa force -> Force execution of anticollision\n"
308 "hf 14a config --atqa skip -> Skip anticollision\n"
309 "hf 14a config --bcc std -> Follow standard\n"
310 "hf 14a config --bcc fix -> Fix bad BCC in anticollision\n"
311 "hf 14a config --bcc ignore -> Ignore bad BCC and use it as such\n"
312 "hf 14a config --cl2 std -> Follow standard\n"
313 "hf 14a config --cl2 force -> Execute CL2\n"
314 "hf 14a config --cl2 skip -> Skip CL2\n"
315 "hf 14a config --cl3 std -> Follow standard\n"
316 "hf 14a config --cl3 force -> Execute CL3\n"
317 "hf 14a config --cl3 skip -> Skip CL3\n"
318 "hf 14a config --rats std -> Follow standard\n"
319 "hf 14a config --rats force -> Execute RATS\n"
320 "hf 14a config --rats skip -> Skip RATS");
324 arg_str0(NULL
, "atqa", "<std|force|skip>", "Configure ATQA<>anticollision behavior"),
325 arg_str0(NULL
, "bcc", "<std|fix|ignore>", "Configure BCC behavior"),
326 arg_str0(NULL
, "cl2", "<std|force|skip>", "Configure SAK<>CL2 behavior"),
327 arg_str0(NULL
, "cl3", "<std|force|skip>", "Configure SAK<>CL3 behavior"),
328 arg_str0(NULL
, "rats", "<std|force|skip>", "Configure RATS behavior"),
329 arg_lit0(NULL
, "std", "Reset default configuration: follow all standard"),
330 arg_lit0("v", "verbose", "verbose output"),
333 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
334 bool defaults
= arg_get_lit(ctx
, 6);
337 int atqa
= defaults
? 0 : -1;
338 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)value
, sizeof(value
), &vlen
);
340 if (strcmp(value
, "std") == 0) atqa
= 0;
341 else if (strcmp(value
, "force") == 0) atqa
= 1;
342 else if (strcmp(value
, "skip") == 0) atqa
= 2;
344 PrintAndLogEx(ERR
, "atqa argument must be 'std', 'force', or 'skip'");
349 int bcc
= defaults
? 0 : -1;
350 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)value
, sizeof(value
), &vlen
);
352 if (strcmp(value
, "std") == 0) bcc
= 0;
353 else if (strcmp(value
, "fix") == 0) bcc
= 1;
354 else if (strcmp(value
, "ignore") == 0) bcc
= 2;
356 PrintAndLogEx(ERR
, "bcc argument must be 'std', 'fix', or 'ignore'");
361 int cl2
= defaults
? 0 : -1;
362 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)value
, sizeof(value
), &vlen
);
364 if (strcmp(value
, "std") == 0) cl2
= 0;
365 else if (strcmp(value
, "force") == 0) cl2
= 1;
366 else if (strcmp(value
, "skip") == 0) cl2
= 2;
368 PrintAndLogEx(ERR
, "cl2 argument must be 'std', 'force', or 'skip'");
373 int cl3
= defaults
? 0 : -1;
374 CLIParamStrToBuf(arg_get_str(ctx
, 4), (uint8_t *)value
, sizeof(value
), &vlen
);
376 if (strcmp(value
, "std") == 0) cl3
= 0;
377 else if (strcmp(value
, "force") == 0) cl3
= 1;
378 else if (strcmp(value
, "skip") == 0) cl3
= 2;
380 PrintAndLogEx(ERR
, "cl3 argument must be 'std', 'force', or 'skip'");
385 int rats
= defaults
? 0 : -1;
386 CLIParamStrToBuf(arg_get_str(ctx
, 5), (uint8_t *)value
, sizeof(value
), &vlen
);
388 if (strcmp(value
, "std") == 0) rats
= 0;
389 else if (strcmp(value
, "force") == 0) rats
= 1;
390 else if (strcmp(value
, "skip") == 0) rats
= 2;
392 PrintAndLogEx(ERR
, "rats argument must be 'std', 'force', or 'skip'");
398 bool verbose
= arg_get_lit(ctx
, 7);
403 if (strlen(Cmd
) == 0) {
404 return hf14a_setconfig(NULL
, verbose
);
408 hf_14a_config_example();
411 hf14a_config config
= {
412 .forceanticol
= atqa
,
419 return hf14a_setconfig(&config
, verbose
);
422 static const char *get_uid_type(iso14a_card_select_t
*card
) {
424 static char s
[60] = {0};
425 memset(s
, 0, sizeof(s
));
427 switch (card
->uidlen
) {
429 if (card
->uid
[0] == 0x08) {
430 sprintf(s
, " ( RID - random ID )");
431 } else if ((card
->uid
[0] & 0xF) == 0xF) {
432 sprintf(s
, " ( FNUID, fixed, non-unique ID )");
433 } else if (card
->uid
[0] == 0x88) {
434 sprintf(s
, " ( Cascade tag - not final )");
435 } else if (card
->uid
[0] == 0xF8) {
436 sprintf(s
, " ( RFU )");
438 sprintf(s
, " ( ONUID, re-used )");
443 sprintf(s
, " ( double )");
447 sprintf(s
, " ( triple )");
456 int Hf14443_4aGetCardData(iso14a_card_select_t
*card
) {
458 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
, 0, 0, NULL
, 0);
459 PacketResponseNG resp
;
460 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
461 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
465 memcpy(card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
467 uint64_t select_status
= resp
.oldarg
[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
469 if (select_status
== 0) {
470 PrintAndLogEx(ERR
, "iso14443a card select failed");
474 if (select_status
== 2) {
475 PrintAndLogEx(ERR
, "Card doesn't support iso14443-4 mode");
479 if (select_status
== 3) {
480 PrintAndLogEx(INFO
, "Card doesn't support standard iso14443-3 anticollision");
482 if (card
->atqa
[1] == 0x0C && card
->atqa
[0] == 0x00) {
483 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf topaz info`"));
485 PrintAndLogEx(SUCCESS
, "\tATQA : %02X %02X", card
->atqa
[1], card
->atqa
[0]);
490 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(card
->uid
, card
->uidlen
));
491 PrintAndLogEx(SUCCESS
, "ATQA: %02X %02X", card
->atqa
[1], card
->atqa
[0]);
492 PrintAndLogEx(SUCCESS
, " SAK: %02X [%" PRIu64
"]", card
->sak
, resp
.oldarg
[0]);
494 // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
495 if (card
->ats_len
< 3) {
496 PrintAndLogEx(INFO
, "Error ATS length(%d) : %s", card
->ats_len
, sprint_hex(card
->ats
, card
->ats_len
));
497 return PM3_ECARDEXCHANGE
;
500 if (card
->ats_len
== card
->ats
[0] + 2)
501 PrintAndLogEx(SUCCESS
, " ATS: [%d] %s", card
->ats
[0], sprint_hex(card
->ats
, card
->ats
[0]));
503 PrintAndLogEx(SUCCESS
, " ATS: [%d] %s", card
->ats_len
, sprint_hex(card
->ats
, card
->ats_len
));
508 iso14a_polling_parameters_t
iso14a_get_polling_parameters(bool use_ecp
, bool use_magsafe
) {
509 // Extra 100ms give enough time for Apple (ECP) devices to proccess field info and make a decision
511 if (use_ecp
&& use_magsafe
) {
512 iso14a_polling_parameters_t full_polling_parameters
= {
513 .frames
= { WUPA_FRAME
, ECP_FRAME
, MAGWUPA1_FRAME
, MAGWUPA2_FRAME
, MAGWUPA3_FRAME
, MAGWUPA4_FRAME
},
517 return full_polling_parameters
;
518 } else if (use_ecp
) {
519 iso14a_polling_parameters_t ecp_polling_parameters
= {
520 .frames
= { WUPA_FRAME
, ECP_FRAME
},
524 return ecp_polling_parameters
;
525 } else if (use_magsafe
) {
526 iso14a_polling_parameters_t magsafe_polling_parameters
= {
527 .frames
= { WUPA_FRAME
, MAGWUPA1_FRAME
, MAGWUPA2_FRAME
, MAGWUPA3_FRAME
, MAGWUPA4_FRAME
},
531 return magsafe_polling_parameters
;
534 iso14a_polling_parameters_t wupa_polling_parameters
= {
535 .frames
= { WUPA_FRAME
},
539 return wupa_polling_parameters
;
542 static int CmdHF14AReader(const char *Cmd
) {
543 CLIParserContext
*ctx
;
544 CLIParserInit(&ctx
, "hf 14a reader",
545 "Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
547 "hf 14a reader -@ -> Continuous mode\n"
548 "hf 14a reader --ecp -> trigger apple enhanced contactless polling\n"
549 "hf 14a reader --mag -> trigger apple magsafe polling\n"
554 arg_lit0("k", "keep", "keep the field active after command executed"),
555 arg_lit0("s", "silent", "silent (no messages)"),
556 arg_lit0(NULL
, "drop", "just drop the signal field"),
557 arg_lit0(NULL
, "skip", "ISO14443-3 select only (skip RATS)"),
558 arg_lit0(NULL
, "ecp", "Use enhanced contactless polling"),
559 arg_lit0(NULL
, "mag", "Use Apple magsafe polling"),
560 arg_lit0("@", NULL
, "continuous reader mode"),
561 arg_lit0("w", "wait", "wait for card"),
564 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
566 bool disconnectAfter
= true;
567 if (arg_get_lit(ctx
, 1)) {
568 disconnectAfter
= false;
571 bool silent
= arg_get_lit(ctx
, 2);
573 uint32_t cm
= ISO14A_CONNECT
;
574 if (arg_get_lit(ctx
, 3)) {
575 cm
&= ~ISO14A_CONNECT
;
578 if (arg_get_lit(ctx
, 4)) {
579 cm
|= ISO14A_NO_RATS
;
582 bool use_ecp
= arg_get_lit(ctx
, 5);
583 bool use_magsafe
= arg_get_lit(ctx
, 6);
585 iso14a_polling_parameters_t
*polling_parameters
= NULL
;
586 iso14a_polling_parameters_t parameters
= iso14a_get_polling_parameters(use_ecp
, use_magsafe
);
587 if (use_ecp
|| use_magsafe
) {
588 cm
|= ISO14A_USE_CUSTOM_POLLING
;
589 polling_parameters
= ¶meters
;
592 bool continuous
= arg_get_lit(ctx
, 7);
593 bool wait
= arg_get_lit(ctx
, 8);
597 if (disconnectAfter
== false) {
598 cm
|= ISO14A_NO_DISCONNECT
;
602 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
605 int res
= PM3_SUCCESS
;
607 clearCommandBuffer();
609 if ((cm
& ISO14A_USE_CUSTOM_POLLING
) == ISO14A_USE_CUSTOM_POLLING
) {
610 SendCommandMIX(CMD_HF_ISO14443A_READER
, cm
, 0, 0, (uint8_t *)polling_parameters
, sizeof(iso14a_polling_parameters_t
));
612 SendCommandMIX(CMD_HF_ISO14443A_READER
, cm
, 0, 0, NULL
, 0);
615 if ((cm
& ISO14A_CONNECT
) == ISO14A_CONNECT
) {
616 PacketResponseNG resp
;
617 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
623 iso14a_card_select_t card
;
624 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
630 3: proprietary Anticollision
632 uint64_t select_status
= resp
.oldarg
[0];
634 found
= (select_status
!= 0);
636 if (select_status
== 0) {
642 if (select_status
== 3) {
643 if (!(silent
&& continuous
)) {
644 PrintAndLogEx(INFO
, "Card doesn't support standard iso14443-3 anticollision");
647 if (card
.atqa
[1] == 0x0C && card
.atqa
[0] == 0x00) {
648 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf topaz info`"));
650 PrintAndLogEx(SUCCESS
, "ATQA: %02X %02X", card
.atqa
[1], card
.atqa
[0]);
652 PrintAndLogEx(NORMAL
, "");
659 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(card
.uid
, card
.uidlen
));
661 if (!(silent
&& continuous
)) {
662 PrintAndLogEx(SUCCESS
, "ATQA: " _GREEN_("%02X %02X"), card
.atqa
[1], card
.atqa
[0]);
663 PrintAndLogEx(SUCCESS
, " SAK: " _GREEN_("%02X [%" PRIu64
"]"), card
.sak
, resp
.oldarg
[0]);
665 if (card
.ats_len
>= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
666 if (card
.ats_len
== card
.ats
[0] + 2)
667 PrintAndLogEx(SUCCESS
, " ATS: " _GREEN_("%s"), sprint_hex(card
.ats
, card
.ats
[0]));
669 PrintAndLogEx(SUCCESS
, " ATS: [%d] " _GREEN_("%s"), card
.ats_len
, sprint_hex(card
.ats
, card
.ats_len
));
672 PrintAndLogEx(NORMAL
, "");
674 if ((disconnectAfter
== false) && (silent
== false)) {
675 PrintAndLogEx(SUCCESS
, "Card is selected. You can now start sending commands");
680 res
= handle_hf_plot(false);
681 if (res
!= PM3_SUCCESS
) {
682 PrintAndLogEx(DEBUG
, "plot failed");
686 if (kbd_enter_pressed()) {
690 } while (continuous
|| (wait
&& (!found
)));
692 if (disconnectAfter
== false) {
693 if (silent
== false) {
694 PrintAndLogEx(INFO
, "field is on");
704 static int CmdHF14AInfo(const char *Cmd
) {
706 bool do_nack_test
= false;
707 bool do_aid_search
= false;
709 CLIParserContext
*ctx
;
710 CLIParserInit(&ctx
, "hf 14a info",
711 "This command makes more extensive tests against a ISO14443a tag in order to collect information",
712 "hf 14a info -nsv -> shows full information about the card\n");
716 arg_lit0("v", "verbose", "verbose output"),
717 arg_lit0("n", "nacktest", "test for nack bug"),
718 arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
721 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
723 verbose
= arg_get_lit(ctx
, 1);
724 do_nack_test
= arg_get_lit(ctx
, 2);
725 do_aid_search
= arg_get_lit(ctx
, 3);
729 infoHF14A(verbose
, do_nack_test
, do_aid_search
);
733 // Collect ISO14443 Type A UIDs
734 static int CmdHF14ACUIDs(const char *Cmd
) {
735 CLIParserContext
*ctx
;
736 CLIParserInit(&ctx
, "hf 14a cuids",
737 "Collect n>0 ISO14443-a UIDs in one go",
738 "hf 14a cuids -n 5 --> Collect 5 UIDs");
742 arg_int0("n", "num", "<dec>", "Number of UIDs to collect"),
745 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
747 // requested number of UIDs
748 // collect at least 1 (e.g. if no parameter was given)
749 int n
= arg_get_int_def(ctx
, 1, 1);
753 uint64_t t1
= msclock();
754 PrintAndLogEx(SUCCESS
, "collecting %d UIDs", n
);
757 for (int i
= 0; i
< n
; i
++) {
759 if (kbd_enter_pressed()) {
760 PrintAndLogEx(WARNING
, "aborted via keyboard!\n");
764 // execute anticollision procedure
765 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
766 PacketResponseNG resp
;
768 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
769 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
773 iso14a_card_select_t
*card
= (iso14a_card_select_t
*) resp
.data
.asBytes
;
775 // check if command failed
776 if (resp
.oldarg
[0] == 0) {
777 PrintAndLogEx(WARNING
, "card select failed.");
780 for (uint16_t m
= 0; m
< card
->uidlen
; m
++) {
782 snprintf(uid_string
+ offset
, sizeof(uid_string
) - offset
, "%02X", card
->uid
[m
]);
784 PrintAndLogEx(SUCCESS
, "%s", uid_string
);
787 PrintAndLogEx(SUCCESS
, "end: %" PRIu64
" seconds", (msclock() - t1
) / 1000);
791 // ## simulate iso14443a tag
792 int CmdHF14ASim(const char *Cmd
) {
793 CLIParserContext
*ctx
;
794 CLIParserInit(&ctx
, "hf 14a sim",
795 "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
796 "Use type 7 for Mifare Ultralight EV1, Amiibo (NTAG215 pack 0x8080)",
797 "hf 14a sim -t 1 --uid 11223344 -> MIFARE Classic 1k\n"
798 "hf 14a sim -t 2 -> MIFARE Ultralight\n"
799 "hf 14a sim -t 3 -> MIFARE Desfire\n"
800 "hf 14a sim -t 4 -> ISO/IEC 14443-4\n"
801 "hf 14a sim -t 5 -> MIFARE Tnp3xxx\n"
802 "hf 14a sim -t 6 -> MIFARE Mini\n"
803 "hf 14a sim -t 7 -> MFU EV1 / NTAG 215 Amiibo\n"
804 "hf 14a sim -t 8 -> MIFARE Classic 4k\n"
805 "hf 14a sim -t 9 -> FM11RF005SH Shanghai Metro\n"
806 "hf 14a sim -t 10 -> ST25TA IKEA Rothult\n"
807 "hf 14a sim -t 11 -> Javacard (JCOP)\n"
808 "hf 14a sim -t 12 -> 4K Seos card\n"
813 arg_int1("t", "type", "<1-12> ", "Simulation type to use"),
814 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
815 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
816 arg_lit0("x", NULL
, "Performs the 'reader attack', nr/ar attack against a reader"),
817 arg_lit0(NULL
, "sk", "Fill simulator keys from found keys"),
818 arg_lit0("v", "verbose", "verbose output"),
821 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
823 int tagtype
= arg_get_int_def(ctx
, 1, 1);
826 uint8_t uid
[10] = {0};
827 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
830 bool useUIDfromEML
= true;
833 FLAG_SET_UID_IN_DATA(flags
, uid_len
);
834 if (IS_FLAG_UID_IN_EMUL(flags
)) {
835 PrintAndLogEx(ERR
, "Please specify a 4, 7, or 10 byte UID");
839 PrintAndLogEx(SUCCESS
, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len
, sprint_hex(uid
, uid_len
));
840 useUIDfromEML
= false;
843 uint8_t exitAfterNReads
= arg_get_int_def(ctx
, 3, 0);
845 if (arg_get_lit(ctx
, 4)) {
846 flags
|= FLAG_NR_AR_ATTACK
;
849 bool setEmulatorMem
= arg_get_lit(ctx
, 5);
850 bool verbose
= arg_get_lit(ctx
, 6);
855 PrintAndLogEx(ERR
, "Undefined tag %d", tagtype
);
860 FLAG_SET_UID_IN_EMUL(flags
);
870 payload
.tagtype
= tagtype
;
871 payload
.flags
= flags
;
872 payload
.exitAfter
= exitAfterNReads
;
873 memcpy(payload
.uid
, uid
, uid_len
);
875 clearCommandBuffer();
876 SendCommandNG(CMD_HF_ISO14443A_SIMULATE
, (uint8_t *)&payload
, sizeof(payload
));
877 PacketResponseNG resp
= {0};
879 sector_t
*k_sector
= NULL
;
880 size_t k_sectors_cnt
= MIFARE_4K_MAXSECTOR
;
882 PrintAndLogEx(INFO
, "Press " _GREEN_("pm3 button") " to abort simulation");
883 bool keypress
= kbd_enter_pressed();
884 while (keypress
== false) {
886 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE
, &resp
, 1500) == 0)
889 if (resp
.status
!= PM3_SUCCESS
)
892 if ((flags
& FLAG_NR_AR_ATTACK
) != FLAG_NR_AR_ATTACK
)
895 const nonces_t
*data
= (nonces_t
*)resp
.data
.asBytes
;
896 readerAttack(k_sector
, k_sectors_cnt
, data
[0], setEmulatorMem
, verbose
);
898 keypress
= kbd_enter_pressed();
902 if ((flags
& FLAG_NR_AR_ATTACK
) == FLAG_NR_AR_ATTACK
) {
903 // inform device to break the sim loop since client has exited
904 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
908 PrintAndLogEx(INFO
, "Done!");
912 int CmdHF14ASniff(const char *Cmd
) {
913 CLIParserContext
*ctx
;
914 CLIParserInit(&ctx
, "hf 14a sniff",
915 "Sniff the communication between reader and tag\n"
916 "Use `hf 14a list` to view collected data.",
917 " hf 14a sniff -c -r"
921 arg_lit0("c", "card", "triggered by first data from card"),
922 arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ, WUP)"),
923 arg_lit0("i", "interactive", "Console will not be returned until sniff finishes or is aborted"),
926 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
930 if (arg_get_lit(ctx
, 1)) {
934 if (arg_get_lit(ctx
, 2)) {
938 bool interactive
= arg_get_lit(ctx
, 3);
941 clearCommandBuffer();
942 SendCommandNG(CMD_HF_ISO14443A_SNIFF
, (uint8_t *)¶m
, sizeof(uint8_t));
944 PrintAndLogEx(INFO
, "Press " _GREEN_("pm3 button") " to abort sniffing");
947 PacketResponseNG resp
;
948 WaitForResponse(CMD_HF_ISO14443A_SNIFF
, &resp
);
949 PrintAndLogEx(INFO
, "Done!");
950 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf 14a list")"` to view captured tracelog");
951 PrintAndLogEx(HINT
, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
956 int ExchangeRAW14a(uint8_t *datain
, int datainlen
, bool activateField
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
, bool silentMode
) {
962 // select with no disconnect and set gs_frame_len
963 int selres
= SelectCard14443A_4(false, !silentMode
, NULL
);
965 if (selres
!= PM3_SUCCESS
) {
971 cmdc
|= ISO14A_NO_DISCONNECT
;
974 uint8_t data
[PM3_CMD_DATA_SIZE
] = { 0x0a | gs_frames_num
, 0x00 };
977 int min
= MIN((PM3_CMD_DATA_SIZE
- 2), (datainlen
& 0x1FF));
978 memcpy(&data
[2], datain
, min
);
979 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| cmdc
, (datainlen
& 0xFFFF) + 2, 0, data
, min
+ 2);
982 PacketResponseNG resp
;
983 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
984 recv
= resp
.data
.asBytes
;
985 int iLen
= resp
.oldarg
[0];
988 if (silentMode
== false) {
989 PrintAndLogEx(ERR
, "No card response");
991 return PM3_ECARDEXCHANGE
;
994 *dataoutlen
= iLen
- 2;
995 if (*dataoutlen
< 0) {
999 if (maxdataoutlen
&& *dataoutlen
> maxdataoutlen
) {
1000 if (silentMode
== false) {
1001 PrintAndLogEx(ERR
, "Buffer too small(%d). Needs %d bytes", *dataoutlen
, maxdataoutlen
);
1006 if (recv
[0] != data
[0]) {
1007 if (silentMode
== false) {
1008 PrintAndLogEx(ERR
, "iso14443-4 framing error. Card send %2x must be %2x", recv
[0], data
[0]);
1013 memcpy(dataout
, &recv
[2], *dataoutlen
);
1017 if (silentMode
== false) {
1018 PrintAndLogEx(ERR
, "ISO 14443A CRC error");
1024 if (silentMode
== false) {
1025 PrintAndLogEx(ERR
, "Reply timeout.");
1027 return PM3_ETIMEOUT
;
1033 int SelectCard14443A_4_WithParameters(bool disconnect
, bool verbose
, iso14a_card_select_t
*card
, iso14a_polling_parameters_t
*polling_parameters
) {
1034 // global vars should be prefixed with g_
1039 memset(card
, 0, sizeof(iso14a_card_select_t
));
1044 // Anticollision + SELECT card
1045 PacketResponseNG resp
;
1046 if (polling_parameters
!= NULL
) {
1047 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
| ISO14A_USE_CUSTOM_POLLING
, 0, 0, (uint8_t *)polling_parameters
, sizeof(iso14a_polling_parameters_t
));
1049 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
1052 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2000) == false) {
1053 PrintAndLogEx(WARNING
, "command execution time out");
1054 return PM3_ETIMEOUT
;
1058 if (resp
.oldarg
[0] == 0) {
1060 PrintAndLogEx(WARNING
, "No ISO14443-A Card in field");
1062 return PM3_ECARDEXCHANGE
;
1065 if (resp
.oldarg
[0] != 1 && resp
.oldarg
[0] != 2) {
1066 PrintAndLogEx(WARNING
, "Card not in iso14443-4, res=%" PRId64
".", resp
.oldarg
[0]);
1067 return PM3_ECARDEXCHANGE
;
1070 iso14a_card_select_t
*vcard
= (iso14a_card_select_t
*) resp
.data
.asBytes
;
1072 memcpy(card
, vcard
, sizeof(iso14a_card_select_t
));
1075 if (resp
.oldarg
[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
1077 uint8_t rats
[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
1078 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_DISCONNECT
, sizeof(rats
), 0, rats
, sizeof(rats
));
1079 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
1080 PrintAndLogEx(WARNING
, "command execution time out");
1081 return PM3_ETIMEOUT
;
1084 if (resp
.oldarg
[0] == 0) { // ats_len
1086 PrintAndLogEx(FAILED
, "Can't get ATS");
1088 return PM3_ECARDEXCHANGE
;
1091 // get frame length from ATS in data field
1092 if (resp
.oldarg
[0] > 1) {
1093 uint8_t fsci
= resp
.data
.asBytes
[1] & 0x0f;
1094 if (fsci
< ARRAYLEN(atsFSC
)) {
1095 gs_frame_len
= atsFSC
[fsci
];
1100 card
->ats_len
= resp
.oldarg
[0];
1101 memcpy(card
->ats
, resp
.data
.asBytes
, card
->ats_len
);
1104 // get frame length from ATS in card data structure
1105 if (vcard
->ats_len
> 1) {
1106 uint8_t fsci
= vcard
->ats
[1] & 0x0f;
1107 if (fsci
< ARRAYLEN(atsFSC
)) {
1108 gs_frame_len
= atsFSC
[fsci
];
1113 SetISODEPState(ISODEP_NFCA
);
1122 int SelectCard14443A_4(bool disconnect
, bool verbose
, iso14a_card_select_t
*card
) {
1123 return SelectCard14443A_4_WithParameters(disconnect
, verbose
, card
, NULL
);
1126 static int CmdExchangeAPDU(bool chainingin
, const uint8_t *datain
, int datainlen
, bool activateField
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
, bool *chainingout
) {
1127 *chainingout
= false;
1129 size_t timeout
= 1500;
1130 if (activateField
) {
1131 // select with no disconnect and set gs_frame_len
1132 iso14a_card_select_t card
;
1133 int selres
= SelectCard14443A_4(false, true, &card
);
1134 if (selres
!= PM3_SUCCESS
) {
1138 // Extract FWI and SFGI from ATS and increase timeout by the indicated values
1139 // for most cards these values are trivially small so will make no practical
1140 // difference but some "cards" like hf_cardhopper overwrite these to their
1141 // maximum values resulting in ~5 seconds each which can cause timeouts if we
1143 if (((card
.ats
[1] & 0x20) == 0x20) && card
.ats_len
> 2) {
1144 // TB is present in ATS
1147 if ((card
.ats
[1] & 0x10) == 0x10 && card
.ats_len
> 3) {
1148 // TA is also present, so TB at ats[3]
1151 // TA is not present, so TB is at ats[2]
1155 uint8_t fwi
= (tb
& 0xF0) >> 4;
1157 uint32_t fwt
= 256 * 16 * (1 << fwi
);
1161 uint8_t sfgi
= tb
& 0x0F;
1163 uint32_t sgft
= 256 * 16 * (1 << sfgi
);
1171 cmdc
= ISO14A_SEND_CHAINING
;
1173 // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
1174 // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
1175 // here length PM3_CMD_DATA_SIZE=512
1176 // timeout must be authomatically set by "get ATS"
1178 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_APDU
| ISO14A_NO_DISCONNECT
| cmdc
, (datainlen
& 0x1FF), 0, datain
, datainlen
& 0x1FF);
1180 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_APDU
| ISO14A_NO_DISCONNECT
| cmdc
, 0, 0, NULL
, 0);
1182 PacketResponseNG resp
;
1184 if (WaitForResponseTimeout(CMD_ACK
, &resp
, timeout
)) {
1185 const uint8_t *recv
= resp
.data
.asBytes
;
1186 int iLen
= resp
.oldarg
[0];
1187 uint8_t res
= resp
.oldarg
[1];
1189 int dlen
= iLen
- 2;
1192 *dataoutlen
+= dlen
;
1194 if (maxdataoutlen
&& *dataoutlen
> maxdataoutlen
) {
1195 PrintAndLogEx(DEBUG
, "ERR: APDU: Buffer too small(%d), needs %d bytes", *dataoutlen
, maxdataoutlen
);
1196 return PM3_EAPDU_FAIL
;
1200 if ((res
& 0xF2) == 0xA2) {
1202 *chainingout
= true;
1207 PrintAndLogEx(DEBUG
, "ERR: APDU: No APDU response");
1208 return PM3_EAPDU_FAIL
;
1211 // check apdu length
1212 if (iLen
< 2 && iLen
>= 0) {
1213 PrintAndLogEx(DEBUG
, "ERR: APDU: Small APDU response, len %d", iLen
);
1214 return PM3_EAPDU_FAIL
;
1219 PrintAndLogEx(DEBUG
, "ERR: APDU: Block type mismatch");
1220 return PM3_EAPDU_FAIL
;
1223 memcpy(dataout
, recv
, dlen
);
1226 if ((res
& 0x10) != 0) {
1227 *chainingout
= true;
1232 PrintAndLogEx(DEBUG
, "ERR: APDU: ISO 14443A CRC error");
1233 return PM3_EAPDU_FAIL
;
1236 PrintAndLogEx(DEBUG
, "ERR: APDU: Reply timeout");
1237 return PM3_EAPDU_FAIL
;
1243 int ExchangeAPDU14a(const uint8_t *datain
, int datainlen
, bool activateField
, bool leaveSignalON
, uint8_t *dataout
, int maxdataoutlen
, int *dataoutlen
) {
1245 bool chaining
= false;
1248 // 3 byte here - 1b framing header, 2b crc16
1249 if (g_apdu_in_framing_enable
&&
1250 ((gs_frame_len
&& (datainlen
> gs_frame_len
- 3)) || (datainlen
> PM3_CMD_DATA_SIZE
- 3))) {
1254 bool vActivateField
= activateField
;
1257 int vlen
= MIN(gs_frame_len
- 3, datainlen
- clen
);
1258 bool chainBlockNotLast
= ((clen
+ vlen
) < datainlen
);
1261 res
= CmdExchangeAPDU(chainBlockNotLast
, &datain
[clen
], vlen
, vActivateField
, dataout
, maxdataoutlen
, dataoutlen
, &chaining
);
1262 if (res
!= PM3_SUCCESS
) {
1263 if (leaveSignalON
== false)
1269 // check R-block ACK
1270 // TODO check this one...
1271 if ((*dataoutlen
== 0) && (chaining
!= chainBlockNotLast
)) {
1272 if (leaveSignalON
== false)
1279 vActivateField
= false;
1281 if (clen
!= datainlen
) {
1282 PrintAndLogEx(ERR
, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen
, clen
, *dataoutlen
);
1286 } while (clen
< datainlen
);
1289 res
= CmdExchangeAPDU(false, datain
, datainlen
, activateField
, dataout
, maxdataoutlen
, dataoutlen
, &chaining
);
1290 if (res
!= PM3_SUCCESS
) {
1291 if (leaveSignalON
== false) {
1299 // I-block with chaining
1300 res
= CmdExchangeAPDU(false, NULL
, 0, false, &dataout
[*dataoutlen
], maxdataoutlen
, dataoutlen
, &chaining
);
1301 if (res
!= PM3_SUCCESS
) {
1302 if (leaveSignalON
== false) {
1309 if (leaveSignalON
== false) {
1316 // ISO14443-4. 7. Half-duplex block transmission protocol
1317 static int CmdHF14AAPDU(const char *Cmd
) {
1318 CLIParserContext
*ctx
;
1319 CLIParserInit(&ctx
, "hf 14a apdu",
1320 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL).\n"
1321 "Works with all APDU types from ISO 7816-4:2013\n"
1324 " `-m` and `-d` goes hand in hand\n"
1325 " -m <CLA INS P1 P2> -d 325041592E5359532E4444463031\n"
1329 " use `-d` with complete APDU data\n"
1330 " -d 00A404000E325041592E5359532E444446303100",
1331 "hf 14a apdu -st -d 00A404000E325041592E5359532E444446303100\n"
1332 "hf 14a apdu -sd -d 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
1333 "hf 14a apdu -sm 00A40400 -d 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
1334 "hf 14a apdu -sm 00A40400 -d 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
1336 void *argtable
[] = {
1338 arg_lit0("s", "select", "activate field and select card"),
1339 arg_lit0("k", "keep", "keep signal field ON after receive"),
1340 arg_lit0("t", "tlv", "decode TLV"),
1341 arg_lit0(NULL
, "decode", "decode APDU request"),
1342 arg_str0("m", "make", "<hex>", "APDU header, 4 bytes <CLA INS P1 P2>"),
1343 arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
1344 arg_int0("l", "le", "<dec>", "Le APDU parameter if `m` parameter included"),
1345 arg_strx1("d", "data", "<hex>", "full APDU package or data if `m` parameter included"),
1348 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1350 bool activateField
= arg_get_lit(ctx
, 1);
1351 bool leaveSignalON
= arg_get_lit(ctx
, 2);
1352 bool decodeTLV
= arg_get_lit(ctx
, 3);
1353 bool decodeAPDU
= arg_get_lit(ctx
, 4);
1355 uint8_t header
[PM3_CMD_DATA_SIZE
];
1357 CLIGetHexWithReturn(ctx
, 5, header
, &headerlen
);
1359 bool makeAPDU
= (headerlen
> 0);
1361 if (makeAPDU
&& headerlen
!= 4) {
1362 PrintAndLogEx(ERR
, "header length must be 4 bytes instead of %d", headerlen
);
1366 bool extendedAPDU
= arg_get_lit(ctx
, 6);
1367 int le
= arg_get_int_def(ctx
, 7, 0);
1369 uint8_t data
[PM3_CMD_DATA_SIZE
];
1373 uint8_t apdudata
[PM3_CMD_DATA_SIZE
] = {0};
1374 int apdudatalen
= 0;
1376 CLIGetHexBLessWithReturn(ctx
, 8, apdudata
, &apdudatalen
, 1 + 2);
1379 apdu
.cla
= header
[0];
1380 apdu
.ins
= header
[1];
1381 apdu
.p1
= header
[2];
1382 apdu
.p2
= header
[3];
1384 apdu
.lc
= apdudatalen
;
1385 apdu
.data
= apdudata
;
1387 apdu
.extended_apdu
= extendedAPDU
;
1390 if (APDUEncode(&apdu
, data
, &datalen
)) {
1391 PrintAndLogEx(ERR
, "can't make apdu with provided parameters.");
1398 PrintAndLogEx(ERR
, "make mode not set but here `e` option.");
1403 PrintAndLogEx(ERR
, "make mode not set but here `l` option.");
1408 // len = data + PCB(1b) + CRC(2b)
1409 CLIGetHexBLessWithReturn(ctx
, 8, data
, &datalen
, 1 + 2);
1413 PrintAndLogEx(SUCCESS
, _YELLOW_("%s%s%s"),
1414 activateField
? "select card" : "",
1415 leaveSignalON
? ", keep field on" : "",
1416 decodeTLV
? ", TLV" : ""
1418 PrintAndLogEx(SUCCESS
, ">>> %s", sprint_hex_inrow(data
, datalen
));
1423 if (APDUDecode(data
, datalen
, &apdu
) == 0)
1426 PrintAndLogEx(WARNING
, "can't decode APDU.");
1429 int res
= ExchangeAPDU14a(data
, datalen
, activateField
, leaveSignalON
, data
, PM3_CMD_DATA_SIZE
, &datalen
);
1430 if (res
!= PM3_SUCCESS
)
1433 PrintAndLogEx(SUCCESS
, "<<< %s | %s", sprint_hex_inrow(data
, datalen
), sprint_ascii(data
, datalen
));
1434 PrintAndLogEx(SUCCESS
, "<<< status: %02X %02X - %s", data
[datalen
- 2], data
[datalen
- 1], GetAPDUCodeDescription(data
[datalen
- 2], data
[datalen
- 1]));
1437 if (decodeTLV
&& datalen
> 4) {
1438 TLVPrintFromBuffer(data
, datalen
- 2);
1444 static int CmdHF14ACmdRaw(const char *Cmd
) {
1445 CLIParserContext
*ctx
;
1446 CLIParserInit(&ctx
, "hf 14a raw",
1447 "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
1448 "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
1449 "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
1450 "hf 14a raw --ecp -s -> send ECP before select\n"
1451 "Crypto1 session example, with special auth shortcut 6xxx<key>:\n"
1452 "hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF\n"
1453 "hf 14a raw --crypto1 -kc 3000\n"
1454 "hf 14a raw --crypto1 -kc 6007FFFFFFFFFFFF\n"
1455 "hf 14a raw --crypto1 -c 3007"
1458 void *argtable
[] = {
1460 arg_lit0("a", NULL
, "Active signal field ON without select"),
1461 arg_lit0("c", NULL
, "Calculate and append CRC"),
1462 arg_lit0("k", NULL
, "Keep signal field ON after receive"),
1463 arg_lit0("3", NULL
, "ISO14443-3 select only (skip RATS)"),
1464 arg_lit0("r", NULL
, "Do not read response"),
1465 arg_lit0("s", NULL
, "Active signal field ON with select"),
1466 arg_int0("t", "timeout", "<ms>", "Timeout in milliseconds"),
1467 arg_int0("b", NULL
, "<dec>", "Number of bits to send. Useful for send partial byte"),
1468 arg_lit0("v", "verbose", "Verbose output"),
1469 arg_lit0(NULL
, "ecp", "Use enhanced contactless polling"),
1470 arg_lit0(NULL
, "mag", "Use Apple magsafe polling"),
1471 arg_lit0(NULL
, "topaz", "Use Topaz protocol to send command"),
1472 arg_lit0(NULL
, "crypto1", "Use crypto1 session"),
1473 arg_strx1(NULL
, NULL
, "<hex>", "Raw bytes to send"),
1476 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1478 bool active
= arg_get_lit(ctx
, 1);
1479 bool crc
= arg_get_lit(ctx
, 2);
1480 bool keep_field_on
= arg_get_lit(ctx
, 3);
1481 bool no_rats
= arg_get_lit(ctx
, 4);
1482 bool reply
= (arg_get_lit(ctx
, 5) == false);
1483 bool active_select
= arg_get_lit(ctx
, 6);
1484 uint32_t timeout
= (uint32_t)arg_get_int_def(ctx
, 7, 0);
1485 uint16_t numbits
= (uint16_t)arg_get_int_def(ctx
, 8, 0);
1486 bool verbose
= arg_get_lit(ctx
, 9);
1487 bool use_ecp
= arg_get_lit(ctx
, 10);
1488 bool use_magsafe
= arg_get_lit(ctx
, 11);
1489 bool topazmode
= arg_get_lit(ctx
, 12);
1490 bool crypto1mode
= arg_get_lit(ctx
, 13);
1493 uint8_t data
[PM3_CMD_DATA_SIZE_MIX
] = {0};
1494 CLIGetHexWithReturn(ctx
, 14, data
, &datalen
);
1497 bool bTimeout
= (timeout
) ? true : false;
1499 // ensure we can add 2byte crc to input data
1500 if (datalen
>= sizeof(data
) + 2) {
1502 PrintAndLogEx(FAILED
, "Buffer is full, we can't add CRC to your data");
1507 if (crc
&& datalen
> 0 && datalen
< sizeof(data
) - 2) {
1508 uint8_t first
, second
;
1510 compute_crc(CRC_14443_B
, data
, datalen
, &first
, &second
);
1512 compute_crc(CRC_14443_A
, data
, datalen
, &first
, &second
);
1514 data
[datalen
++] = first
;
1515 data
[datalen
++] = second
;
1519 if (active
|| active_select
) {
1520 flags
|= ISO14A_CONNECT
;
1522 flags
|= ISO14A_NO_SELECT
;
1525 uint32_t argtimeout
= 0;
1527 #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
1528 flags
|= ISO14A_SET_TIMEOUT
;
1529 if (timeout
> MAX_TIMEOUT
) {
1530 timeout
= MAX_TIMEOUT
;
1531 PrintAndLogEx(INFO
, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
1533 argtimeout
= 13560000 / 1000 / (8 * 16) * timeout
; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
1536 if (keep_field_on
) {
1537 flags
|= ISO14A_NO_DISCONNECT
;
1541 flags
|= ISO14A_RAW
;
1545 flags
|= ISO14A_TOPAZMODE
;
1549 flags
|= ISO14A_CRYPTO1MODE
;
1550 if (numbits
> 0 || topazmode
|| use_ecp
|| use_magsafe
) {
1551 PrintAndLogEx(FAILED
, "crypto1 mode cannot be used with other modes or partial bytes");
1557 flags
|= ISO14A_NO_RATS
;
1560 // TODO: allow to use reader command with both data and polling configuration
1561 if (use_ecp
|| use_magsafe
) {
1562 PrintAndLogEx(WARNING
, "ECP and Magsafe not supported with this command at this moment. Instead use 'hf 14a reader -sk --ecp/--mag'");
1563 // flags |= ISO14A_USE_MAGSAFE;
1564 // flags |= ISO14A_USE_ECP;
1567 // Max buffer is PM3_CMD_DATA_SIZE_MIX
1568 datalen
= (datalen
> PM3_CMD_DATA_SIZE_MIX
) ? PM3_CMD_DATA_SIZE_MIX
: datalen
;
1570 clearCommandBuffer();
1571 SendCommandMIX(CMD_HF_ISO14443A_READER
, flags
, (datalen
& 0x1FF) | ((uint32_t)(numbits
<< 16)), argtimeout
, data
, datalen
);
1576 res
= waitCmd(true, timeout
, verbose
);
1577 if (res
== PM3_SUCCESS
&& datalen
> 0)
1578 waitCmd(false, timeout
, verbose
);
1583 static int waitCmd(bool i_select
, uint32_t timeout
, bool verbose
) {
1584 PacketResponseNG resp
;
1586 if (WaitForResponseTimeout(CMD_ACK
, &resp
, timeout
+ 1500)) {
1587 uint16_t len
= (resp
.oldarg
[0] & 0xFFFF);
1589 len
= (resp
.oldarg
[1] & 0xFFFF);
1592 PrintAndLogEx(SUCCESS
, "Card selected. UID[%u]:", len
);
1598 PrintAndLogEx(WARNING
, "Can't select card.");
1602 PrintAndLogEx(SUCCESS
, "received " _YELLOW_("%u") " bytes", len
);
1610 uint8_t *data
= resp
.data
.asBytes
;
1612 if (i_select
== false && len
>= 3) {
1613 bool crc
= check_crc(CRC_14443_A
, data
, len
);
1618 (crc
) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
1623 PrintAndLogEx(SUCCESS
, "%s[ %s ]", sprint_hex(data
, len
- 2), s
);
1625 PrintAndLogEx(SUCCESS
, "%s", sprint_hex(data
, len
));
1629 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
1630 return PM3_ETIMEOUT
;
1635 static int CmdHF14AAntiFuzz(const char *Cmd
) {
1637 CLIParserContext
*ctx
;
1638 CLIParserInit(&ctx
, "hf 14a antifuzz",
1639 "Tries to fuzz the ISO14443a anticollision phase",
1640 "hf 14a antifuzz -4\n");
1642 void *argtable
[] = {
1644 arg_lit0("4", NULL
, "4 byte uid"),
1645 arg_lit0("7", NULL
, "7 byte uid"),
1646 arg_lit0(NULL
, "10", "10 byte uid"),
1649 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1655 FLAG_SET_UID_IN_DATA(param
.flag
, 4);
1656 if (arg_get_lit(ctx
, 2)) {
1657 FLAG_SET_UID_IN_DATA(param
.flag
, 7);
1659 if (arg_get_lit(ctx
, 3)) {
1660 FLAG_SET_UID_IN_DATA(param
.flag
, 10);
1664 clearCommandBuffer();
1665 SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ
, (uint8_t *)¶m
, sizeof(param
));
1669 static int CmdHF14AChaining(const char *Cmd
) {
1671 CLIParserContext
*ctx
;
1672 CLIParserInit(&ctx
, "hf 14a chaining",
1673 "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
1674 "hf 14a chaining -> show chaining enable/disable state\n"
1675 "hf 14a chaining --off -> disable chaining\n"
1678 void *argtable
[] = {
1680 arg_lit0("1", "on", "enabled chaining"),
1681 arg_lit0("0", "off", "disable chaining"),
1684 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1686 bool on
= arg_get_lit(ctx
, 1);
1687 bool off
= arg_get_lit(ctx
, 2);
1690 if ((on
+ off
) > 1) {
1691 PrintAndLogEx(INFO
, "Select only one option");
1696 Set_apdu_in_framing(true);
1699 Set_apdu_in_framing(false);
1701 PrintAndLogEx(INFO
, "\nISO 14443-4 input chaining %s.\n", g_apdu_in_framing_enable
? "enabled" : "disabled");
1705 static void printTag(const char *tag
) {
1706 PrintAndLogEx(SUCCESS
, " " _YELLOW_("%s"), tag
);
1709 int detect_nxp_card(uint8_t sak
, uint16_t atqa
, uint64_t select_status
) {
1713 if ((sak
& 0x02) != 0x02) {
1714 if ((sak
& 0x19) == 0x19) {
1716 } else if ((sak
& 0x40) == 0x40) {
1718 } else if ((sak
& 0x38) == 0x38) {
1720 } else if ((sak
& 0x18) == 0x18) {
1721 if (select_status
== 1) {
1726 } else if ((sak
& 0x09) == 0x09) {
1728 } else if ((sak
& 0x28) == 0x28) {
1730 } else if ((sak
& 0x08) == 0x08) {
1731 if (select_status
== 1) {
1736 } else if ((sak
& 0x11) == 0x11) {
1738 } else if ((sak
& 0x10) == 0x10) {
1740 } else if ((sak
& 0x01) == 0x01) {
1742 } else if ((sak
& 0x24) == 0x24) {
1744 } else if ((sak
& 0x20) == 0x20) {
1745 if (select_status
== 1) {
1746 if ((atqa
& 0x0040) == 0x0040) {
1747 if ((atqa
& 0x0300) == 0x0300) {
1754 if ((atqa
& 0x0001) == 0x0001) {
1760 if ((atqa
& 0x0004) == 0x0004) {
1764 type
|= (MTDESFIRE
| MT424
);
1766 } else if ((sak
& 0x04) == 0x04) {
1769 type
|= MTULTRALIGHT
;
1771 } else if ((sak
& 0x0A) == 0x0A) {
1773 if ((atqa
& 0x0003) == 0x0003) {
1775 } else if ((atqa
& 0x0005) == 0x0005) {
1778 } else if ((sak
& 0x53) == 0x53) {
1786 // Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
1787 static int detect_nxp_card_print(uint8_t sak
, uint16_t atqa
, uint64_t select_status
) {
1790 PrintAndLogEx(SUCCESS
, "Possible types:");
1792 if ((sak
& 0x02) != 0x02) {
1793 if ((sak
& 0x19) == 0x19) {
1794 printTag("MIFARE Classic 2K");
1796 } else if ((sak
& 0x40) == 0x40) {
1797 if ((atqa
& 0x0110) == 0x0110)
1798 printTag("P2P Support / Proprietary");
1800 printTag("P2P Support / Android");
1803 } else if ((sak
& 0x38) == 0x38) {
1804 printTag("SmartMX with MIFARE Classic 4K");
1806 } else if ((sak
& 0x18) == 0x18) {
1807 if (select_status
== 1) {
1808 if ((atqa
& 0x0040) == 0x0040) {
1809 printTag("MIFARE Plus EV1 4K CL2 in SL1");
1810 printTag("MIFARE Plus S 4K CL2 in SL1");
1811 printTag("MIFARE Plus X 4K CL2 in SL1");
1813 printTag("MIFARE Plus EV1 4K in SL1");
1814 printTag("MIFARE Plus S 4K in SL1");
1815 printTag("MIFARE Plus X 4K in SL1");
1820 if ((atqa
& 0x0040) == 0x0040) {
1821 printTag("MIFARE Classic 4K CL2");
1823 printTag("MIFARE Classic 4K");
1828 } else if ((sak
& 0x09) == 0x09) {
1829 if ((atqa
& 0x0040) == 0x0040) {
1830 printTag("MIFARE Mini 0.3K CL2");
1832 printTag("MIFARE Mini 0.3K");
1836 } else if ((sak
& 0x28) == 0x28) {
1837 printTag("SmartMX with MIFARE Classic 1K");
1838 printTag("FM1208-10 with MIFARE Classic 1K");
1839 printTag("FM1216-137 with MIFARE Classic 1K");
1841 } else if ((sak
& 0x08) == 0x08) {
1842 if (select_status
== 1) {
1843 if ((atqa
& 0x0040) == 0x0040) {
1844 printTag("MIFARE Plus EV1 2K CL2 in SL1");
1845 printTag("MIFARE Plus S 2K CL2 in SL1");
1846 printTag("MIFARE Plus X 2K CL2 in SL1");
1847 printTag("MIFARE Plus SE 1K CL2");
1849 printTag("MIFARE Plus EV1 2K in SL1");
1850 printTag("MIFARE Plus S 2K in SL1");
1851 printTag("MIFARE Plus X 2K in SL1");
1852 printTag("MIFARE Plus SE 1K");
1857 if ((atqa
& 0x0040) == 0x0040) {
1858 printTag("MIFARE Classic 1K CL2");
1860 printTag("MIFARE Classic 1K");
1865 } else if ((sak
& 0x11) == 0x11) {
1866 printTag("MIFARE Plus 4K in SL2");
1868 } else if ((sak
& 0x10) == 0x10) {
1869 printTag("MIFARE Plus 2K in SL2");
1871 } else if ((sak
& 0x01) == 0x01) {
1872 printTag("TNP3xxx (TagNPlay, Activision Game Appliance)");
1874 } else if ((sak
& 0x24) == 0x24) {
1875 printTag("MIFARE DESFire CL1");
1876 printTag("MIFARE DESFire EV1 CL1");
1878 } else if ((sak
& 0x20) == 0x20) {
1879 if (select_status
== 1) {
1880 if ((atqa
& 0x0040) == 0x0040) {
1881 if ((atqa
& 0x0300) == 0x0300) {
1882 printTag("MIFARE DESFire CL2");
1883 printTag("MIFARE DESFire EV1 256B/2K/4K/8K CL2");
1884 printTag("MIFARE DESFire EV2 2K/4K/8K/16K/32K");
1885 printTag("MIFARE DESFire EV3 2K/4K/8K");
1886 printTag("MIFARE DESFire Light 640B");
1889 printTag("MIFARE Plus EV1 2K/4K CL2 in SL3");
1890 printTag("MIFARE Plus S 2K/4K CL2 in SL3");
1891 printTag("MIFARE Plus X 2K/4K CL2 in SL3");
1892 printTag("MIFARE Plus SE 1K CL2");
1897 if ((atqa
& 0x0001) == 0x0001) {
1898 printTag("HID SEOS (smartmx / javacard)");
1901 printTag("MIFARE Plus EV1 2K/4K in SL3");
1902 printTag("MIFARE Plus S 2K/4K in SL3");
1903 printTag("MIFARE Plus X 2K/4K in SL3");
1904 printTag("MIFARE Plus SE 1K");
1908 if ((atqa
& 0x0004) == 0x0004) {
1914 printTag("NTAG 4xx");
1915 type
|= (MTDESFIRE
| MT424
);
1917 } else if ((sak
& 0x04) == 0x04) {
1918 printTag("Any MIFARE CL1");
1921 printTag("MIFARE Ultralight");
1922 printTag("MIFARE Ultralight C");
1923 printTag("MIFARE Ultralight EV1");
1924 printTag("MIFARE Ultralight Nano");
1925 printTag("MIFARE Ultralight AES");
1926 printTag("MIFARE Hospitality");
1927 printTag("NTAG 2xx");
1928 type
|= MTULTRALIGHT
;
1930 } else if ((sak
& 0x0A) == 0x0A) {
1932 if ((atqa
& 0x0003) == 0x0003) {
1933 // Uses Shanghai algo
1934 printTag("FM11RF005SH (FUDAN Shanghai Metro)");
1936 } else if ((atqa
& 0x0005) == 0x0005) {
1937 printTag("FM11RF005M (FUDAN ISO14443A w Crypto-1 algo)");
1940 } else if ((sak
& 0x53) == 0x53) {
1941 printTag("FM11RF08SH (FUDAN)");
1945 if (type
== MTNONE
) {
1946 PrintAndLogEx(WARNING
, " failed to fingerprint");
1957 static const uid_label_name_t uid_label_map
[] = {
1959 {0x02, 0x84, "M24SR64-Y"},
1960 {0x02, 0xA3, "25TA02KB-P"},
1961 {0x02, 0xC4, "25TA64K"},
1962 {0x02, 0xE3, "25TA02KB"},
1963 {0x02, 0xE4, "25TA512B"},
1964 {0x02, 0xF3, "25TA02KB-D"},
1965 {0x11, 0x22, "NTAG21x Modifiable"},
1966 {0x00, 0x00, "None"}
1969 static void getTagLabel(uint8_t uid0
, uint8_t uid1
) {
1971 while (uid_label_map
[i
].uid0
!= 0x00) {
1972 if ((uid_label_map
[i
].uid0
== uid0
) && (uid_label_map
[i
].uid1
== uid1
)) {
1973 PrintAndLogEx(SUCCESS
, _YELLOW_(" %s"), uid_label_map
[i
].desc
);
1980 static void get_compact_tlv(uint8_t *d
, uint8_t n
) {
1985 uint8_t tag
= NIBBLE_HIGH(d
[0]);
1986 uint8_t len
= NIBBLE_LOW(d
[0]);
1990 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Country code in (ISO 3166-1)", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
1991 // iso3166 script in cmdlffdb.c is buggy, Ã…land, Australia not showing. getline issues
1994 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Issuer identification number (ISO 7812-1)", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
1997 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Card service data byte", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
1998 PrintAndLogEx(INFO
, " %c....... Application selection: by full DF name", (d
[1] & 0x80) ? '1' : '0');
1999 PrintAndLogEx(INFO
, " .%c...... Application selection: by partial DF name", (d
[1] & 0x40) ? '1' : '0');
2000 PrintAndLogEx(INFO
, " ..%c..... BER-TLV data objects available in EF.DIR", (d
[1] & 0x20) ? '1' : '0');
2001 PrintAndLogEx(INFO
, " ...%c.... BER-TLV data objects available in EF.ATR", (d
[1] & 0x10) ? '1' : '0');
2002 PrintAndLogEx(INFO
, " ....%c... EF.DIR and EF.ATR access services: by READ BINARY command", (d
[1] & 0x08) ? '1' : '0');
2003 PrintAndLogEx(INFO
, " .....%c.. EF.DIR and EF.ATR access services: by GET DATA command", (d
[1] & 0x04) ? '1' : '0');
2004 PrintAndLogEx(INFO
, " ......%c. EF.DIR and EF.ATR access services: by GET RECORD(s) command", (d
[1] & 0x02) ? '1' : '0');
2005 PrintAndLogEx(INFO
, " .......%c EF.DIR and EF.ATR access services: RFU", (d
[1] & 0x01) ? '1' : '0');
2008 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Initial access data", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
2011 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Card issuer data", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
2014 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Pre-issuing data", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
2017 PrintAndLogEx(INFO
, " %1x%1x " _YELLOW_("%s") " Card capabilities", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
2019 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") " - Selection methods", d
[1]);
2020 PrintAndLogEx(INFO
, " %c....... DF selection by full DF name", (d
[1] & 0x80) ? '1' : '0');
2021 PrintAndLogEx(INFO
, " .%c...... DF selection by partial DF name", (d
[1] & 0x40) ? '1' : '0');
2022 PrintAndLogEx(INFO
, " ..%c..... DF selection by path", (d
[1] & 0x20) ? '1' : '0');
2023 PrintAndLogEx(INFO
, " ...%c.... DF selection by file identifier", (d
[1] & 0x10) ? '1' : '0');
2024 PrintAndLogEx(INFO
, " ....%c... Implicit DF selection", (d
[1] & 0x08) ? '1' : '0');
2025 PrintAndLogEx(INFO
, " .....%c.. Short EF identifier supported", (d
[1] & 0x04) ? '1' : '0');
2026 PrintAndLogEx(INFO
, " ......%c. Record number supported", (d
[1] & 0x02) ? '1' : '0');
2027 PrintAndLogEx(INFO
, " .......%c Record identifier supported", (d
[1] & 0x01) ? '1' : '0');
2030 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") " - Data coding byte", d
[2]);
2033 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") " - Command chaining, length fields and logical channels", d
[3]);
2037 PrintAndLogEx(INFO
, " %1x%1x ... " _YELLOW_("%s") " Status indicator", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
2040 PrintAndLogEx(INFO
, " %1x%1x ... " _YELLOW_("%s") " Application identifier", tag
, len
, sprint_hex_inrow(d
+ 1, len
));
2052 int infoHF14A(bool verbose
, bool do_nack_test
, bool do_aid_search
) {
2054 uint8_t dbg_curr
= DBG_NONE
;
2055 if (getDeviceDebugLevel(&dbg_curr
) != PM3_SUCCESS
) {
2059 clearCommandBuffer();
2060 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
2061 PacketResponseNG resp
;
2062 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
2063 PrintAndLogEx(DEBUG
, "iso14443a card select timeout");
2068 iso14a_card_select_t card
;
2069 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
2075 3: proprietary Anticollision
2077 uint64_t select_status
= resp
.oldarg
[0];
2079 if (select_status
== 0) {
2080 PrintAndLogEx(DEBUG
, "iso14443a card select failed");
2082 return select_status
;
2085 PrintAndLogEx(NORMAL
, "");
2087 if (select_status
== 3) {
2088 PrintAndLogEx(INFO
, "Card doesn't support standard iso14443-3 anticollision");
2091 PrintAndLogEx(SUCCESS
, "ATQA: %02X %02X", card
.atqa
[1], card
.atqa
[0]);
2095 if (card
.atqa
[1] == 0x0C && card
.atqa
[0] == 0x00) {
2096 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf topaz info`"));
2100 return select_status
;
2103 PrintAndLogEx(INFO
, "---------- " _CYAN_("ISO14443-A Information") " ----------");
2104 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s") " %s", sprint_hex(card
.uid
, card
.uidlen
), get_uid_type(&card
));
2105 PrintAndLogEx(SUCCESS
, "ATQA: " _GREEN_("%02X %02X"), card
.atqa
[1], card
.atqa
[0]);
2106 PrintAndLogEx(SUCCESS
, " SAK: " _GREEN_("%02X [%" PRIu64
"]"), card
.sak
, select_status
);
2108 bool isMifareMini
= false;
2109 bool isMifareClassic
= true;
2110 bool isMifareDESFire
= false;
2111 bool isMifarePlus
= false;
2112 bool isMifareUltralight
= false;
2115 bool isFUDAN
= false;
2116 bool isISO18092
= false;
2117 bool isNTAG424
= false;
2118 bool isSEOS
= false;
2119 int nxptype
= MTNONE
;
2121 if (card
.uidlen
<= 4) {
2122 nxptype
= detect_nxp_card_print(card
.sak
, ((card
.atqa
[1] << 8) + card
.atqa
[0]), select_status
);
2124 isMifareMini
= ((nxptype
& MTMINI
) == MTMINI
);
2125 isMifareClassic
= ((nxptype
& MTCLASSIC
) == MTCLASSIC
);
2126 isMifareDESFire
= ((nxptype
& MTDESFIRE
) == MTDESFIRE
);
2127 isMifarePlus
= ((nxptype
& MTPLUS
) == MTPLUS
);
2128 isMifareUltralight
= ((nxptype
& MTULTRALIGHT
) == MTULTRALIGHT
);
2129 isNTAG424
= ((nxptype
& MT424
) == MT424
);
2130 isFUDAN
= ((nxptype
& MTFUDAN
) == MTFUDAN
);
2131 isEMV
= ((nxptype
& MTEMV
) == MTEMV
);
2132 isISO18092
= ((nxptype
& MTISO18092
) == MTISO18092
);
2133 isSEOS
= ((nxptype
& HID_SEOS
) == HID_SEOS
);
2135 // generic catch, we assume MIFARE Classic for all unknown ISO14443a tags
2136 isMifareClassic
|= ((nxptype
& MTOTHER
) == MTOTHER
);
2140 // Double & triple sized UID, can be mapped to a manufacturer.
2141 PrintAndLogEx(SUCCESS
, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card
.uid
[0]));
2143 switch (card
.uid
[0]) {
2146 isMifareClassic
= false;
2149 nxptype
= detect_nxp_card_print(card
.sak
, ((card
.atqa
[1] << 8) + card
.atqa
[0]), select_status
);
2151 isMifareMini
= ((nxptype
& MTMINI
) == MTMINI
);
2152 isMifareClassic
= ((nxptype
& MTCLASSIC
) == MTCLASSIC
);
2153 isMifareDESFire
= ((nxptype
& MTDESFIRE
) == MTDESFIRE
);
2154 isMifarePlus
= ((nxptype
& MTPLUS
) == MTPLUS
);
2155 isMifareUltralight
= ((nxptype
& MTULTRALIGHT
) == MTULTRALIGHT
);
2156 isNTAG424
= ((nxptype
& MT424
) == MT424
);
2158 if ((nxptype
& MTOTHER
) == MTOTHER
)
2159 isMifareClassic
= true;
2161 if ((nxptype
& MTFUDAN
) == MTFUDAN
)
2164 if ((nxptype
& MTEMV
) == MTEMV
)
2168 case 0x05: // Infineon
2169 if ((card
.uid
[1] & 0xF0) == 0x10) {
2170 printTag("my-d(tm) command set SLE 66R04/16/32P, SLE 66R04/16/32S");
2171 } else if ((card
.uid
[1] & 0xF0) == 0x20) {
2172 printTag("my-d(tm) command set SLE 66R01/16/32P (Type 2 Tag)");
2173 } else if ((card
.uid
[1] & 0xF0) == 0x30) {
2174 printTag("my-d(tm) move lean SLE 66R01P/66R01PN");
2175 } else if ((card
.uid
[1] & 0xF0) == 0x70) {
2176 printTag("my-d(tm) move lean SLE 66R01L");
2178 isMifareUltralight
= true;
2179 isMifareClassic
= false;
2181 if (card
.sak
== 0x88) {
2182 printTag("Infineon MIFARE CLASSIC 1K");
2183 isMifareUltralight
= false;
2184 isMifareClassic
= true;
2186 getTagLabel(card
.uid
[0], card
.uid
[1]);
2189 if (memcmp(card
.uid
, "FSTN10m", 7) == 0) {
2190 isMifareClassic
= false;
2191 printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
2195 if (memcmp(card
.uid
, "WSDZ10m", 7) == 0) {
2196 isMifareClassic
= false;
2197 printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
2201 getTagLabel(card
.uid
[0], card
.uid
[1]);
2204 isMifareClassic
= false;
2206 // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc)
2209 uint64_t tagT
= GetHF14AMfU_Type();
2210 if (tagT
!= MFU_TT_UL_ERROR
) {
2211 ul_print_type(tagT
, 0);
2212 isMifareUltralight
= true;
2213 printTag("MIFARE Ultralight/C/NTAG Compatible");
2215 printTag("Possible AZTEK (iso14443a compliant)");
2218 // reconnect for further tests
2219 clearCommandBuffer();
2220 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
, 0, 0, NULL
, 0);
2221 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
2222 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
2224 return PM3_ETIMEOUT
;
2227 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
2229 select_status
= resp
.oldarg
[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
2231 if (select_status
== 0) {
2233 return select_status
;
2238 if (card
.atqa
[0] == 0x03) {
2239 // Uses Shanghai algo
2240 printTag("FM11RF005SH (FUDAN Shanghai Metro)");
2242 } else if (card
.atqa
[0] == 0x05) {
2243 // Uses MIFARE Crypto-1 algo
2244 printTag("FM11RF005M (FUDAN ISO14443A w Crypto-1 algo)");
2249 printTag("JCOP 31/41");
2253 printTag("JCOP31 or JCOP41 v2.3.1");
2257 printTag("Nokia 6212 or 6131");
2261 printTag("FM11RF08SH (FUDAN)");
2265 printTag("Gemplus MPCOS");
2276 // try to request ATS even if tag claims not to support it
2277 if (select_status
== 2) {
2278 uint8_t rats
[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
2279 clearCommandBuffer();
2280 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_DISCONNECT
, 2, 0, rats
, sizeof(rats
));
2281 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
2282 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
2283 return PM3_ETIMEOUT
;
2286 memcpy(card
.ats
, resp
.data
.asBytes
, resp
.oldarg
[0]);
2287 card
.ats_len
= resp
.oldarg
[0]; // note: ats_len includes CRC Bytes
2288 if (card
.ats_len
> 3) {
2293 if (card
.ats_len
>= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
2295 PrintAndLogEx(INFO
, "-------------------------- " _CYAN_("ATS") " --------------------------");
2296 bool ta1
= 0, tb1
= 0, tc1
= 0;
2298 if (select_status
== 2) {
2299 PrintAndLogEx(INFO
, "--> SAK incorrectly claims that card doesn't support RATS <--");
2302 bool bad_ats
= false;
2303 if (card
.ats
[0] != card
.ats_len
- 2) {
2304 PrintAndLogEx(WARNING
, _RED_("ATS may be corrupted."));
2305 PrintAndLogEx(INFO
, "Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card
.ats_len
);
2309 PrintAndLogEx(SUCCESS
, "ATS: " _YELLOW_("%s")"[ %02X %02X ]", sprint_hex(card
.ats
, card
.ats_len
- 2), card
.ats
[card
.ats_len
- 2], card
.ats
[card
.ats_len
- 1]);
2310 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "............... TL length is " _GREEN_("%d") " bytes", card
.ats
[0], card
.ats
[0]);
2312 if (bad_ats
== false) {
2314 if ((card
.ats
[0] > 1) && (card
.ats_len
> 3)) { // there is a format byte (T0)
2315 ta1
= (card
.ats
[1] & 0x10) == 0x10;
2316 tb1
= (card
.ats
[1] & 0x20) == 0x20;
2317 tc1
= (card
.ats
[1] & 0x40) == 0x40;
2318 int16_t fsci
= card
.ats
[1] & 0x0f;
2320 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
2321 "TC1 is%s present, FSCI is %d (FSC = %d)",
2323 (ta1
? "" : _RED_(" NOT")),
2324 (tb1
? "" : _RED_(" NOT")),
2325 (tc1
? "" : _RED_(" NOT")),
2327 fsci
< ARRAYLEN(atsFSC
) ? atsFSC
[fsci
] : -1
2331 if (ta1
&& (card
.ats_len
> pos
+ 2)) {
2332 char dr
[16], ds
[16];
2333 dr
[0] = ds
[0] = '\0';
2334 if (card
.ats
[pos
] & 0x10) strcat(ds
, "2, ");
2335 if (card
.ats
[pos
] & 0x20) strcat(ds
, "4, ");
2336 if (card
.ats
[pos
] & 0x40) strcat(ds
, "8, ");
2337 if (card
.ats
[pos
] & 0x01) strcat(dr
, "2, ");
2338 if (card
.ats
[pos
] & 0x02) strcat(dr
, "4, ");
2339 if (card
.ats
[pos
] & 0x04) strcat(dr
, "8, ");
2340 if (strlen(ds
) != 0) ds
[strlen(ds
) - 2] = '\0';
2341 if (strlen(dr
) != 0) dr
[strlen(dr
) - 2] = '\0';
2342 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
2343 "DR: [%s], DS: [%s]",
2345 ((card
.ats
[pos
] & 0x80) ? _RED_(" NOT") : ""),
2353 if (tb1
&& (card
.ats_len
> pos
+ 2)) {
2354 uint32_t sfgi
= card
.ats
[pos
] & 0x0F;
2355 uint32_t fwi
= card
.ats
[pos
] >> 4;
2357 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
2360 sfgi
? "" : "(not needed) ",
2361 sfgi
? (1 << 12) << sfgi
: 0,
2368 if (tc1
&& (card
.ats_len
> pos
+ 2)) {
2369 PrintAndLogEx(INFO
, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
2371 (card
.ats
[pos
] & 0x01) ? "" : _RED_(" NOT"),
2372 (card
.ats
[pos
] & 0x02) ? "" : _RED_(" NOT")
2377 // ATS - Historial bytes and identify based on it
2378 if ((card
.ats
[0] > pos
) && (card
.ats_len
>= card
.ats
[0] + 2)) {
2381 if (card
.ats
[0] - pos
>= 7) {
2383 snprintf(tip
, sizeof(tip
), " ");
2385 if ((card
.sak
& 0x70) == 0x40) { // and no GetVersion()..
2387 if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2388 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
2390 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2392 if ((card
.atqa
[0] & 0x02) == 0x02) {
2393 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
2394 } else if ((card
.atqa
[0] & 0x04) == 0x04) {
2395 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
2398 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
2399 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
2401 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
2402 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
2405 } else { //SAK B4,5,6
2407 if ((card
.sak
& 0x20) == 0x20) { // and no GetVersion()..
2409 if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2410 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
2411 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2412 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
2413 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
2414 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
2415 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
2416 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
2419 if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2420 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
2421 } else if (memcmp(card
.ats
+ pos
, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2422 snprintf(tip
+ strlen(tip
), sizeof(tip
) - strlen(tip
), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
2428 uint8_t calen
= card
.ats
[0] - pos
;
2429 PrintAndLogEx(NORMAL
, "");
2430 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("Historical bytes") " --------------------");
2432 if (card
.ats
[pos
] == 0xC1) {
2433 PrintAndLogEx(INFO
, " %s%s", sprint_hex(card
.ats
+ pos
, calen
), tip
);
2434 PrintAndLogEx(SUCCESS
, " C1..................... Mifare or (multiple) virtual cards of various type");
2435 PrintAndLogEx(SUCCESS
, " %02X.................. length is " _YELLOW_("%d") " bytes", card
.ats
[pos
+ 1], card
.ats
[pos
+ 1]);
2436 switch (card
.ats
[pos
+ 2] & 0xf0) {
2438 PrintAndLogEx(SUCCESS
, " 1x............... MIFARE DESFire");
2439 isMifareDESFire
= true;
2440 isMifareClassic
= false;
2441 isMifarePlus
= false;
2444 PrintAndLogEx(SUCCESS
, " 2x............... MIFARE Plus");
2445 isMifarePlus
= true;
2446 isMifareDESFire
= false;
2447 isMifareClassic
= false;
2450 switch (card
.ats
[pos
+ 2] & 0x0f) {
2452 PrintAndLogEx(SUCCESS
, " x0............... < 1 kByte");
2455 PrintAndLogEx(SUCCESS
, " x1............... 1 kByte");
2458 PrintAndLogEx(SUCCESS
, " x2............... 2 kByte");
2461 PrintAndLogEx(SUCCESS
, " x3............... 4 kByte");
2464 PrintAndLogEx(SUCCESS
, " x4............... 8 kByte");
2467 switch (card
.ats
[pos
+ 3] & 0xf0) {
2469 PrintAndLogEx(SUCCESS
, " 0x............ Engineering sample");
2472 PrintAndLogEx(SUCCESS
, " 2x............ Released");
2475 switch (card
.ats
[pos
+ 3] & 0x0f) {
2477 PrintAndLogEx(SUCCESS
, " x0............ Generation 1");
2480 PrintAndLogEx(SUCCESS
, " x1............ Generation 2");
2483 PrintAndLogEx(SUCCESS
, " x2............ Generation 3");
2486 switch (card
.ats
[pos
+ 4] & 0x0f) {
2488 PrintAndLogEx(SUCCESS
, " x0......... Only VCSL supported");
2491 PrintAndLogEx(SUCCESS
, " x1......... VCS, VCSL, and SVC supported");
2494 PrintAndLogEx(SUCCESS
, " xE......... no VCS command supported");
2499 if (card
.ats
[pos
] == 0x80 || card
.ats
[pos
] == 0x00) {
2500 PrintAndLogEx(SUCCESS
, "%s (compact TLV data object)", sprint_hex_inrow(&card
.ats
[pos
], calen
));
2501 get_compact_tlv(card
.ats
+ pos
, calen
);
2503 PrintAndLogEx(SUCCESS
, "%s - %s"
2504 , sprint_hex_inrow(card
.ats
+ pos
, calen
)
2505 , sprint_ascii(card
.ats
+ pos
, calen
)
2509 PrintAndLogEx(NORMAL
, "");
2515 if (do_aid_search
) {
2517 PrintAndLogEx(INFO
, "-------------------- " _CYAN_("AID Search") " --------------------");
2519 json_t
*root
= AIDSearchInit(verbose
);
2522 bool ActivateField
= true;
2523 for (size_t elmindx
= 0; elmindx
< json_array_size(root
); elmindx
++) {
2525 if (kbd_enter_pressed()) {
2529 json_t
*data
= AIDSearchGetElm(root
, elmindx
);
2530 uint8_t vaid
[200] = {0};
2532 if (!AIDGetFromElm(data
, vaid
, sizeof(vaid
), &vaidlen
) || !vaidlen
)
2536 uint8_t result
[1024] = {0};
2537 size_t resultlen
= 0;
2538 int res
= Iso7816Select(CC_CONTACTLESS
, ActivateField
, true, vaid
, vaidlen
, result
, sizeof(result
), &resultlen
, &sw
);
2539 ActivateField
= false;
2543 uint8_t dfname
[200] = {0};
2544 size_t dfnamelen
= 0;
2545 if (resultlen
> 3) {
2546 struct tlvdb
*tlv
= tlvdb_parse_multi(result
, resultlen
);
2548 // 0x84 Dedicated File (DF) Name
2549 const struct tlv
*dfnametlv
= tlvdb_get_tlv(tlvdb_find_full(tlv
, 0x84));
2551 dfnamelen
= dfnametlv
->len
;
2552 memcpy(dfname
, dfnametlv
->value
, dfnamelen
);
2558 if (sw
== ISO7816_OK
|| sw
== ISO7816_INVALID_DF
|| sw
== ISO7816_FILE_TERMINATED
) {
2559 if (sw
== ISO7816_OK
) {
2560 if (verbose
) PrintAndLogEx(SUCCESS
, "Application ( " _GREEN_("ok") " )");
2562 if (verbose
) PrintAndLogEx(WARNING
, "Application ( " _RED_("blocked") " )");
2565 PrintAIDDescriptionBuf(root
, vaid
, vaidlen
, verbose
);
2568 if (dfnamelen
== vaidlen
) {
2569 if (memcmp(dfname
, vaid
, vaidlen
) == 0) {
2570 if (verbose
) PrintAndLogEx(INFO
, "(DF) Name found and equal to AID");
2572 PrintAndLogEx(INFO
, "(DF) Name not equal to AID: %s :", sprint_hex(dfname
, dfnamelen
));
2573 PrintAIDDescriptionBuf(root
, dfname
, dfnamelen
, verbose
);
2576 PrintAndLogEx(INFO
, "(DF) Name not equal to AID: %s :", sprint_hex(dfname
, dfnamelen
));
2577 PrintAIDDescriptionBuf(root
, dfname
, dfnamelen
, verbose
);
2580 if (verbose
) PrintAndLogEx(INFO
, "(DF) Name not found");
2583 if (verbose
) PrintAndLogEx(SUCCESS
, "----------------------------------------------------");
2590 if (verbose
== false && found
)
2591 PrintAndLogEx(INFO
, "----------------------------------------------------");
2598 PrintAndLogEx(INFO
, "proprietary iso18092 card found");
2601 PrintAndLogEx(INFO
, "proprietary non iso14443-4 card found, RATS not supported");
2602 if ((card
.sak
& 0x20) == 0x20) {
2603 PrintAndLogEx(INFO
, "--> SAK incorrectly claims that card supports RATS <--");
2607 if (select_status
== 1) {
2612 if (setDeviceDebugLevel(verbose
? MAX(dbg_curr
, DBG_INFO
) : DBG_NONE
, false) != PM3_SUCCESS
) {
2616 PrintAndLogEx(INFO
, "");
2618 uint16_t isMagic
= 0;
2620 if (isMifareClassic
|| isMifareMini
) {
2621 isMagic
= detect_mf_magic(true, MF_KEY_B
, 0xFFFFFFFFFFFF);
2624 if (isMifareUltralight
) {
2625 isMagic
= detect_mf_magic(false, MF_KEY_A
, 0);
2628 if (isMifareClassic
|| isMifareMini
) {
2629 int res
= detect_classic_static_nonce();
2630 if (res
== NONCE_STATIC
) {
2631 PrintAndLogEx(SUCCESS
, "Static nonce......... " _YELLOW_("yes"));
2634 if (res
== NONCE_NORMAL
) {
2636 res
= detect_classic_prng();
2638 PrintAndLogEx(SUCCESS
, "Prng detection....... " _GREEN_("weak"));
2639 } else if (res
== 0) {
2640 PrintAndLogEx(SUCCESS
, "Prng detection....... " _YELLOW_("hard"));
2642 PrintAndLogEx(FAILED
, "Prng detection........ " _RED_("fail"));
2646 detect_classic_nackbug(false);
2650 uint8_t signature
[32] = {0};
2651 res
= read_mfc_ev1_signature(signature
);
2652 if (res
== PM3_SUCCESS
) {
2653 mfc_ev1_print_signature(card
.uid
, card
.uidlen
, signature
, sizeof(signature
));
2657 if (setDeviceDebugLevel(dbg_curr
, false) != PM3_SUCCESS
) {
2661 PrintAndLogEx(NORMAL
, "");
2662 if (isMifareUltralight
) {
2664 if (((isMagic
& MAGIC_FLAG_GEN_1A
) == MAGIC_FLAG_GEN_1A
) || ((isMagic
& MAGIC_FLAG_GEN_1B
) == MAGIC_FLAG_GEN_1B
)) {
2665 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands");
2668 if ((isMagic
& MAGIC_FLAG_NTAG21X
) == MAGIC_FLAG_NTAG21X
) {
2669 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands");
2672 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf mfu info") "`");
2675 if (isMifarePlus
&& (isMagic
== MAGIC_FLAG_NONE
)) {
2676 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf mfp info") "`");
2679 if (isMifareDESFire
&& (isMagic
== MAGIC_FLAG_NONE
) && isEMV
== false) {
2680 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf mfdes info") "`");
2684 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf st info") "`");
2688 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("emv reader") "`");
2692 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf seos info") "`");
2696 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf fudan dump") "`");
2698 PrintAndLogEx(HINT, " hf 14a raw -a -b 7 -k 26");
2699 PrintAndLogEx(HINT, " hf 14a raw -k -c 3000");
2700 PrintAndLogEx(HINT, " hf 14a raw -k -c 3001");
2701 PrintAndLogEx(HINT, " hf 14a raw -k -c 3002");
2702 PrintAndLogEx(HINT, " hf 14a raw -k -c 3003");
2703 PrintAndLogEx(HINT, " hf 14a raw -k -c 3004");
2704 PrintAndLogEx(HINT, " hf 14a raw -k -c 3005");
2705 PrintAndLogEx(HINT, " hf 14a raw -k -c 3006");
2706 PrintAndLogEx(HINT, " hf 14a raw -c 3007");
2711 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("hf ntag424 info") "`");
2714 if (isMifareClassic
|| isMifareMini
) {
2715 if (((isMagic
& MAGIC_FLAG_GEN_1A
) == MAGIC_FLAG_GEN_1A
) || ((isMagic
& MAGIC_FLAG_GEN_1B
) == MAGIC_FLAG_GEN_1B
)) {
2716 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mf c*") "` magic commands");
2718 // if GEN4 GDM in Gen1a more, hint about it
2719 if ((isMagic
& MAGIC_FLAG_GDM_WUP_40
) == MAGIC_FLAG_GDM_WUP_40
) {
2720 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mf gdm* --gen1a") "` magic commands");
2724 if ((isMagic
& MAGIC_FLAG_GEN_3
) == MAGIC_FLAG_GEN_3
) {
2725 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mf gen3*") "` magic commands");
2728 if ((isMagic
& MAGIC_FLAG_GEN_4GTU
) == MAGIC_FLAG_GEN_4GTU
) {
2729 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mf g*") "` magic commands");
2732 if ((isMagic
& MAGIC_FLAG_GDM_AUTH
) == MAGIC_FLAG_GDM_AUTH
) {
2733 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mf gdm*") "` magic commands");
2736 if ((isMagic
& MAGIC_FLAG_GEN_2
) == MAGIC_FLAG_GEN_2
) {
2737 PrintAndLogEx(HINT
, "Hint: use `" _YELLOW_("hf mf") "` commands");
2739 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mf`") " commands");
2744 PrintAndLogEx(NORMAL
, "");
2746 return select_status
;
2749 int infoHF14A4Applications(bool verbose
) {
2750 bool cardFound
[ARRAYLEN(hintAIDList
)] = {0};
2751 bool ActivateField
= true;
2753 for (int i
= 0; i
< ARRAYLEN(hintAIDList
); i
++) {
2755 uint8_t result
[1024] = {0};
2756 size_t resultlen
= 0;
2757 int res
= Iso7816Select(CC_CONTACTLESS
, ActivateField
, true, (uint8_t *)hintAIDList
[i
].aid
, hintAIDList
[i
].aid_length
, result
, sizeof(result
), &resultlen
, &sw
);
2758 ActivateField
= false;
2762 if (sw
== ISO7816_OK
|| sw
== ISO7816_INVALID_DF
|| sw
== ISO7816_FILE_TERMINATED
) {
2765 PrintAndLogEx(INFO
, "----------------- " _CYAN_("Short AID search") " -----------------");
2769 if (sw
== ISO7816_OK
) {
2771 PrintAndLogEx(SUCCESS
, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList
[i
].desc
);
2772 cardFound
[i
] = true;
2775 PrintAndLogEx(WARNING
, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList
[i
].desc
);
2782 PrintAndLogEx(INFO
, "---------------------------------------------------");
2785 if (found
>= ARRAYLEN(hintAIDList
) - 1) {
2786 PrintAndLogEx(HINT
, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card.");
2788 for (int i
= 0; i
< ARRAYLEN(hintAIDList
); i
++) {
2789 if (cardFound
[i
] && strlen(hintAIDList
[i
].hint
))
2790 PrintAndLogEx(HINT
, "Hint: try `" _YELLOW_("%s") "` commands", hintAIDList
[i
].hint
);
2799 static uint32_t inc_sw_error_occurrence(uint16_t sw
, uint32_t *all_sw
) {
2800 uint8_t sw1
= (uint8_t)(sw
>> 8);
2801 uint8_t sw2
= (uint8_t)(0xff & sw
);
2803 // Don't count successes
2804 if (sw1
== 0x90 && sw2
== 0x00) {
2808 // Always max "Instruction not supported"
2809 if (sw1
== 0x6D && sw2
== 0x00) {
2810 return 0xFFFFFFFFUL
;
2813 all_sw
[(sw1
* 256) + sw2
]++;
2815 return all_sw
[(sw1
* 256) + sw2
];
2818 static int CmdHf14AFindapdu(const char *Cmd
) {
2819 // TODO: Option to select AID/File (and skip INS 0xA4).
2820 // TODO: Check all instructions with extended APDUs if the card support it.
2821 // TODO: Option to reset tag before every command.
2822 CLIParserContext
*ctx
;
2823 CLIParserInit(&ctx
, "hf 14a apdufind",
2824 "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands.\n"
2825 "It loops all 256 possible values for each byte.\n"
2826 "The loop oder is INS -> P1/P2 (alternating) -> CLA.\n"
2827 "Tag must be on antenna before running.",
2829 "hf 14a apdufind --cla 80\n"
2830 "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le\n"
2833 void *argtable
[] = {
2835 arg_str0("c", "cla", "<hex>", "Start value of CLASS (1 hex byte)"),
2836 arg_str0("i", "ins", "<hex>", "Start value of INSTRUCTION (1 hex byte)"),
2837 arg_str0(NULL
, "p1", "<hex>", "Start value of P1 (1 hex byte)"),
2838 arg_str0(NULL
, "p2", "<hex>", "Start value of P2 (1 hex byte)"),
2839 arg_u64_0("r", "reset", "<number>", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"),
2840 arg_u64_0("e", "error-limit", "<number>", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."),
2841 arg_strx0("s", "skip-ins", "<hex>", "Do not test an instruction (can be specified multiple times)"),
2842 arg_lit0("l", "with-le", "Search for APDUs with Le=0 (case 2S) as well"),
2843 arg_lit0("v", "verbose", "Verbose output"),
2846 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2849 uint8_t cla_arg
[1] = {0};
2850 CLIGetHexWithReturn(ctx
, 1, cla_arg
, &cla_len
);
2853 uint8_t ins_arg
[1] = {0};
2854 CLIGetHexWithReturn(ctx
, 2, ins_arg
, &ins_len
);
2857 uint8_t p1_arg
[1] = {0};
2858 CLIGetHexWithReturn(ctx
, 3, p1_arg
, &p1_len
);
2861 uint8_t p2_arg
[1] = {0};
2862 CLIGetHexWithReturn(ctx
, 4, p2_arg
, &p2_len
);
2864 uint64_t reset_time
= arg_get_u64_def(ctx
, 5, 5 * 60);
2865 uint32_t error_limit
= arg_get_u64_def(ctx
, 6, 512);
2867 int ignore_ins_len
= 0;
2868 uint8_t ignore_ins_arg
[250] = {0};
2869 CLIGetHexWithReturn(ctx
, 7, ignore_ins_arg
, &ignore_ins_len
);
2871 bool with_le
= arg_get_lit(ctx
, 8);
2872 bool verbose
= arg_get_lit(ctx
, 9);
2876 bool activate_field
= true;
2877 bool keep_field_on
= true;
2878 uint8_t cla
= cla_arg
[0];
2879 uint8_t ins
= ins_arg
[0];
2880 uint8_t p1
= p1_arg
[0];
2881 uint8_t p2
= p2_arg
[0];
2883 uint8_t response
[PM3_CMD_DATA_SIZE
] = {0};
2885 uint8_t aSELECT_AID
[80];
2886 int aSELECT_AID_n
= 0;
2888 // Check if the tag reponds to APDUs.
2889 PrintAndLogEx(INFO
, "Sending a test APDU (select file command) to check if the tag is responding to APDU");
2890 param_gethex_to_eol("00a404000aa000000440000101000100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
2891 int res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, true, false, response
, sizeof(response
), &response_n
);
2892 if (res
!= PM3_SUCCESS
) {
2893 PrintAndLogEx(FAILED
, "Tag did not respond to a test APDU (select file command). Aborting...");
2897 PrintAndLogEx(INFO
, "Press " _GREEN_("<Enter>") " to exit");
2898 PrintAndLogEx(NORMAL
, "");
2899 PrintAndLogEx(SUCCESS
, "Starting the APDU finder [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2901 bool inc_p1
= false;
2902 bool skip_ins
= false;
2903 uint32_t all_sw
[256][256] = { { 0 } };
2904 uint32_t sw_occurrences
= 0;
2906 uint64_t t_start
= msclock();
2907 uint64_t t_last_reset
= msclock();
2914 // Exit (was the Enter key pressed)?
2915 if (kbd_enter_pressed()) {
2916 PrintAndLogEx(INFO
, "User interrupted detected. Aborting");
2920 // Skip/Ignore this instrctuion?
2921 for (int i
= 0; i
< ignore_ins_len
; i
++) {
2922 if (ins
== ignore_ins_arg
[i
]) {
2934 PrintAndLogEx(INFO
, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2937 // Send APDU without Le (case 1) and with Le = 0 (case 2S), if "with-le" was set.
2938 uint8_t command
[5] = {cla
, ins
, p1
, p2
, 0x00};
2940 for (int i
= 0; i
< 1 + with_le
; i
++) {
2942 res
= ExchangeAPDU14a(command
, command_n
+ i
, activate_field
, keep_field_on
, response
, sizeof(response
), &response_n
);
2943 if (res
!= PM3_SUCCESS
) {
2945 activate_field
= true;
2949 uint16_t sw
= get_sw(response
, response_n
);
2950 sw_occurrences
= inc_sw_error_occurrence(sw
, all_sw
[0]);
2953 if (sw_occurrences
< error_limit
) {
2954 logLevel_t log_level
= INFO
;
2955 if (sw
== ISO7816_OK
) {
2956 log_level
= SUCCESS
;
2959 if (verbose
== true || sw
!= 0x6e00) {
2960 PrintAndLogEx(log_level
, "Got response for APDU \"%s\": %04X (%s)",
2961 sprint_hex_inrow(command
, command_n
+ i
),
2963 GetAPDUCodeDescription(sw
>> 8, sw
& 0xff)
2966 if (response_n
> 2) {
2967 PrintAndLogEx(SUCCESS
, "Response data is: %s | %s",
2968 sprint_hex_inrow(response
, response_n
- 2),
2969 sprint_ascii(response
, response_n
- 2)
2975 // Do not reativate the filed until the next reset.
2976 activate_field
= false;
2977 } while (++ins
!= ins_arg
[0]);
2979 // Increment P1/P2 in an alternating fashion.
2988 // Check if re-selecting the card is needed.
2989 uint64_t t_since_last_reset
= ((msclock() - t_last_reset
) / 1000);
2990 if (t_since_last_reset
> reset_time
) {
2992 activate_field
= true;
2993 t_last_reset
= msclock();
2994 PrintAndLogEx(INFO
, "Last reset was %" PRIu64
" seconds ago. Resetting the tag to prevent timeout issues", t_since_last_reset
);
2996 PrintAndLogEx(INFO
, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
2998 } while (p1
!= p1_arg
[0] || p2
!= p2_arg
[0]);
3001 PrintAndLogEx(INFO
, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla
, ins
, p1
, p2
);
3003 } while (cla
!= cla_arg
[0]);
3006 PrintAndLogEx(SUCCESS
, "Runtime: %" PRIu64
" seconds\n", (msclock() - t_start
) / 1000);
3011 int CmdHF14ANdefRead(const char *Cmd
) {
3012 CLIParserContext
*ctx
;
3013 CLIParserInit(&ctx
, "hf 14a ndefread",
3014 "Read NFC Data Exchange Format (NDEF) file on Type 4 NDEF tag",
3016 "hf 14a ndefread -f myfilename -> save raw NDEF to file"
3019 void *argtable
[] = {
3021 arg_str0("f", "file", "<fn>", "save raw NDEF to file"),
3022 arg_litn("v", "verbose", 0, 2, "verbose output"),
3025 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3027 char filename
[FILE_PATH_SIZE
] = {0};
3028 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
3030 bool verbose
= arg_get_lit(ctx
, 2);
3031 bool verbose2
= arg_get_lit(ctx
, 2) > 1;
3034 bool activate_field
= true;
3035 bool keep_field_on
= true;
3036 uint8_t response
[PM3_CMD_DATA_SIZE
];
3038 bool backward_compatibility_v1
= false;
3040 // --------------- Select NDEF Tag application ----------------
3041 uint8_t aSELECT_AID
[80];
3042 int aSELECT_AID_n
= 0;
3043 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
3044 int res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3045 if (res
!= PM3_SUCCESS
) {
3055 uint16_t sw
= get_sw(response
, resplen
);
3056 if (sw
!= ISO7816_OK
) {
3057 // Try NDEF Type 4 Tag v1.0
3058 param_gethex_to_eol("00a4040007d2760000850100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
3059 res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3060 if (res
!= PM3_SUCCESS
) {
3069 sw
= get_sw(response
, resplen
);
3070 if (sw
!= ISO7816_OK
) {
3071 PrintAndLogEx(ERR
, "Selecting NDEF aid failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
3075 backward_compatibility_v1
= true;
3078 activate_field
= false;
3079 keep_field_on
= true;
3081 // --------------- CC file reading ----------------
3082 uint8_t aSELECT_FILE_CC
[30];
3083 int aSELECT_FILE_CC_n
= 0;
3084 if (backward_compatibility_v1
) {
3085 param_gethex_to_eol("00a4000002e103", 0, aSELECT_FILE_CC
, sizeof(aSELECT_FILE_CC
), &aSELECT_FILE_CC_n
);
3087 param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC
, sizeof(aSELECT_FILE_CC
), &aSELECT_FILE_CC_n
);
3089 res
= ExchangeAPDU14a(aSELECT_FILE_CC
, aSELECT_FILE_CC_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3090 if (res
!= PM3_SUCCESS
) {
3095 sw
= get_sw(response
, resplen
);
3096 if (sw
!= ISO7816_OK
) {
3097 PrintAndLogEx(ERR
, "Selecting CC file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
3102 uint8_t aREAD_CC
[30];
3104 param_gethex_to_eol("00b000000f", 0, aREAD_CC
, sizeof(aREAD_CC
), &aREAD_CC_n
);
3105 res
= ExchangeAPDU14a(aREAD_CC
, aREAD_CC_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3106 if (res
!= PM3_SUCCESS
) {
3110 sw
= get_sw(response
, resplen
);
3111 if (sw
!= ISO7816_OK
) {
3112 PrintAndLogEx(ERR
, "reading CC file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
3118 uint8_t cc_data
[resplen
- 2];
3119 memcpy(cc_data
, response
, sizeof(cc_data
));
3120 uint8_t file_id
[2] = {cc_data
[9], cc_data
[10]};
3123 print_type4_cc_info(cc_data
, sizeof(cc_data
));
3126 uint16_t max_rapdu_size
= (cc_data
[3] << 8 | cc_data
[4]) - 2;
3127 max_rapdu_size
= max_rapdu_size
< sizeof(response
) - 2 ? max_rapdu_size
: sizeof(response
) - 2;
3129 // --------------- NDEF file reading ----------------
3130 uint8_t aSELECT_FILE_NDEF
[30];
3131 int aSELECT_FILE_NDEF_n
= 0;
3132 if (backward_compatibility_v1
) {
3133 param_gethex_to_eol("00a4000002", 0, aSELECT_FILE_NDEF
, sizeof(aSELECT_FILE_NDEF
), &aSELECT_FILE_NDEF_n
);
3135 param_gethex_to_eol("00a4000c02", 0, aSELECT_FILE_NDEF
, sizeof(aSELECT_FILE_NDEF
), &aSELECT_FILE_NDEF_n
);
3137 memcpy(aSELECT_FILE_NDEF
+ aSELECT_FILE_NDEF_n
, file_id
, sizeof(file_id
));
3138 res
= ExchangeAPDU14a(aSELECT_FILE_NDEF
, aSELECT_FILE_NDEF_n
+ sizeof(file_id
), activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3139 if (res
!= PM3_SUCCESS
) {
3144 sw
= get_sw(response
, resplen
);
3145 if (sw
!= ISO7816_OK
) {
3146 PrintAndLogEx(ERR
, "Selecting NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
3151 // read first 2 bytes to get NDEF length
3152 uint8_t aREAD_NDEF
[30];
3153 int aREAD_NDEF_n
= 0;
3154 param_gethex_to_eol("00b0000002", 0, aREAD_NDEF
, sizeof(aREAD_NDEF
), &aREAD_NDEF_n
);
3155 res
= ExchangeAPDU14a(aREAD_NDEF
, aREAD_NDEF_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3156 if (res
!= PM3_SUCCESS
) {
3161 sw
= get_sw(response
, resplen
);
3162 if (sw
!= ISO7816_OK
) {
3163 PrintAndLogEx(ERR
, "reading NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
3168 uint16_t ndef_size
= (response
[0] << 8) + response
[1];
3169 uint16_t offset
= 2;
3170 uint8_t *ndef_file
= calloc(ndef_size
, sizeof(uint8_t));
3171 if (ndef_file
== NULL
) {
3172 PrintAndLogEx(ERR
, "Out of memory error in CmdHF14ANdef(). Aborting...\n");
3177 if (ndef_size
+ offset
> 0xFFFF) {
3178 PrintAndLogEx(ERR
, "NDEF size abnormally large in CmdHF14ANdef(). Aborting...\n");
3184 for (uint16_t i
= offset
; i
< ndef_size
+ offset
; i
+= max_rapdu_size
) {
3185 uint16_t segment_size
= max_rapdu_size
< ndef_size
+ offset
- i
? max_rapdu_size
: ndef_size
+ offset
- i
;
3186 keep_field_on
= i
< ndef_size
+ offset
- max_rapdu_size
;
3188 param_gethex_to_eol("00b00000", 0, aREAD_NDEF
, sizeof(aREAD_NDEF
), &aREAD_NDEF_n
);
3189 aREAD_NDEF
[2] = i
>> 8;
3190 aREAD_NDEF
[3] = i
& 0xFF;
3191 aREAD_NDEF
[4] = segment_size
;
3193 res
= ExchangeAPDU14a(aREAD_NDEF
, aREAD_NDEF_n
+ 1, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3194 if (res
!= PM3_SUCCESS
) {
3200 sw
= get_sw(response
, resplen
);
3201 if (sw
!= ISO7816_OK
) {
3202 PrintAndLogEx(ERR
, "reading NDEF file failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
3208 if (resplen
!= segment_size
+ 2) {
3209 PrintAndLogEx(ERR
, "reading NDEF file failed, expected %i bytes, got %i bytes.", segment_size
, resplen
- 2);
3215 memcpy(ndef_file
+ (i
- offset
), response
, segment_size
);
3219 PrintAndLogEx(NORMAL
, "");
3220 PrintAndLogEx(INFO
, "--- " _CYAN_("NDEF raw") " ----------------");
3221 print_buffer(ndef_file
, ndef_size
, 1);
3224 NDEFRecordsDecodeAndPrint(ndef_file
, ndef_size
, verbose
);
3226 pm3_save_dump(filename
, ndef_file
, ndef_size
, jsfNDEF
);
3228 if (verbose
== false) {
3229 PrintAndLogEx(HINT
, "Try " _YELLOW_("`hf 14a ndefread -v`") " for more details");
3231 if (verbose2
== false) {
3232 PrintAndLogEx(HINT
, "Try " _YELLOW_("`hf 14a ndefread -vv`") " for more details");
3240 int CmdHF14ANdefFormat(const char *Cmd
) {
3241 CLIParserContext
*ctx
;
3242 CLIParserInit(&ctx
, "hf 14a ndefformat",
3243 "Format ISO14443-a Tag as a NFC tag with Data Exchange Format (NDEF)",
3244 "hf 14a ndefformat\n"
3247 void *argtable
[] = {
3249 arg_lit0("v", "verbose", "verbose output"),
3252 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3253 bool verbose
= arg_get_lit(ctx
, 1);
3256 if (g_session
.pm3_present
== false)
3259 bool activate_field
= true;
3260 bool keep_field_on
= false;
3261 uint8_t response
[PM3_CMD_DATA_SIZE
];
3264 SetAPDULogging(false);
3266 // step 1 - Select NDEF Tag application
3267 uint8_t aSELECT_AID
[80];
3268 int aSELECT_AID_n
= 0;
3269 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID
, sizeof(aSELECT_AID
), &aSELECT_AID_n
);
3270 int res
= ExchangeAPDU14a(aSELECT_AID
, aSELECT_AID_n
, activate_field
, keep_field_on
, response
, sizeof(response
), &resplen
);
3272 if (res
!= PM3_SUCCESS
) {
3280 bool have_application
= true;
3281 uint16_t sw
= get_sw(response
, resplen
);
3282 if (sw
!= ISO7816_OK
) {
3283 have_application
= false;
3284 PrintAndLogEx(INFO
, "no NDEF application found");
3286 PrintAndLogEx(INFO
, "found ndef application");
3290 // setup desfire authentication context
3291 uint8_t empty_key
[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3292 DesfireContext_t dctx
;
3293 dctx
.secureChannel
= DACNone
;
3294 DesfireSetKey(&dctx
, 0, T_DES
, empty_key
);
3295 DesfireSetKdf(&dctx
, MFDES_KDF_ALGO_NONE
, NULL
, 0);
3296 DesfireSetCommandSet(&dctx
, DCCNativeISO
);
3297 DesfireSetCommMode(&dctx
, DCMPlain
);
3299 // step 1 - create application
3300 if (have_application
== false) {
3301 // "hf mfdes createapp --aid 000001 --fid E110 --ks1 0B --ks2 A1 --dfhex D2760000850101 -t des -n 0 -k 0000000000000000"
3302 PrintAndLogEx(INFO
, "creating NDEF application...");
3304 // authenticae first to AID 00 00 00
3305 res
= DesfireSelectAndAuthenticateEx(&dctx
, DACEV1
, 0x000000, false, verbose
);
3306 if (res
!= PM3_SUCCESS
) {
3308 PrintAndLogEx(INFO
, "failed empty auth..");
3312 // create application
3313 uint8_t dfname
[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
3315 uint8_t ks2
= 0xA1; // bit FileID in ks2
3316 uint32_t appid
= 0x0000001;
3317 uint16_t fileid
= 0xE110;
3318 uint8_t data
[250] = {0};
3321 DesfireAIDUintToByte(appid
, &data
[0]);
3324 Uint2byteToMemLe(&data
[5], fileid
);
3325 memcpy(&data
[7], dfname
, sizeof(dfname
));
3329 PrintAndLogEx(INFO
, "---------------------------");
3330 PrintAndLogEx(INFO
, _CYAN_("Creating Application using:"));
3331 PrintAndLogEx(INFO
, "AID........... 0x%02X%02X%02X", data
[2], data
[1], data
[0]);
3332 PrintAndLogEx(INFO
, "Key Set 1..... 0x%02X", data
[3]);
3333 PrintAndLogEx(INFO
, "Key Set 2..... 0x%02X", data
[4]);
3334 PrintAndLogEx(INFO
, "ISO file ID... %s", (data
[4] & 0x20) ? "enabled" : "disabled");
3335 if ((data
[4] & 0x20)) {
3336 PrintAndLogEx(INFO
, "ISO file ID... 0x%04X", MemLeToUint2byte(&data
[5]));
3337 PrintAndLogEx(INFO
, "DF Name[%02d] %s | %s\n", 7, sprint_ascii(dfname
, sizeof(dfname
)), sprint_hex(dfname
, sizeof(dfname
)));
3339 PrintKeySettings(data
[3], data
[4], true, true);
3340 PrintAndLogEx(INFO
, "---------------------------");
3343 res
= DesfireCreateApplication(&dctx
, data
, datalen
);
3344 if (res
!= PM3_SUCCESS
) {
3345 PrintAndLogEx(ERR
, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res
);
3350 PrintAndLogEx(SUCCESS
, "Desfire application %06x successfully " _GREEN_("created"), appid
);
3353 // step 2 - create capability container (CC File)
3355 // authenticae to the new AID 00 00 01
3356 uint8_t aes_key
[] = {
3357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3360 dctx
.secureChannel
= DACNone
;
3361 DesfireSetKey(&dctx
, 0, T_AES
, aes_key
);
3362 DesfireSetKdf(&dctx
, MFDES_KDF_ALGO_NONE
, NULL
, 0);
3363 DesfireSetCommandSet(&dctx
, DCCNativeISO
);
3364 DesfireSetCommMode(&dctx
, DCMPlain
);
3365 res
= DesfireSelectAndAuthenticateEx(&dctx
, DACEV1
, 0x000001, false, verbose
);
3366 if (res
!= PM3_SUCCESS
) {
3368 PrintAndLogEx(INFO
, "failed aid auth..");
3372 // hf mfdes createfile --aid 000001 --fid 01 --isofid E103 --amode plain --size 00000F
3373 // --rrights free --wrights key0 --rwrights key0 --chrights key0
3374 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3376 uint16_t isofid
= 0xE103;
3377 uint32_t fsize
= 0x0F;
3378 uint8_t filetype
= 0x00; // standard file
3380 // file access mode: plain 0x00
3381 // read access: free 0x0E
3382 // write access: key0 0x00
3383 // r/w access: key0 0x00
3384 // change access: key0 0x00
3385 memset(data
, 0x00, sizeof(data
));
3389 data
[1] = isofid
& 0xff;
3390 data
[2] = (isofid
>> 8) & 0xff;
3393 uint8_t *settings
= &data
[datalen
];
3397 DesfireEncodeFileAcessMode(&settings
[1], 0x0E, 0x00, 0x00, 0x00) ;
3400 Uint3byteToMemLe(&data
[datalen
], fsize
);
3404 PrintAndLogEx(INFO
, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid
, data
[0], filetype
, datalen
, sprint_hex(data
, datalen
));
3407 DesfirePrintCreateFileSettings(filetype
, data
, datalen
);
3409 res
= DesfireCreateFile(&dctx
, filetype
, data
, datalen
, true); // check length only if we dont use raw mode
3410 if (res
!= PM3_SUCCESS
) {
3411 PrintAndLogEx(ERR
, "Desfire CreateFile command " _RED_("error") ". Result: %d", res
);
3416 PrintAndLogEx(SUCCESS
, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype
), data
[0], appid
);
3420 // hf mfdes write --aid 000001 --fid 01 -d 000F20003B00340406E10400FF00FF
3421 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3422 res
= DesfireSelectAndAuthenticateEx(&dctx
, DACEV1
, 0x000001, false, verbose
);
3423 if (res
!= PM3_SUCCESS
) {
3425 PrintAndLogEx(INFO
, "failed aid auth..");
3429 uint8_t fnum
= 0x01;
3430 uint32_t offset
= 0;
3431 uint8_t cc_data
[] = {0x00, 0x0F, 0x20, 0x00, 0x3B, 0x00, 0x34, 0x04, 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00};
3433 res
= DesfireWriteFile(&dctx
, fnum
, offset
, sizeof(cc_data
), cc_data
);
3434 if (res
!= PM3_SUCCESS
) {
3435 PrintAndLogEx(ERR
, "Desfire WriteFile command " _RED_("error") ". Result: %d", res
);
3441 PrintAndLogEx(INFO
, "Write data file %02x " _GREEN_("success"), fnum
);
3446 // step 3 - create NDEF record file
3447 // hf mfdes write --aid 000001 --fid 02 -d 000CD1010855016E78702E636F6DFE
3448 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3453 filetype
= 0x00; // standard file
3455 // file access mode: plain 0x00
3456 // read access: free 0x0E
3457 // write access: key0 0x00
3458 // r/w access: key0 0x00
3459 // change access: key0 0x00
3460 memset(data
, 0x00, sizeof(data
));
3464 data
[1] = isofid
& 0xff;
3465 data
[2] = (isofid
>> 8) & 0xff;
3468 settings
= &data
[datalen
];
3472 DesfireEncodeFileAcessMode(&settings
[1], 0x0E, 0x00, 0x00, 0x00) ;
3475 Uint3byteToMemLe(&data
[datalen
], fsize
);
3479 PrintAndLogEx(INFO
, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid
, data
[0], filetype
, datalen
, sprint_hex(data
, datalen
));
3482 DesfirePrintCreateFileSettings(filetype
, data
, datalen
);
3484 res
= DesfireCreateFile(&dctx
, filetype
, data
, datalen
, true); // check length only if we dont use raw mode
3485 if (res
!= PM3_SUCCESS
) {
3486 PrintAndLogEx(ERR
, "Desfire CreateFile command " _RED_("error") ". Result: %d", res
);
3491 PrintAndLogEx(SUCCESS
, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype
), data
[0], appid
);
3496 PrintAndLogEx(NORMAL
, "");
3497 PrintAndLogEx(INFO
, "finished");
3501 int CmdHF14ANdefWrite(const char *Cmd
) {
3502 CLIParserContext
*ctx
;
3503 CLIParserInit(&ctx
, "hf 14a ndefwrite",
3504 "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n",
3505 "hf 14a ndefwrite -d 0300FE -> write empty record to tag\n"
3506 "hf 14a ndefwrite -f myfilename\n"
3507 "hf 14a ndefwrite -d 003fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\n"
3510 void *argtable
[] = {
3512 arg_str0("d", NULL
, "<hex>", "raw NDEF hex bytes"),
3513 arg_str0("f", "file", "<fn>", "write raw NDEF file to tag"),
3514 arg_lit0("p", NULL
, "fix NDEF record headers / terminator block if missing"),
3515 arg_lit0("v", "verbose", "verbose output"),
3518 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3520 uint8_t raw
[256] = {0};
3522 CLIGetHexWithReturn(ctx
, 1, raw
, &rawlen
);
3525 char filename
[FILE_PATH_SIZE
] = {0};
3526 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
3528 bool fix_msg
= arg_get_lit(ctx
, 3);
3529 bool verbose
= arg_get_lit(ctx
, 4);
3532 if (g_session
.pm3_present
== false) {
3536 if ((rawlen
&& fnlen
) || (rawlen
== 0 && fnlen
== 0)) {
3537 PrintAndLogEx(WARNING
, "Please specify either raw hex or filename");
3541 int res
= PM3_SUCCESS
;
3542 int32_t bytes
= rawlen
;
3546 uint8_t *dump
= NULL
;
3547 size_t bytes_read
= 0;
3548 res
= pm3_load_dump(filename
, (void **)&dump
, &bytes_read
, sizeof(raw
));
3549 if (res
!= PM3_SUCCESS
) {
3552 memcpy(raw
, dump
, bytes_read
);
3558 PrintAndLogEx(INFO
, "Num of bytes... %i (raw %i)", bytes
, rawlen
);
3561 // Has raw bytes ndef message header?bytes
3571 if (fix_msg
== false) {
3572 PrintAndLogEx(WARNING
, "raw NDEF message doesn't have a proper header, continuing...");
3574 if (bytes
+ 2 > sizeof(raw
)) {
3575 PrintAndLogEx(WARNING
, "no room for header, exiting...");
3578 uint8_t tmp_raw
[256];
3579 memcpy(tmp_raw
, raw
, sizeof(tmp_raw
));
3582 memcpy(raw
+ 2, tmp_raw
, sizeof(raw
) - 2);
3584 PrintAndLogEx(SUCCESS
, "Added generic message header (0x03)");
3589 // Has raw bytes ndef a terminator block?
3590 if (raw
[bytes
- 1] != 0xFE) {
3591 if (fix_msg
== false) {
3592 PrintAndLogEx(WARNING
, "raw NDEF message doesn't have a terminator block, continuing...");
3595 if (bytes
+ 1 > sizeof(raw
)) {
3596 PrintAndLogEx(WARNING
, "no room for terminator block, exiting...");
3601 PrintAndLogEx(SUCCESS
, "Added terminator block (0xFE)");
3606 PrintAndLogEx(INFO
, "Num of Bytes... %u", bytes
);
3607 print_buffer(raw
, bytes
, 0);
3611 // setup desfire authentication context
3612 // authenticae to the new AID 00 00 01
3613 uint8_t aes_key
[] = {
3614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3618 DesfireContext_t dctx
;
3619 dctx
.secureChannel
= DACNone
;
3620 DesfireSetKey(&dctx
, 0, T_AES
, aes_key
);
3621 DesfireSetKdf(&dctx
, MFDES_KDF_ALGO_NONE
, NULL
, 0);
3622 DesfireSetCommandSet(&dctx
, DCCNativeISO
);
3623 DesfireSetCommMode(&dctx
, DCMPlain
);
3624 res
= DesfireSelectAndAuthenticateEx(&dctx
, DACEV1
, 0x000001, false, verbose
);
3625 if (res
!= PM3_SUCCESS
) {
3627 PrintAndLogEx(INFO
, "failed aid auth..");
3633 // hf mfdes write --aid 000002 --fid 02 -
3634 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3635 uint8_t fnum
= 0x02;
3636 uint32_t offset
= 0;
3638 res
= DesfireWriteFile(&dctx
, fnum
, offset
, bytes
, raw
);
3639 if (res
!= PM3_SUCCESS
) {
3640 PrintAndLogEx(ERR
, "Desfire WriteFile command " _RED_("error") ". Result: %d", res
);
3646 PrintAndLogEx(INFO
, "Write data file %02x " _GREEN_("success"), fnum
);
3649 PrintAndLogEx(NORMAL
, "");
3650 PrintAndLogEx(INFO
, "finished");
3655 * Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values
3656 * These AID Values can be responded to and include extra APDU commands after verification
3659 int CmdHF14AAIDSim(const char *Cmd
) {
3660 CLIParserContext
*ctx
;
3661 CLIParserInit(&ctx
, "hf 14a simaid",
3662 "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values\n"
3663 "These AID Values can be responded to and include extra APDU commands on GetData after response\n",
3664 "hf 14a simaid -t 3 -> MIFARE Desfire\n"
3665 "hf 14a simaid -t 4 -> ISO/IEC 14443-4\n"
3666 "hf 14a simaid -t 11 -> Javacard (JCOP)\n"
3667 "hf 14a simaid -t 3 --aid a000000000000000000000 --response 9000 --apdu 9000 -> AID, Response and APDU\n"
3668 "hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added\n"
3669 "hf 14a simaid -t 3 --rats 05788172220101 -x -> Enumerate AID Values\n"
3672 void *argtable
[] = {
3674 arg_int1("t", "type", "<1-12> ", "Simulation type to use"),
3675 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
3676 arg_str0("r", "rats", "<hex>", "<0-20> hex bytes RATS"),
3677 arg_str0("a", "aid", "<hex>", "<0-100> hex bytes for AID to respond to (Default: A000000000000000000000)"),
3678 arg_str0("e", "response", "<hex>", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"),
3679 arg_str0("p", "apdu", "<hex>", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"),
3680 arg_lit0("x", "enumerate", "Enumerate all AID values via returning Not Found and print them to console "),
3683 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3685 int tagtype
= arg_get_int_def(ctx
, 1, 1);
3687 bool enumerate
= arg_get_lit(ctx
, 7);
3692 int respond_len
= 0;
3695 uint8_t uid
[10] = {0};
3696 uint8_t rats
[20] = {0};
3697 uint8_t aid
[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3698 uint8_t response
[100] = {0x90, 0x00};
3699 uint8_t apdu
[100] = {0x90, 0x00};
3701 CLIGetHexWithReturn(ctx
, 2, uid
, &uid_len
);
3702 CLIGetHexWithReturn(ctx
, 3, rats
, &rats_len
);
3703 CLIGetHexWithReturn(ctx
, 4, aid
, &aid_len
);
3704 CLIGetHexWithReturn(ctx
, 5, response
, &respond_len
);
3705 CLIGetHexWithReturn(ctx
, 6, apdu
, &apdu_len
);
3707 // default value fill for the AID, response, and apdu
3711 if (respond_len
== 0) {
3714 if (apdu_len
== 0) {
3719 bool useUIDfromEML
= true;
3722 FLAG_SET_UID_IN_DATA(flags
, uid_len
);
3723 if (IS_FLAG_UID_IN_EMUL(flags
)) {
3724 PrintAndLogEx(ERR
, "Please specify a 4, 7, or 10 byte UID");
3728 PrintAndLogEx(SUCCESS
, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len
, sprint_hex(uid
, uid_len
));
3729 useUIDfromEML
= false;
3733 flags
|= FLAG_RATS_IN_DATA
;
3740 PrintAndLogEx(ERR
, "Undefined tag %d", tagtype
);
3744 if (useUIDfromEML
) {
3745 FLAG_SET_UID_IN_EMUL(flags
);
3754 uint8_t response
[100];
3762 payload
.tagtype
= tagtype
;
3763 payload
.flags
= flags
;
3764 payload
.enumerate
= enumerate
;
3766 // Copy data to payload
3767 memcpy(payload
.uid
, uid
, uid_len
);
3768 memcpy(payload
.rats
, rats
, rats_len
);
3769 memcpy(payload
.aid
, aid
, aid_len
);
3770 memcpy(payload
.response
, response
, respond_len
);
3771 memcpy(payload
.apdu
, apdu
, apdu_len
);
3773 // copy the lengths data to the payload
3774 memcpy(&payload
.aid_len
, &aid_len
, sizeof(aid_len
));
3775 memcpy(&payload
.respond_len
, &respond_len
, sizeof(respond_len
));
3776 memcpy(&payload
.apdu_len
, &apdu_len
, sizeof(apdu_len
));
3778 clearCommandBuffer();
3779 SendCommandNG(CMD_HF_ISO14443A_SIM_AID
, (uint8_t *)&payload
, sizeof(payload
));
3780 PacketResponseNG resp
= {0};
3782 PrintAndLogEx(INFO
, "Press " _GREEN_("pm3 button") " to abort simulation");
3783 bool keypress
= kbd_enter_pressed();
3784 while (keypress
== false) {
3786 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE
, &resp
, 1500) == 0)
3789 if (resp
.status
!= PM3_SUCCESS
)
3792 if ((flags
& FLAG_NR_AR_ATTACK
) != FLAG_NR_AR_ATTACK
)
3795 keypress
= kbd_enter_pressed();
3799 if ((flags
& FLAG_NR_AR_ATTACK
) == FLAG_NR_AR_ATTACK
) {
3800 // inform device to break the sim loop since client has exited
3801 SendCommandNG(CMD_BREAK_LOOP
, NULL
, 0);
3806 PrintAndLogEx(INFO
, "Done!");
3807 PrintAndLogEx(HINT
, "Try `" _YELLOW_("trace list -t 14a")"` to view captured tracelog");
3808 PrintAndLogEx(HINT
, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
3814 static command_t CommandTable
[] = {
3815 {"-----------", CmdHelp
, AlwaysAvailable
, "----------------------- " _CYAN_("General") " -----------------------"},
3816 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
3817 {"list", CmdHF14AList
, AlwaysAvailable
, "List ISO 14443-a history"},
3818 {"-----------", CmdHelp
, IfPm3Iso14443a
, "---------------------- " _CYAN_("Operations") " ---------------------"},
3819 {"antifuzz", CmdHF14AAntiFuzz
, IfPm3Iso14443a
, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
3820 {"config", CmdHf14AConfig
, IfPm3Iso14443a
, "Configure 14a settings (use with caution)"},
3821 {"cuids", CmdHF14ACUIDs
, IfPm3Iso14443a
, "Collect n>0 ISO14443-a UIDs in one go"},
3822 {"info", CmdHF14AInfo
, IfPm3Iso14443a
, "Tag information"},
3823 {"sim", CmdHF14ASim
, IfPm3Iso14443a
, "Simulate ISO 14443-a tag"},
3824 {"simaid", CmdHF14AAIDSim
, IfPm3Iso14443a
, "Simulate ISO 14443-a AID Selection"},
3825 {"sniff", CmdHF14ASniff
, IfPm3Iso14443a
, "sniff ISO 14443-a traffic"},
3826 {"raw", CmdHF14ACmdRaw
, IfPm3Iso14443a
, "Send raw hex data to tag"},
3827 {"reader", CmdHF14AReader
, IfPm3Iso14443a
, "Act like an ISO14443-a reader"},
3828 {"-----------", CmdHelp
, IfPm3Iso14443a
, "------------------------- " _CYAN_("APDU") " -------------------------"},
3829 {"apdu", CmdHF14AAPDU
, IfPm3Iso14443a
, "Send ISO 14443-4 APDU to tag"},
3830 {"apdufind", CmdHf14AFindapdu
, IfPm3Iso14443a
, "Enumerate APDUs - CLA/INS/P1P2"},
3831 {"chaining", CmdHF14AChaining
, IfPm3Iso14443a
, "Control ISO 14443-4 input chaining"},
3832 {"-----------", CmdHelp
, IfPm3Iso14443a
, "------------------------- " _CYAN_("NDEF") " -------------------------"},
3833 {"ndefformat", CmdHF14ANdefFormat
, IfPm3Iso14443a
, "Format ISO 14443-A as NFC Type 4 tag"},
3834 {"ndefread", CmdHF14ANdefRead
, IfPm3Iso14443a
, "Read an NDEF file from ISO 14443-A Type 4 tag"},
3835 {"ndefwrite", CmdHF14ANdefWrite
, IfPm3Iso14443a
, "Write NDEF records to ISO 14443-A tag"},
3836 {NULL
, NULL
, NULL
, NULL
}
3839 static int CmdHelp(const char *Cmd
) {
3840 (void)Cmd
; // Cmd is not used so far
3841 CmdsHelp(CommandTable
);
3845 int CmdHF14A(const char *Cmd
) {
3846 clearCommandBuffer();
3847 return CmdsParse(CommandTable
, Cmd
);