style
[RRG-proxmark3.git] / client / src / cmdhf14a.c
bloba662710a0ea42295d3ab439563a83c22a417955b
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // High frequency ISO14443A commands
17 //-----------------------------------------------------------------------------
18 #include "cmdhf14a.h"
19 #include <ctype.h>
20 #include <string.h>
21 #include "cmdparser.h" // command_t
22 #include "commonutil.h" // ARRAYLEN
23 #include "comms.h" // clearCommandBuffer
24 #include "cmdtrace.h"
25 #include "cliparser.h"
26 #include "cmdhfmf.h"
27 #include "cmdhfmfu.h"
28 #include "iso7816/iso7816core.h"
29 #include "emv/emvcore.h"
30 #include "ui.h"
31 #include "crc16.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 = {
60 { 0x52 }, 1, 7, 0,
63 static const iso14a_polling_frame_t MAGWUPA1_FRAME = {
64 { 0x7A }, 1, 7, 0
67 static const iso14a_polling_frame_t MAGWUPA2_FRAME = {
68 { 0x7B }, 1, 7, 0
71 static const iso14a_polling_frame_t MAGWUPA3_FRAME = {
72 { 0x7C }, 1, 7, 0
75 static const iso14a_polling_frame_t MAGWUPA4_FRAME = {
76 { 0x7D }, 1, 7, 0
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},
81 .frame_length = 15,
82 .last_byte_bits = 8,
83 .extra_delay = 0
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
204 // uid[8] tag 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;
242 if (config == NULL)
243 return PM3_EINVARG;
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");
251 return PM3_ETIMEOUT;
253 memcpy(config, resp.data.asBytes, sizeof(hf14a_config));
254 return PM3_SUCCESS;
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));
263 if (verbose) {
264 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0);
266 } else {
267 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0);
270 return PM3_SUCCESS;
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"));
295 return PM3_SUCCESS;
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");
322 void *argtable[] = {
323 arg_param_begin,
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"),
331 arg_param_end
333 CLIExecWithReturn(ctx, Cmd, argtable, true);
334 bool defaults = arg_get_lit(ctx, 6);
335 int vlen = 0;
336 char value[10];
337 int atqa = defaults ? 0 : -1;
338 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)value, sizeof(value), &vlen);
339 if (vlen > 0) {
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;
343 else {
344 PrintAndLogEx(ERR, "atqa argument must be 'std', 'force', or 'skip'");
345 CLIParserFree(ctx);
346 return PM3_EINVARG;
349 int bcc = defaults ? 0 : -1;
350 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)value, sizeof(value), &vlen);
351 if (vlen > 0) {
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;
355 else {
356 PrintAndLogEx(ERR, "bcc argument must be 'std', 'fix', or 'ignore'");
357 CLIParserFree(ctx);
358 return PM3_EINVARG;
361 int cl2 = defaults ? 0 : -1;
362 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)value, sizeof(value), &vlen);
363 if (vlen > 0) {
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;
367 else {
368 PrintAndLogEx(ERR, "cl2 argument must be 'std', 'force', or 'skip'");
369 CLIParserFree(ctx);
370 return PM3_EINVARG;
373 int cl3 = defaults ? 0 : -1;
374 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)value, sizeof(value), &vlen);
375 if (vlen > 0) {
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;
379 else {
380 PrintAndLogEx(ERR, "cl3 argument must be 'std', 'force', or 'skip'");
381 CLIParserFree(ctx);
382 return PM3_EINVARG;
385 int rats = defaults ? 0 : -1;
386 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)value, sizeof(value), &vlen);
387 if (vlen > 0) {
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;
391 else {
392 PrintAndLogEx(ERR, "rats argument must be 'std', 'force', or 'skip'");
393 CLIParserFree(ctx);
394 return PM3_EINVARG;
398 bool verbose = arg_get_lit(ctx, 7);
400 CLIParserFree(ctx);
402 // validations
403 if (strlen(Cmd) == 0) {
404 return hf14a_setconfig(NULL, verbose);
407 if (verbose) {
408 hf_14a_config_example();
411 hf14a_config config = {
412 .forceanticol = atqa,
413 .forcebcc = bcc,
414 .forcecl2 = cl2,
415 .forcecl3 = cl3,
416 .forcerats = rats
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) {
428 case 4: {
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 )");
437 } else {
438 sprintf(s, " ( ONUID, re-used )");
440 break;
442 case 7: {
443 sprintf(s, " ( double )");
444 break;
446 case 10: {
447 sprintf(s, " ( triple )");
448 break;
450 default:
451 break;
453 return s;
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.");
462 return PM3_ETIMEOUT;
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");
471 return PM3_EFAILED;
474 if (select_status == 2) {
475 PrintAndLogEx(ERR, "Card doesn't support iso14443-4 mode");
476 return PM3_EFAILED;
479 if (select_status == 3) {
480 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
481 // identify TOPAZ
482 if (card->atqa[1] == 0x0C && card->atqa[0] == 0x00) {
483 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
484 } else {
485 PrintAndLogEx(SUCCESS, "\tATQA : %02X %02X", card->atqa[1], card->atqa[0]);
487 return PM3_EFAILED;
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]));
502 else
503 PrintAndLogEx(SUCCESS, " ATS: [%d] %s", card->ats_len, sprint_hex(card->ats, card->ats_len));
505 return PM3_SUCCESS;
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 },
514 .frame_count = 6,
515 .extra_timeout = 100
517 return full_polling_parameters;
518 } else if (use_ecp) {
519 iso14a_polling_parameters_t ecp_polling_parameters = {
520 .frames = { WUPA_FRAME, ECP_FRAME },
521 .frame_count = 2,
522 .extra_timeout = 100
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 },
528 .frame_count = 5,
529 .extra_timeout = 0
531 return magsafe_polling_parameters;
534 iso14a_polling_parameters_t wupa_polling_parameters = {
535 .frames = { WUPA_FRAME },
536 .frame_count = 1,
537 .extra_timeout = 0,
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",
546 "hf 14a reader\n"
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"
552 void *argtable[] = {
553 arg_param_begin,
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"),
562 arg_param_end
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 = &parameters;
592 bool continuous = arg_get_lit(ctx, 7);
593 bool wait = arg_get_lit(ctx, 8);
594 CLIParserFree(ctx);
596 bool found = false;
597 if (disconnectAfter == false) {
598 cm |= ISO14A_NO_DISCONNECT;
601 if (continuous) {
602 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
605 int res = PM3_SUCCESS;
606 do {
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));
611 } else {
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) {
618 DropField();
619 res = PM3_ESOFT;
620 goto plot;
623 iso14a_card_select_t card;
624 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
627 0: couldn't read
628 1: OK, with ATS
629 2: OK, no ATS
630 3: proprietary Anticollision
632 uint64_t select_status = resp.oldarg[0];
634 found = (select_status != 0);
636 if (select_status == 0) {
637 DropField();
638 res = PM3_ESOFT;
639 goto plot;
642 if (select_status == 3) {
643 if (!(silent && continuous)) {
644 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
646 // identify TOPAZ
647 if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) {
648 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
649 } else {
650 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
652 PrintAndLogEx(NORMAL, "");
654 DropField();
655 res = PM3_ESOFT;
656 goto plot;
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]));
668 else {
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");
678 plot:
679 if (continuous) {
680 res = handle_hf_plot(false);
681 if (res != PM3_SUCCESS) {
682 PrintAndLogEx(DEBUG, "plot failed");
686 if (kbd_enter_pressed()) {
687 break;
690 } while (continuous || (wait && (!found)));
692 if (disconnectAfter == false) {
693 if (silent == false) {
694 PrintAndLogEx(INFO, "field is on");
698 if (continuous)
699 return PM3_SUCCESS;
700 else
701 return res;
704 static int CmdHF14AInfo(const char *Cmd) {
705 bool verbose = true;
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");
714 void *argtable[] = {
715 arg_param_begin,
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"),
719 arg_param_end
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);
727 CLIParserFree(ctx);
729 infoHF14A(verbose, do_nack_test, do_aid_search);
730 return PM3_SUCCESS;
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");
740 void *argtable[] = {
741 arg_param_begin,
742 arg_int0("n", "num", "<dec>", "Number of UIDs to collect"),
743 arg_param_end
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);
751 CLIParserFree(ctx);
753 uint64_t t1 = msclock();
754 PrintAndLogEx(SUCCESS, "collecting %d UIDs", n);
756 // repeat n times
757 for (int i = 0; i < n; i++) {
759 if (kbd_enter_pressed()) {
760 PrintAndLogEx(WARNING, "aborted via keyboard!\n");
761 break;
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.");
770 return PM3_ETIMEOUT;
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.");
778 } else {
779 char uid_string[20];
780 for (uint16_t m = 0; m < card->uidlen; m++) {
781 int offset = 2 * 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);
788 return PM3_SUCCESS;
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"
811 void *argtable[] = {
812 arg_param_begin,
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"),
819 arg_param_end
821 CLIExecWithReturn(ctx, Cmd, argtable, false);
823 int tagtype = arg_get_int_def(ctx, 1, 1);
825 int uid_len = 0;
826 uint8_t uid[10] = {0};
827 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
829 uint16_t flags = 0;
830 bool useUIDfromEML = true;
832 if (uid_len > 0) {
833 switch (uid_len) {
834 case 10:
835 flags |= FLAG_10B_UID_IN_DATA;
836 break;
837 case 7:
838 flags |= FLAG_7B_UID_IN_DATA;
839 break;
840 case 4:
841 flags |= FLAG_4B_UID_IN_DATA;
842 break;
843 default:
844 PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
845 CLIParserFree(ctx);
846 return PM3_EINVARG;
848 PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
849 useUIDfromEML = false;
852 uint8_t exitAfterNReads = arg_get_int_def(ctx, 3, 0);
854 if (arg_get_lit(ctx, 4)) {
855 flags |= FLAG_NR_AR_ATTACK;
858 bool setEmulatorMem = arg_get_lit(ctx, 5);
859 bool verbose = arg_get_lit(ctx, 6);
861 CLIParserFree(ctx);
863 if (tagtype > 12) {
864 PrintAndLogEx(ERR, "Undefined tag %d", tagtype);
865 return PM3_EINVARG;
868 if (useUIDfromEML) {
869 flags |= FLAG_UID_IN_EMUL;
872 struct {
873 uint8_t tagtype;
874 uint16_t flags;
875 uint8_t uid[10];
876 uint8_t exitAfter;
877 } PACKED payload;
879 payload.tagtype = tagtype;
880 payload.flags = flags;
881 payload.exitAfter = exitAfterNReads;
882 memcpy(payload.uid, uid, uid_len);
884 clearCommandBuffer();
885 SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload));
886 PacketResponseNG resp = {0};
888 sector_t *k_sector = NULL;
889 size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
891 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
892 bool keypress = kbd_enter_pressed();
893 while (keypress == false) {
895 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
896 continue;
898 if (resp.status != PM3_SUCCESS)
899 break;
901 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
902 break;
904 const nonces_t *data = (nonces_t *)resp.data.asBytes;
905 readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
907 keypress = kbd_enter_pressed();
910 if (keypress) {
911 if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
912 // inform device to break the sim loop since client has exited
913 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
917 PrintAndLogEx(INFO, "Done!");
918 return PM3_SUCCESS;
921 int CmdHF14ASniff(const char *Cmd) {
922 CLIParserContext *ctx;
923 CLIParserInit(&ctx, "hf 14a sniff",
924 "Sniff the communication between reader and tag\n"
925 "Use `hf 14a list` to view collected data.",
926 " hf 14a sniff -c -r"
928 void *argtable[] = {
929 arg_param_begin,
930 arg_lit0("c", "card", "triggered by first data from card"),
931 arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ, WUP)"),
932 arg_lit0("i", "interactive", "Console will not be returned until sniff finishes or is aborted"),
933 arg_param_end
935 CLIExecWithReturn(ctx, Cmd, argtable, true);
937 uint8_t param = 0;
939 if (arg_get_lit(ctx, 1)) {
940 param |= 0x01;
943 if (arg_get_lit(ctx, 2)) {
944 param |= 0x02;
947 bool interactive = arg_get_lit(ctx, 3);
948 CLIParserFree(ctx);
950 clearCommandBuffer();
951 SendCommandNG(CMD_HF_ISO14443A_SNIFF, (uint8_t *)&param, sizeof(uint8_t));
953 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort sniffing");
955 if (interactive) {
956 PacketResponseNG resp;
957 WaitForResponse(CMD_HF_ISO14443A_SNIFF, &resp);
958 PrintAndLogEx(INFO, "Done!");
959 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14a list")"` to view captured tracelog");
960 PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
962 return PM3_SUCCESS;
965 int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode) {
967 uint16_t cmdc = 0;
968 *dataoutlen = 0;
970 if (activateField) {
971 // select with no disconnect and set gs_frame_len
972 int selres = SelectCard14443A_4(false, !silentMode, NULL);
973 gs_frames_num = 0;
974 if (selres != PM3_SUCCESS) {
975 return selres;
979 if (leaveSignalON) {
980 cmdc |= ISO14A_NO_DISCONNECT;
983 uint8_t data[PM3_CMD_DATA_SIZE] = { 0x0a | gs_frames_num, 0x00 };
984 gs_frames_num ^= 1;
986 int min = MIN((PM3_CMD_DATA_SIZE - 2), (datainlen & 0x1FF));
987 memcpy(&data[2], datain, min);
988 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0, data, min + 2);
990 uint8_t *recv;
991 PacketResponseNG resp;
992 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
993 recv = resp.data.asBytes;
994 int iLen = resp.oldarg[0];
996 if (iLen == 0) {
997 if (silentMode == false) {
998 PrintAndLogEx(ERR, "No card response");
1000 return PM3_ECARDEXCHANGE;
1003 *dataoutlen = iLen - 2;
1004 if (*dataoutlen < 0) {
1005 *dataoutlen = 0;
1008 if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
1009 if (silentMode == false) {
1010 PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen);
1012 return PM3_ELENGTH;
1015 if (recv[0] != data[0]) {
1016 if (silentMode == false) {
1017 PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", recv[0], data[0]);
1019 return PM3_ELENGTH;
1022 memcpy(dataout, &recv[2], *dataoutlen);
1024 // CRC Check
1025 if (iLen == -1) {
1026 if (silentMode == false) {
1027 PrintAndLogEx(ERR, "ISO 14443A CRC error");
1029 return PM3_ECRC;
1032 } else {
1033 if (silentMode == false) {
1034 PrintAndLogEx(ERR, "Reply timeout.");
1036 return PM3_ETIMEOUT;
1039 return PM3_SUCCESS;
1042 int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters) {
1043 // global vars should be prefixed with g_
1044 gs_frame_len = 0;
1045 gs_frames_num = 0;
1047 if (card) {
1048 memset(card, 0, sizeof(iso14a_card_select_t));
1051 DropField();
1053 // Anticollision + SELECT card
1054 PacketResponseNG resp;
1055 if (polling_parameters != NULL) {
1056 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));
1057 } else {
1058 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
1061 if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
1062 PrintAndLogEx(WARNING, "command execution time out");
1063 return PM3_ETIMEOUT;
1066 // check result
1067 if (resp.oldarg[0] == 0) {
1068 if (verbose) {
1069 PrintAndLogEx(WARNING, "No ISO14443-A Card in field");
1071 return PM3_ECARDEXCHANGE;
1074 if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) {
1075 PrintAndLogEx(WARNING, "Card not in iso14443-4, res=%" PRId64 ".", resp.oldarg[0]);
1076 return PM3_ECARDEXCHANGE;
1079 iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.data.asBytes;
1080 if (card) {
1081 memcpy(card, vcard, sizeof(iso14a_card_select_t));
1084 if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
1085 // get ATS
1086 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
1087 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats));
1088 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1089 PrintAndLogEx(WARNING, "command execution time out");
1090 return PM3_ETIMEOUT;
1093 if (resp.oldarg[0] == 0) { // ats_len
1094 if (verbose) {
1095 PrintAndLogEx(FAILED, "Can't get ATS");
1097 return PM3_ECARDEXCHANGE;
1100 // get frame length from ATS in data field
1101 if (resp.oldarg[0] > 1) {
1102 uint8_t fsci = resp.data.asBytes[1] & 0x0f;
1103 if (fsci < ARRAYLEN(atsFSC)) {
1104 gs_frame_len = atsFSC[fsci];
1108 if (card) {
1109 card->ats_len = resp.oldarg[0];
1110 memcpy(card->ats, resp.data.asBytes, card->ats_len);
1112 } else {
1113 // get frame length from ATS in card data structure
1114 if (vcard->ats_len > 1) {
1115 uint8_t fsci = vcard->ats[1] & 0x0f;
1116 if (fsci < ARRAYLEN(atsFSC)) {
1117 gs_frame_len = atsFSC[fsci];
1122 SetISODEPState(ISODEP_NFCA);
1124 if (disconnect) {
1125 DropField();
1128 return PM3_SUCCESS;
1131 int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card) {
1132 return SelectCard14443A_4_WithParameters(disconnect, verbose, card, NULL);
1135 static int CmdExchangeAPDU(bool chainingin, const uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
1136 *chainingout = false;
1138 size_t timeout = 1500;
1139 if (activateField) {
1140 // select with no disconnect and set gs_frame_len
1141 iso14a_card_select_t card;
1142 int selres = SelectCard14443A_4(false, true, &card);
1143 if (selres != PM3_SUCCESS) {
1144 return selres;
1147 // Extract FWI and SFGI from ATS and increase timeout by the indicated values
1148 // for most cards these values are trivially small so will make no practical
1149 // difference but some "cards" like hf_cardhopper overwrite these to their
1150 // maximum values resulting in ~5 seconds each which can cause timeouts if we
1151 // just ignore it
1152 if (((card.ats[1] & 0x20) == 0x20) && card.ats_len > 2) {
1153 // TB is present in ATS
1155 uint8_t tb;
1156 if ((card.ats[1] & 0x10) == 0x10 && card.ats_len > 3) {
1157 // TA is also present, so TB at ats[3]
1158 tb = card.ats[3];
1159 } else {
1160 // TA is not present, so TB is at ats[2]
1161 tb = card.ats[2];
1164 uint8_t fwi = (tb & 0xF0) >> 4;
1165 if (fwi != 0x0F) {
1166 uint32_t fwt = 256 * 16 * (1 << fwi);
1167 timeout += fwt;
1170 uint8_t sfgi = tb & 0x0F;
1171 if (sfgi != 0x0F) {
1172 uint32_t sgft = 256 * 16 * (1 << sfgi);
1173 timeout += sgft;
1178 uint16_t cmdc = 0;
1179 if (chainingin)
1180 cmdc = ISO14A_SEND_CHAINING;
1182 // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
1183 // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
1184 // here length PM3_CMD_DATA_SIZE=512
1185 // timeout must be authomatically set by "get ATS"
1186 if (datain)
1187 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0x1FF), 0, datain, datainlen & 0x1FF);
1188 else
1189 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, 0, 0, NULL, 0);
1191 PacketResponseNG resp;
1193 if (WaitForResponseTimeout(CMD_ACK, &resp, timeout)) {
1194 const uint8_t *recv = resp.data.asBytes;
1195 int iLen = resp.oldarg[0];
1196 uint8_t res = resp.oldarg[1];
1198 int dlen = iLen - 2;
1199 if (dlen < 0)
1200 dlen = 0;
1201 *dataoutlen += dlen;
1203 if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
1204 PrintAndLogEx(DEBUG, "ERR: APDU: Buffer too small(%d), needs %d bytes", *dataoutlen, maxdataoutlen);
1205 return PM3_EAPDU_FAIL;
1208 // I-block ACK
1209 if ((res & 0xF2) == 0xA2) {
1210 *dataoutlen = 0;
1211 *chainingout = true;
1212 return PM3_SUCCESS;
1215 if (!iLen) {
1216 PrintAndLogEx(DEBUG, "ERR: APDU: No APDU response");
1217 return PM3_EAPDU_FAIL;
1220 // check apdu length
1221 if (iLen < 2 && iLen >= 0) {
1222 PrintAndLogEx(DEBUG, "ERR: APDU: Small APDU response, len %d", iLen);
1223 return PM3_EAPDU_FAIL;
1226 // check block TODO
1227 if (iLen == -2) {
1228 PrintAndLogEx(DEBUG, "ERR: APDU: Block type mismatch");
1229 return PM3_EAPDU_FAIL;
1232 memcpy(dataout, recv, dlen);
1234 // chaining
1235 if ((res & 0x10) != 0) {
1236 *chainingout = true;
1239 // CRC Check
1240 if (iLen == -1) {
1241 PrintAndLogEx(DEBUG, "ERR: APDU: ISO 14443A CRC error");
1242 return PM3_EAPDU_FAIL;
1244 } else {
1245 PrintAndLogEx(DEBUG, "ERR: APDU: Reply timeout");
1246 return PM3_EAPDU_FAIL;
1249 return PM3_SUCCESS;
1252 int ExchangeAPDU14a(const uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
1253 *dataoutlen = 0;
1254 bool chaining = false;
1255 int res;
1257 // 3 byte here - 1b framing header, 2b crc16
1258 if (g_apdu_in_framing_enable &&
1259 ((gs_frame_len && (datainlen > gs_frame_len - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) {
1261 int clen = 0;
1263 bool vActivateField = activateField;
1265 do {
1266 int vlen = MIN(gs_frame_len - 3, datainlen - clen);
1267 bool chainBlockNotLast = ((clen + vlen) < datainlen);
1269 *dataoutlen = 0;
1270 res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining);
1271 if (res != PM3_SUCCESS) {
1272 if (leaveSignalON == false)
1273 DropField();
1275 return 200;
1278 // check R-block ACK
1279 // TODO check this one...
1280 if ((*dataoutlen == 0) && (chaining != chainBlockNotLast)) {
1281 if (leaveSignalON == false)
1282 DropField();
1284 return 201;
1287 clen += vlen;
1288 vActivateField = false;
1289 if (*dataoutlen) {
1290 if (clen != datainlen) {
1291 PrintAndLogEx(ERR, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen);
1293 break;
1295 } while (clen < datainlen);
1297 } else {
1298 res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining);
1299 if (res != PM3_SUCCESS) {
1300 if (leaveSignalON == false) {
1301 DropField();
1303 return res;
1307 while (chaining) {
1308 // I-block with chaining
1309 res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining);
1310 if (res != PM3_SUCCESS) {
1311 if (leaveSignalON == false) {
1312 DropField();
1314 return 100;
1318 if (leaveSignalON == false) {
1319 DropField();
1322 return PM3_SUCCESS;
1325 // ISO14443-4. 7. Half-duplex block transmission protocol
1326 static int CmdHF14AAPDU(const char *Cmd) {
1327 CLIParserContext *ctx;
1328 CLIParserInit(&ctx, "hf 14a apdu",
1329 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL).\n"
1330 "Works with all APDU types from ISO 7816-4:2013\n"
1331 "\n"
1332 "note:\n"
1333 " `-m` and `-d` goes hand in hand\n"
1334 " -m <CLA INS P1 P2> -d 325041592E5359532E4444463031\n"
1335 "\n"
1336 " OR\n"
1337 "\n"
1338 " use `-d` with complete APDU data\n"
1339 " -d 00A404000E325041592E5359532E444446303100",
1340 "hf 14a apdu -st -d 00A404000E325041592E5359532E444446303100\n"
1341 "hf 14a apdu -sd -d 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
1342 "hf 14a apdu -sm 00A40400 -d 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
1343 "hf 14a apdu -sm 00A40400 -d 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
1345 void *argtable[] = {
1346 arg_param_begin,
1347 arg_lit0("s", "select", "activate field and select card"),
1348 arg_lit0("k", "keep", "keep signal field ON after receive"),
1349 arg_lit0("t", "tlv", "decode TLV"),
1350 arg_lit0(NULL, "decode", "decode APDU request"),
1351 arg_str0("m", "make", "<hex>", "APDU header, 4 bytes <CLA INS P1 P2>"),
1352 arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
1353 arg_int0("l", "le", "<dec>", "Le APDU parameter if `m` parameter included"),
1354 arg_strx1("d", "data", "<hex>", "full APDU package or data if `m` parameter included"),
1355 arg_param_end
1357 CLIExecWithReturn(ctx, Cmd, argtable, false);
1359 bool activateField = arg_get_lit(ctx, 1);
1360 bool leaveSignalON = arg_get_lit(ctx, 2);
1361 bool decodeTLV = arg_get_lit(ctx, 3);
1362 bool decodeAPDU = arg_get_lit(ctx, 4);
1364 uint8_t header[PM3_CMD_DATA_SIZE];
1365 int headerlen = 0;
1366 CLIGetHexWithReturn(ctx, 5, header, &headerlen);
1368 bool makeAPDU = (headerlen > 0);
1370 if (makeAPDU && headerlen != 4) {
1371 PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen);
1372 CLIParserFree(ctx);
1373 return PM3_EINVARG;
1375 bool extendedAPDU = arg_get_lit(ctx, 6);
1376 int le = arg_get_int_def(ctx, 7, 0);
1378 uint8_t data[PM3_CMD_DATA_SIZE];
1379 int datalen = 0;
1381 if (makeAPDU) {
1382 uint8_t apdudata[PM3_CMD_DATA_SIZE] = {0};
1383 int apdudatalen = 0;
1385 CLIGetHexBLessWithReturn(ctx, 8, apdudata, &apdudatalen, 1 + 2);
1387 APDU_t apdu;
1388 apdu.cla = header[0];
1389 apdu.ins = header[1];
1390 apdu.p1 = header[2];
1391 apdu.p2 = header[3];
1393 apdu.lc = apdudatalen;
1394 apdu.data = apdudata;
1396 apdu.extended_apdu = extendedAPDU;
1397 apdu.le = le;
1399 if (APDUEncode(&apdu, data, &datalen)) {
1400 PrintAndLogEx(ERR, "can't make apdu with provided parameters.");
1401 CLIParserFree(ctx);
1402 return PM3_EINVARG;
1405 } else {
1406 if (extendedAPDU) {
1407 PrintAndLogEx(ERR, "make mode not set but here `e` option.");
1408 CLIParserFree(ctx);
1409 return PM3_EINVARG;
1411 if (le > 0) {
1412 PrintAndLogEx(ERR, "make mode not set but here `l` option.");
1413 CLIParserFree(ctx);
1414 return PM3_EINVARG;
1417 // len = data + PCB(1b) + CRC(2b)
1418 CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2);
1420 CLIParserFree(ctx);
1422 PrintAndLogEx(SUCCESS, _YELLOW_("%s%s%s"),
1423 activateField ? "select card" : "",
1424 leaveSignalON ? ", keep field on" : "",
1425 decodeTLV ? ", TLV" : ""
1427 PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen));
1429 if (decodeAPDU) {
1430 APDU_t apdu;
1432 if (APDUDecode(data, datalen, &apdu) == 0)
1433 APDUPrint(apdu);
1434 else
1435 PrintAndLogEx(WARNING, "can't decode APDU.");
1438 int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, PM3_CMD_DATA_SIZE, &datalen);
1439 if (res != PM3_SUCCESS)
1440 return res;
1442 PrintAndLogEx(SUCCESS, "<<< %s | %s", sprint_hex_inrow(data, datalen), sprint_ascii(data, datalen));
1443 PrintAndLogEx(SUCCESS, "<<< status: %02X %02X - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1]));
1445 // TLV decoder
1446 if (decodeTLV && datalen > 4) {
1447 TLVPrintFromBuffer(data, datalen - 2);
1450 return PM3_SUCCESS;
1453 static int CmdHF14ACmdRaw(const char *Cmd) {
1454 CLIParserContext *ctx;
1455 CLIParserInit(&ctx, "hf 14a raw",
1456 "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
1457 "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
1458 "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
1459 "hf 14a raw --ecp -s -> send ECP before select\n"
1460 "Crypto1 session example, with special auth shortcut 6xxx<key>:\n"
1461 "hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF\n"
1462 "hf 14a raw --crypto1 -kc 3000\n"
1463 "hf 14a raw --crypto1 -kc 6007FFFFFFFFFFFF\n"
1464 "hf 14a raw --crypto1 -c 3007"
1467 void *argtable[] = {
1468 arg_param_begin,
1469 arg_lit0("a", NULL, "Active signal field ON without select"),
1470 arg_lit0("c", NULL, "Calculate and append CRC"),
1471 arg_lit0("k", NULL, "Keep signal field ON after receive"),
1472 arg_lit0("3", NULL, "ISO14443-3 select only (skip RATS)"),
1473 arg_lit0("r", NULL, "Do not read response"),
1474 arg_lit0("s", NULL, "Active signal field ON with select"),
1475 arg_int0("t", "timeout", "<ms>", "Timeout in milliseconds"),
1476 arg_int0("b", NULL, "<dec>", "Number of bits to send. Useful for send partial byte"),
1477 arg_lit0("v", "verbose", "Verbose output"),
1478 arg_lit0(NULL, "ecp", "Use enhanced contactless polling"),
1479 arg_lit0(NULL, "mag", "Use Apple magsafe polling"),
1480 arg_lit0(NULL, "topaz", "Use Topaz protocol to send command"),
1481 arg_lit0(NULL, "crypto1", "Use crypto1 session"),
1482 arg_strx1(NULL, NULL, "<hex>", "Raw bytes to send"),
1483 arg_param_end
1485 CLIExecWithReturn(ctx, Cmd, argtable, false);
1487 bool active = arg_get_lit(ctx, 1);
1488 bool crc = arg_get_lit(ctx, 2);
1489 bool keep_field_on = arg_get_lit(ctx, 3);
1490 bool no_rats = arg_get_lit(ctx, 4);
1491 bool reply = (arg_get_lit(ctx, 5) == false);
1492 bool active_select = arg_get_lit(ctx, 6);
1493 uint32_t timeout = (uint32_t)arg_get_int_def(ctx, 7, 0);
1494 uint16_t numbits = (uint16_t)arg_get_int_def(ctx, 8, 0);
1495 bool verbose = arg_get_lit(ctx, 9);
1496 bool use_ecp = arg_get_lit(ctx, 10);
1497 bool use_magsafe = arg_get_lit(ctx, 11);
1498 bool topazmode = arg_get_lit(ctx, 12);
1499 bool crypto1mode = arg_get_lit(ctx, 13);
1501 int datalen = 0;
1502 uint8_t data[PM3_CMD_DATA_SIZE_MIX] = {0};
1503 CLIGetHexWithReturn(ctx, 14, data, &datalen);
1504 CLIParserFree(ctx);
1506 bool bTimeout = (timeout) ? true : false;
1508 // ensure we can add 2byte crc to input data
1509 if (datalen >= sizeof(data) + 2) {
1510 if (crc) {
1511 PrintAndLogEx(FAILED, "Buffer is full, we can't add CRC to your data");
1512 return PM3_EINVARG;
1516 if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
1517 uint8_t first, second;
1518 if (topazmode) {
1519 compute_crc(CRC_14443_B, data, datalen, &first, &second);
1520 } else {
1521 compute_crc(CRC_14443_A, data, datalen, &first, &second);
1523 data[datalen++] = first;
1524 data[datalen++] = second;
1527 uint16_t flags = 0;
1528 if (active || active_select) {
1529 flags |= ISO14A_CONNECT;
1530 if (active)
1531 flags |= ISO14A_NO_SELECT;
1534 uint32_t argtimeout = 0;
1535 if (bTimeout) {
1536 #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
1537 flags |= ISO14A_SET_TIMEOUT;
1538 if (timeout > MAX_TIMEOUT) {
1539 timeout = MAX_TIMEOUT;
1540 PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
1542 argtimeout = 13560000 / 1000 / (8 * 16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
1545 if (keep_field_on) {
1546 flags |= ISO14A_NO_DISCONNECT;
1549 if (datalen > 0) {
1550 flags |= ISO14A_RAW;
1553 if (topazmode) {
1554 flags |= ISO14A_TOPAZMODE;
1557 if (crypto1mode) {
1558 flags |= ISO14A_CRYPTO1MODE;
1559 if (numbits > 0 || topazmode || use_ecp || use_magsafe) {
1560 PrintAndLogEx(FAILED, "crypto1 mode cannot be used with other modes or partial bytes");
1561 return PM3_EINVARG;
1565 if (no_rats) {
1566 flags |= ISO14A_NO_RATS;
1569 // TODO: allow to use reader command with both data and polling configuration
1570 if (use_ecp || use_magsafe) {
1571 PrintAndLogEx(WARNING, "ECP and Magsafe not supported with this command at this moment. Instead use 'hf 14a reader -sk --ecp/--mag'");
1572 // flags |= ISO14A_USE_MAGSAFE;
1573 // flags |= ISO14A_USE_ECP;
1576 // Max buffer is PM3_CMD_DATA_SIZE_MIX
1577 datalen = (datalen > PM3_CMD_DATA_SIZE_MIX) ? PM3_CMD_DATA_SIZE_MIX : datalen;
1579 clearCommandBuffer();
1580 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, (datalen & 0x1FF) | ((uint32_t)(numbits << 16)), argtimeout, data, datalen);
1582 if (reply) {
1583 int res = 0;
1584 if (active_select)
1585 res = waitCmd(true, timeout, verbose);
1586 if (res == PM3_SUCCESS && datalen > 0)
1587 waitCmd(false, timeout, verbose);
1589 return PM3_SUCCESS;
1592 static int waitCmd(bool i_select, uint32_t timeout, bool verbose) {
1593 PacketResponseNG resp;
1595 if (WaitForResponseTimeout(CMD_ACK, &resp, timeout + 1500)) {
1596 uint16_t len = (resp.oldarg[0] & 0xFFFF);
1597 if (i_select) {
1598 len = (resp.oldarg[1] & 0xFFFF);
1599 if (len) {
1600 if (verbose) {
1601 PrintAndLogEx(SUCCESS, "Card selected. UID[%u]:", len);
1602 } else {
1603 return PM3_SUCCESS;
1606 } else {
1607 PrintAndLogEx(WARNING, "Can't select card.");
1609 } else {
1610 if (verbose) {
1611 PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
1615 if (len == 0) {
1616 return PM3_ESOFT;
1619 uint8_t *data = resp.data.asBytes;
1621 if (i_select == false && len >= 3) {
1622 bool crc = check_crc(CRC_14443_A, data, len);
1624 char s[16];
1625 snprintf(s,
1626 sizeof(s),
1627 (crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
1628 data[len - 2],
1629 data[len - 1]
1632 PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s);
1633 } else {
1634 PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
1637 } else {
1638 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1639 return PM3_ETIMEOUT;
1641 return PM3_SUCCESS;
1644 static int CmdHF14AAntiFuzz(const char *Cmd) {
1646 CLIParserContext *ctx;
1647 CLIParserInit(&ctx, "hf 14a antifuzz",
1648 "Tries to fuzz the ISO14443a anticollision phase",
1649 "hf 14a antifuzz -4\n");
1651 void *argtable[] = {
1652 arg_param_begin,
1653 arg_lit0("4", NULL, "4 byte uid"),
1654 arg_lit0("7", NULL, "7 byte uid"),
1655 arg_lit0(NULL, "10", "10 byte uid"),
1656 arg_param_end
1658 CLIExecWithReturn(ctx, Cmd, argtable, false);
1660 struct {
1661 uint8_t flag;
1662 } PACKED param;
1663 param.flag = FLAG_4B_UID_IN_DATA;
1665 if (arg_get_lit(ctx, 2))
1666 param.flag = FLAG_7B_UID_IN_DATA;
1667 if (arg_get_lit(ctx, 3))
1668 param.flag = FLAG_10B_UID_IN_DATA;
1670 CLIParserFree(ctx);
1671 clearCommandBuffer();
1672 SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t *)&param, sizeof(param));
1673 return PM3_SUCCESS;
1676 static int CmdHF14AChaining(const char *Cmd) {
1678 CLIParserContext *ctx;
1679 CLIParserInit(&ctx, "hf 14a chaining",
1680 "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
1681 "hf 14a chaining -> show chaining enable/disable state\n"
1682 "hf 14a chaining --off -> disable chaining\n"
1685 void *argtable[] = {
1686 arg_param_begin,
1687 arg_lit0("1", "on", "enabled chaining"),
1688 arg_lit0("0", "off", "disable chaining"),
1689 arg_param_end
1691 CLIExecWithReturn(ctx, Cmd, argtable, true);
1693 bool on = arg_get_lit(ctx, 1);
1694 bool off = arg_get_lit(ctx, 2);
1695 CLIParserFree(ctx);
1697 if ((on + off) > 1) {
1698 PrintAndLogEx(INFO, "Select only one option");
1699 return PM3_EINVARG;
1702 if (on)
1703 Set_apdu_in_framing(true);
1705 if (off)
1706 Set_apdu_in_framing(false);
1708 PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", g_apdu_in_framing_enable ? "enabled" : "disabled");
1709 return PM3_SUCCESS;
1712 static void printTag(const char *tag) {
1713 PrintAndLogEx(SUCCESS, " " _YELLOW_("%s"), tag);
1716 int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status) {
1718 int type = MTNONE;
1720 if ((sak & 0x02) != 0x02) {
1721 if ((sak & 0x19) == 0x19) {
1722 type |= MTCLASSIC;
1723 } else if ((sak & 0x40) == 0x40) {
1724 type |= MTISO18092;
1725 } else if ((sak & 0x38) == 0x38) {
1726 type |= MTCLASSIC;
1727 } else if ((sak & 0x18) == 0x18) {
1728 if (select_status == 1) {
1729 type |= MTPLUS;
1730 } else {
1731 type |= MTCLASSIC;
1733 } else if ((sak & 0x09) == 0x09) {
1734 type |= MTMINI;
1735 } else if ((sak & 0x28) == 0x28) {
1736 type |= MTCLASSIC;
1737 } else if ((sak & 0x08) == 0x08) {
1738 if (select_status == 1) {
1739 type |= MTPLUS;
1740 } else {
1741 type |= MTCLASSIC;
1743 } else if ((sak & 0x11) == 0x11) {
1744 type |= MTPLUS;
1745 } else if ((sak & 0x10) == 0x10) {
1746 type |= MTPLUS;
1747 } else if ((sak & 0x01) == 0x01) {
1748 type |= MTCLASSIC;
1749 } else if ((sak & 0x24) == 0x24) {
1750 type |= MTDESFIRE;
1751 } else if ((sak & 0x20) == 0x20) {
1752 if (select_status == 1) {
1753 if ((atqa & 0x0040) == 0x0040) {
1754 if ((atqa & 0x0300) == 0x0300) {
1755 type |= MTDESFIRE;
1756 } else {
1757 type |= MTPLUS;
1759 } else {
1761 if ((atqa & 0x0001) == 0x0001) {
1762 type |= HID_SEOS;
1763 } else {
1764 type |= MTPLUS;
1767 if ((atqa & 0x0004) == 0x0004) {
1768 type |= MTEMV;
1771 type |= (MTDESFIRE | MT424);
1773 } else if ((sak & 0x04) == 0x04) {
1774 type |= MTDESFIRE;
1775 } else {
1776 type |= MTULTRALIGHT;
1778 } else if ((sak & 0x0A) == 0x0A) {
1780 if ((atqa & 0x0003) == 0x0003) {
1781 type |= MTFUDAN;
1782 } else if ((atqa & 0x0005) == 0x0005) {
1783 type |= MTFUDAN;
1785 } else if ((sak & 0x53) == 0x53) {
1786 type |= MTFUDAN;
1789 return type;
1793 // Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
1794 static int detect_nxp_card_print(uint8_t sak, uint16_t atqa, uint64_t select_status) {
1795 int type = MTNONE;
1797 PrintAndLogEx(SUCCESS, "Possible types:");
1799 if ((sak & 0x02) != 0x02) {
1800 if ((sak & 0x19) == 0x19) {
1801 printTag("MIFARE Classic 2K");
1802 type |= MTCLASSIC;
1803 } else if ((sak & 0x40) == 0x40) {
1804 if ((atqa & 0x0110) == 0x0110)
1805 printTag("P2P Support / Proprietary");
1806 else
1807 printTag("P2P Support / Android");
1809 type |= MTISO18092;
1810 } else if ((sak & 0x38) == 0x38) {
1811 printTag("SmartMX with MIFARE Classic 4K");
1812 type |= MTCLASSIC;
1813 } else if ((sak & 0x18) == 0x18) {
1814 if (select_status == 1) {
1815 if ((atqa & 0x0040) == 0x0040) {
1816 printTag("MIFARE Plus EV1 4K CL2 in SL1");
1817 printTag("MIFARE Plus S 4K CL2 in SL1");
1818 printTag("MIFARE Plus X 4K CL2 in SL1");
1819 } else {
1820 printTag("MIFARE Plus EV1 4K in SL1");
1821 printTag("MIFARE Plus S 4K in SL1");
1822 printTag("MIFARE Plus X 4K in SL1");
1825 type |= MTPLUS;
1826 } else {
1827 if ((atqa & 0x0040) == 0x0040) {
1828 printTag("MIFARE Classic 4K CL2");
1829 } else {
1830 printTag("MIFARE Classic 4K");
1833 type |= MTCLASSIC;
1835 } else if ((sak & 0x09) == 0x09) {
1836 if ((atqa & 0x0040) == 0x0040) {
1837 printTag("MIFARE Mini 0.3K CL2");
1838 } else {
1839 printTag("MIFARE Mini 0.3K");
1842 type |= MTMINI;
1843 } else if ((sak & 0x28) == 0x28) {
1844 printTag("SmartMX with MIFARE Classic 1K");
1845 printTag("FM1208-10 with MIFARE Classic 1K");
1846 type |= MTCLASSIC;
1847 } else if ((sak & 0x08) == 0x08) {
1848 if (select_status == 1) {
1849 if ((atqa & 0x0040) == 0x0040) {
1850 printTag("MIFARE Plus EV1 2K CL2 in SL1");
1851 printTag("MIFARE Plus S 2K CL2 in SL1");
1852 printTag("MIFARE Plus X 2K CL2 in SL1");
1853 printTag("MIFARE Plus SE 1K CL2");
1854 } else {
1855 printTag("MIFARE Plus EV1 2K in SL1");
1856 printTag("MIFARE Plus S 2K in SL1");
1857 printTag("MIFARE Plus X 2K in SL1");
1858 printTag("MIFARE Plus SE 1K");
1861 type |= MTPLUS;
1862 } else {
1863 if ((atqa & 0x0040) == 0x0040) {
1864 printTag("MIFARE Classic 1K CL2");
1865 } else {
1866 printTag("MIFARE Classic 1K");
1869 type |= MTCLASSIC;
1871 } else if ((sak & 0x11) == 0x11) {
1872 printTag("MIFARE Plus 4K in SL2");
1873 type |= MTPLUS;
1874 } else if ((sak & 0x10) == 0x10) {
1875 printTag("MIFARE Plus 2K in SL2");
1876 type |= MTPLUS;
1877 } else if ((sak & 0x01) == 0x01) {
1878 printTag("TNP3xxx (TagNPlay, Activision Game Appliance)");
1879 type |= MTCLASSIC;
1880 } else if ((sak & 0x24) == 0x24) {
1881 printTag("MIFARE DESFire CL1");
1882 printTag("MIFARE DESFire EV1 CL1");
1883 type |= MTDESFIRE;
1884 } else if ((sak & 0x20) == 0x20) {
1885 if (select_status == 1) {
1886 if ((atqa & 0x0040) == 0x0040) {
1887 if ((atqa & 0x0300) == 0x0300) {
1888 printTag("MIFARE DESFire CL2");
1889 printTag("MIFARE DESFire EV1 256B/2K/4K/8K CL2");
1890 printTag("MIFARE DESFire EV2 2K/4K/8K/16K/32K");
1891 printTag("MIFARE DESFire EV3 2K/4K/8K");
1892 printTag("MIFARE DESFire Light 640B");
1893 type |= MTDESFIRE;
1894 } else {
1895 printTag("MIFARE Plus EV1 2K/4K CL2 in SL3");
1896 printTag("MIFARE Plus S 2K/4K CL2 in SL3");
1897 printTag("MIFARE Plus X 2K/4K CL2 in SL3");
1898 printTag("MIFARE Plus SE 1K CL2");
1899 type |= MTPLUS;
1901 } else {
1903 if ((atqa & 0x0001) == 0x0001) {
1904 printTag("HID SEOS (smartmx / javacard)");
1905 type |= HID_SEOS;
1906 } else {
1907 printTag("MIFARE Plus EV1 2K/4K in SL3");
1908 printTag("MIFARE Plus S 2K/4K in SL3");
1909 printTag("MIFARE Plus X 2K/4K in SL3");
1910 printTag("MIFARE Plus SE 1K");
1911 type |= MTPLUS;
1914 if ((atqa & 0x0004) == 0x0004) {
1915 printTag("EMV");
1916 type |= MTEMV;
1920 printTag("NTAG 4xx");
1921 type |= (MTDESFIRE | MT424);
1923 } else if ((sak & 0x04) == 0x04) {
1924 printTag("Any MIFARE CL1");
1925 type |= MTDESFIRE;
1926 } else {
1927 printTag("MIFARE Ultralight");
1928 printTag("MIFARE Ultralight C");
1929 printTag("MIFARE Ultralight EV1");
1930 printTag("MIFARE Ultralight Nano");
1931 printTag("MIFARE Ultralight AES");
1932 printTag("MIFARE Hospitality");
1933 printTag("NTAG 2xx");
1934 type |= MTULTRALIGHT;
1936 } else if ((sak & 0x0A) == 0x0A) {
1938 if ((atqa & 0x0003) == 0x0003) {
1939 // Uses Shanghai algo
1940 printTag("FM11RF005SH (FUDAN Shanghai Metro)");
1941 type |= MTFUDAN;
1942 } else if ((atqa & 0x0005) == 0x0005) {
1943 printTag("FM11RF005M (FUDAN ISO14443A w Crypto-1 algo)");
1944 type |= MTFUDAN;
1946 } else if ((sak & 0x53) == 0x53) {
1947 printTag("FM11RF08SH (FUDAN)");
1948 type |= MTFUDAN;
1951 if (type == MTNONE) {
1952 PrintAndLogEx(WARNING, " failed to fingerprint");
1954 return type;
1957 typedef struct {
1958 uint8_t uid0;
1959 uint8_t uid1;
1960 const char *desc;
1961 } uid_label_name_t;
1963 static const uid_label_name_t uid_label_map[] = {
1964 // UID0, UID1, TEXT
1965 {0x02, 0x84, "M24SR64-Y"},
1966 {0x02, 0xA3, "25TA02KB-P"},
1967 {0x02, 0xC4, "25TA64K"},
1968 {0x02, 0xE3, "25TA02KB"},
1969 {0x02, 0xE4, "25TA512B"},
1970 {0x02, 0xF3, "25TA02KB-D"},
1971 {0x11, 0x22, "NTAG21x Modifiable"},
1972 {0x00, 0x00, "None"}
1975 static void getTagLabel(uint8_t uid0, uint8_t uid1) {
1976 int i = 0;
1977 while (uid_label_map[i].uid0 != 0x00) {
1978 if ((uid_label_map[i].uid0 == uid0) && (uid_label_map[i].uid1 == uid1)) {
1979 PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uid_label_map[i].desc);
1980 return;
1982 i += 1;
1986 static void get_compact_tlv(uint8_t *d, uint8_t n) {
1987 d++;
1988 n--;
1990 while (n > 0) {
1991 uint8_t tag = NIBBLE_HIGH(d[0]);
1992 uint8_t len = NIBBLE_LOW(d[0]);
1994 switch (tag) {
1995 case 1:
1996 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Country code in (ISO 3166-1)", tag, len, sprint_hex_inrow(d + 1, len));
1997 // iso3166 script in cmdlffdb.c is buggy, Ã…land, Australia not showing. getline issues
1998 break;
1999 case 2:
2000 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Issuer identification number (ISO 7812-1)", tag, len, sprint_hex_inrow(d + 1, len));
2001 break;
2002 case 3:
2003 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Card service data byte", tag, len, sprint_hex_inrow(d + 1, len));
2004 PrintAndLogEx(INFO, " %c....... Application selection: by full DF name", (d[1] & 0x80) ? '1' : '0');
2005 PrintAndLogEx(INFO, " .%c...... Application selection: by partial DF name", (d[1] & 0x40) ? '1' : '0');
2006 PrintAndLogEx(INFO, " ..%c..... BER-TLV data objects available in EF.DIR", (d[1] & 0x20) ? '1' : '0');
2007 PrintAndLogEx(INFO, " ...%c.... BER-TLV data objects available in EF.ATR", (d[1] & 0x10) ? '1' : '0');
2008 PrintAndLogEx(INFO, " ....%c... EF.DIR and EF.ATR access services: by READ BINARY command", (d[1] & 0x08) ? '1' : '0');
2009 PrintAndLogEx(INFO, " .....%c.. EF.DIR and EF.ATR access services: by GET DATA command", (d[1] & 0x04) ? '1' : '0');
2010 PrintAndLogEx(INFO, " ......%c. EF.DIR and EF.ATR access services: by GET RECORD(s) command", (d[1] & 0x02) ? '1' : '0');
2011 PrintAndLogEx(INFO, " .......%c EF.DIR and EF.ATR access services: RFU", (d[1] & 0x01) ? '1' : '0');
2012 break;
2013 case 4:
2014 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Initial access data", tag, len, sprint_hex_inrow(d + 1, len));
2015 break;
2016 case 5:
2017 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Card issuer data", tag, len, sprint_hex_inrow(d + 1, len));
2018 break;
2019 case 6:
2020 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Pre-issuing data", tag, len, sprint_hex_inrow(d + 1, len));
2021 break;
2022 case 7:
2023 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Card capabilities", tag, len, sprint_hex_inrow(d + 1, len));
2025 PrintAndLogEx(INFO, " " _YELLOW_("%02X") " - Selection methods", d[1]);
2026 PrintAndLogEx(INFO, " %c....... DF selection by full DF name", (d[1] & 0x80) ? '1' : '0');
2027 PrintAndLogEx(INFO, " .%c...... DF selection by partial DF name", (d[1] & 0x40) ? '1' : '0');
2028 PrintAndLogEx(INFO, " ..%c..... DF selection by path", (d[1] & 0x20) ? '1' : '0');
2029 PrintAndLogEx(INFO, " ...%c.... DF selection by file identifier", (d[1] & 0x10) ? '1' : '0');
2030 PrintAndLogEx(INFO, " ....%c... Implicit DF selection", (d[1] & 0x08) ? '1' : '0');
2031 PrintAndLogEx(INFO, " .....%c.. Short EF identifier supported", (d[1] & 0x04) ? '1' : '0');
2032 PrintAndLogEx(INFO, " ......%c. Record number supported", (d[1] & 0x02) ? '1' : '0');
2033 PrintAndLogEx(INFO, " .......%c Record identifier supported", (d[1] & 0x01) ? '1' : '0');
2035 if (len > 1) {
2036 PrintAndLogEx(INFO, " " _YELLOW_("%02X") " - Data coding byte", d[2]);
2038 if (len > 2) {
2039 PrintAndLogEx(INFO, " " _YELLOW_("%02X") " - Command chaining, length fields and logical channels", d[3]);
2041 break;
2042 case 8:
2043 PrintAndLogEx(INFO, " %1x%1x ... " _YELLOW_("%s") " Status indicator", tag, len, sprint_hex_inrow(d + 1, len));
2044 break;
2045 case 0xE:
2046 PrintAndLogEx(INFO, " %1x%1x ... " _YELLOW_("%s") " Application identifier", tag, len, sprint_hex_inrow(d + 1, len));
2047 break;
2050 if (len > n)
2051 break;
2053 n -= (1 + len);
2054 d += (1 + len);
2058 int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
2060 uint8_t dbg_curr = DBG_NONE;
2061 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
2062 return PM3_EFAILED;
2065 clearCommandBuffer();
2066 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
2067 PacketResponseNG resp;
2068 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
2069 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
2070 DropField();
2071 return 0;
2074 iso14a_card_select_t card;
2075 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
2078 0: couldn't read
2079 1: OK, with ATS
2080 2: OK, no ATS
2081 3: proprietary Anticollision
2083 uint64_t select_status = resp.oldarg[0];
2085 if (select_status == 0) {
2086 PrintAndLogEx(DEBUG, "iso14443a card select failed");
2087 DropField();
2088 return select_status;
2091 PrintAndLogEx(NORMAL, "");
2093 if (select_status == 3) {
2094 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
2096 if (verbose) {
2097 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
2100 // identify TOPAZ
2101 if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) {
2102 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
2105 DropField();
2106 return select_status;
2109 PrintAndLogEx(INFO, "---------- " _CYAN_("ISO14443-A Information") " ----------");
2110 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " %s", sprint_hex(card.uid, card.uidlen), get_uid_type(&card));
2111 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
2112 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, select_status);
2114 bool isMifareMini = false;
2115 bool isMifareClassic = true;
2116 bool isMifareDESFire = false;
2117 bool isMifarePlus = false;
2118 bool isMifareUltralight = false;
2119 bool isST = false;
2120 bool isEMV = false;
2121 bool isFUDAN = false;
2122 bool isISO18092 = false;
2123 bool isNTAG424 = false;
2124 bool isSEOS = false;
2125 int nxptype = MTNONE;
2127 if (card.uidlen <= 4) {
2128 nxptype = detect_nxp_card_print(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
2130 isMifareMini = ((nxptype & MTMINI) == MTMINI);
2131 isMifareClassic = ((nxptype & MTCLASSIC) == MTCLASSIC);
2132 isMifareDESFire = ((nxptype & MTDESFIRE) == MTDESFIRE);
2133 isMifarePlus = ((nxptype & MTPLUS) == MTPLUS);
2134 isMifareUltralight = ((nxptype & MTULTRALIGHT) == MTULTRALIGHT);
2135 isNTAG424 = ((nxptype & MT424) == MT424);
2136 isFUDAN = ((nxptype & MTFUDAN) == MTFUDAN);
2137 isEMV = ((nxptype & MTEMV) == MTEMV);
2138 isISO18092 = ((nxptype & MTISO18092) == MTISO18092);
2139 isSEOS = ((nxptype & HID_SEOS) == HID_SEOS);
2141 // generic catch, we assume MIFARE Classic for all unknown ISO14443a tags
2142 isMifareClassic |= ((nxptype & MTOTHER) == MTOTHER);
2144 } else {
2146 // Double & triple sized UID, can be mapped to a manufacturer.
2147 PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0]));
2149 switch (card.uid[0]) {
2150 case 0x02: // ST
2151 isST = true;
2152 isMifareClassic = false;
2153 break;
2154 case 0x04: // NXP
2155 nxptype = detect_nxp_card_print(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
2157 isMifareMini = ((nxptype & MTMINI) == MTMINI);
2158 isMifareClassic = ((nxptype & MTCLASSIC) == MTCLASSIC);
2159 isMifareDESFire = ((nxptype & MTDESFIRE) == MTDESFIRE);
2160 isMifarePlus = ((nxptype & MTPLUS) == MTPLUS);
2161 isMifareUltralight = ((nxptype & MTULTRALIGHT) == MTULTRALIGHT);
2162 isNTAG424 = ((nxptype & MT424) == MT424);
2164 if ((nxptype & MTOTHER) == MTOTHER)
2165 isMifareClassic = true;
2167 if ((nxptype & MTFUDAN) == MTFUDAN)
2168 isFUDAN = true;
2170 if ((nxptype & MTEMV) == MTEMV)
2171 isEMV = true;
2173 break;
2174 case 0x05: // Infineon
2175 if ((card.uid[1] & 0xF0) == 0x10) {
2176 printTag("my-d(tm) command set SLE 66R04/16/32P, SLE 66R04/16/32S");
2177 } else if ((card.uid[1] & 0xF0) == 0x20) {
2178 printTag("my-d(tm) command set SLE 66R01/16/32P (Type 2 Tag)");
2179 } else if ((card.uid[1] & 0xF0) == 0x30) {
2180 printTag("my-d(tm) move lean SLE 66R01P/66R01PN");
2181 } else if ((card.uid[1] & 0xF0) == 0x70) {
2182 printTag("my-d(tm) move lean SLE 66R01L");
2184 isMifareUltralight = true;
2185 isMifareClassic = false;
2187 if (card.sak == 0x88) {
2188 printTag("Infineon MIFARE CLASSIC 1K");
2189 isMifareUltralight = false;
2190 isMifareClassic = true;
2192 getTagLabel(card.uid[0], card.uid[1]);
2193 break;
2194 case 0x46:
2195 if (memcmp(card.uid, "FSTN10m", 7) == 0) {
2196 isMifareClassic = false;
2197 printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
2199 break;
2200 case 0x57:
2201 if (memcmp(card.uid, "WSDZ10m", 7) == 0) {
2202 isMifareClassic = false;
2203 printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
2205 break;
2206 default:
2207 getTagLabel(card.uid[0], card.uid[1]);
2208 switch (card.sak) {
2209 case 0x00: {
2210 isMifareClassic = false;
2212 // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc)
2213 DropField();
2215 uint64_t tagT = GetHF14AMfU_Type();
2216 if (tagT != MFU_TT_UL_ERROR) {
2217 ul_print_type(tagT, 0);
2218 isMifareUltralight = true;
2219 printTag("MIFARE Ultralight/C/NTAG Compatible");
2220 } else {
2221 printTag("Possible AZTEK (iso14443a compliant)");
2224 // reconnect for further tests
2225 clearCommandBuffer();
2226 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
2227 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
2228 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
2229 DropField();
2230 return PM3_ETIMEOUT;
2233 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
2235 select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
2237 if (select_status == 0) {
2238 DropField();
2239 return select_status;
2241 break;
2243 case 0x0A: {
2244 if (card.atqa[0] == 0x03) {
2245 // Uses Shanghai algo
2246 printTag("FM11RF005SH (FUDAN Shanghai Metro)");
2248 } else if (card.atqa[0] == 0x05) {
2249 // Uses MIFARE Crypto-1 algo
2250 printTag("FM11RF005M (FUDAN ISO14443A w Crypto-1 algo)");
2252 break;
2254 case 0x20: {
2255 printTag("JCOP 31/41");
2256 break;
2258 case 0x28: {
2259 printTag("JCOP31 or JCOP41 v2.3.1");
2260 break;
2262 case 0x38: {
2263 printTag("Nokia 6212 or 6131");
2264 break;
2266 case 0x53: {
2267 printTag("FM11RF08SH (FUDAN)");
2268 break;
2270 case 0x98: {
2271 printTag("Gemplus MPCOS");
2272 break;
2274 default: {
2275 break;
2278 break;
2282 // try to request ATS even if tag claims not to support it
2283 if (select_status == 2) {
2284 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
2285 clearCommandBuffer();
2286 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats));
2287 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
2288 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
2289 return PM3_ETIMEOUT;
2292 memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]);
2293 card.ats_len = resp.oldarg[0]; // note: ats_len includes CRC Bytes
2294 if (card.ats_len > 3) {
2295 select_status = 1;
2299 if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
2301 PrintAndLogEx(INFO, "-------------------------- " _CYAN_("ATS") " --------------------------");
2302 bool ta1 = 0, tb1 = 0, tc1 = 0;
2304 if (select_status == 2) {
2305 PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--");
2308 bool bad_ats = false;
2309 if (card.ats[0] != card.ats_len - 2) {
2310 PrintAndLogEx(WARNING, _RED_("ATS may be corrupted."));
2311 PrintAndLogEx(INFO, "Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
2312 bad_ats = true;
2315 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]);
2316 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]);
2318 if (bad_ats == false) {
2320 if ((card.ats[0] > 1) && (card.ats_len > 3)) { // there is a format byte (T0)
2321 ta1 = (card.ats[1] & 0x10) == 0x10;
2322 tb1 = (card.ats[1] & 0x20) == 0x20;
2323 tc1 = (card.ats[1] & 0x40) == 0x40;
2324 int16_t fsci = card.ats[1] & 0x0f;
2326 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
2327 "TC1 is%s present, FSCI is %d (FSC = %d)",
2328 card.ats[1],
2329 (ta1 ? "" : _RED_(" NOT")),
2330 (tb1 ? "" : _RED_(" NOT")),
2331 (tc1 ? "" : _RED_(" NOT")),
2332 fsci,
2333 fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1
2336 int pos = 2;
2337 if (ta1 && (card.ats_len > pos + 2)) {
2338 char dr[16], ds[16];
2339 dr[0] = ds[0] = '\0';
2340 if (card.ats[pos] & 0x10) strcat(ds, "2, ");
2341 if (card.ats[pos] & 0x20) strcat(ds, "4, ");
2342 if (card.ats[pos] & 0x40) strcat(ds, "8, ");
2343 if (card.ats[pos] & 0x01) strcat(dr, "2, ");
2344 if (card.ats[pos] & 0x02) strcat(dr, "4, ");
2345 if (card.ats[pos] & 0x04) strcat(dr, "8, ");
2346 if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
2347 if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
2348 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
2349 "DR: [%s], DS: [%s]",
2350 card.ats[pos],
2351 ((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""),
2356 pos++;
2359 if (tb1 && (card.ats_len > pos + 2)) {
2360 uint32_t sfgi = card.ats[pos] & 0x0F;
2361 uint32_t fwi = card.ats[pos] >> 4;
2363 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
2364 card.ats[pos],
2365 (sfgi),
2366 sfgi ? "" : "(not needed) ",
2367 sfgi ? (1 << 12) << sfgi : 0,
2368 fwi,
2369 (1 << 12) << fwi
2371 pos++;
2374 if (tc1 && (card.ats_len > pos + 2)) {
2375 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
2376 card.ats[pos],
2377 (card.ats[pos] & 0x01) ? "" : _RED_(" NOT"),
2378 (card.ats[pos] & 0x02) ? "" : _RED_(" NOT")
2380 pos++;
2383 // ATS - Historial bytes and identify based on it
2384 if ((card.ats[0] > pos) && (card.ats_len >= card.ats[0] + 2)) {
2385 char tip[60];
2386 tip[0] = '\0';
2387 if (card.ats[0] - pos >= 7) {
2389 snprintf(tip, sizeof(tip), " ");
2391 if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
2393 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2394 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
2396 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2398 if ((card.atqa[0] & 0x02) == 0x02) {
2399 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
2400 } else if ((card.atqa[0] & 0x04) == 0x04) {
2401 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
2404 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
2405 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
2407 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
2408 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
2411 } else { //SAK B4,5,6
2413 if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
2415 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2416 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
2417 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2418 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
2419 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
2420 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
2421 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
2422 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
2424 } else {
2425 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2426 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
2427 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2428 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
2434 uint8_t calen = card.ats[0] - pos;
2435 PrintAndLogEx(NORMAL, "");
2436 PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------");
2438 if (card.ats[pos] == 0xC1) {
2439 PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip);
2440 PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type");
2441 PrintAndLogEx(SUCCESS, " %02X.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]);
2442 switch (card.ats[pos + 2] & 0xf0) {
2443 case 0x10:
2444 PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire");
2445 isMifareDESFire = true;
2446 isMifareClassic = false;
2447 isMifarePlus = false;
2448 break;
2449 case 0x20:
2450 PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus");
2451 isMifarePlus = true;
2452 isMifareDESFire = false;
2453 isMifareClassic = false;
2454 break;
2456 switch (card.ats[pos + 2] & 0x0f) {
2457 case 0x00:
2458 PrintAndLogEx(SUCCESS, " x0............... < 1 kByte");
2459 break;
2460 case 0x01:
2461 PrintAndLogEx(SUCCESS, " x1............... 1 kByte");
2462 break;
2463 case 0x02:
2464 PrintAndLogEx(SUCCESS, " x2............... 2 kByte");
2465 break;
2466 case 0x03:
2467 PrintAndLogEx(SUCCESS, " x3............... 4 kByte");
2468 break;
2469 case 0x04:
2470 PrintAndLogEx(SUCCESS, " x4............... 8 kByte");
2471 break;
2473 switch (card.ats[pos + 3] & 0xf0) {
2474 case 0x00:
2475 PrintAndLogEx(SUCCESS, " 0x............ Engineering sample");
2476 break;
2477 case 0x20:
2478 PrintAndLogEx(SUCCESS, " 2x............ Released");
2479 break;
2481 switch (card.ats[pos + 3] & 0x0f) {
2482 case 0x00:
2483 PrintAndLogEx(SUCCESS, " x0............ Generation 1");
2484 break;
2485 case 0x01:
2486 PrintAndLogEx(SUCCESS, " x1............ Generation 2");
2487 break;
2488 case 0x02:
2489 PrintAndLogEx(SUCCESS, " x2............ Generation 3");
2490 break;
2492 switch (card.ats[pos + 4] & 0x0f) {
2493 case 0x00:
2494 PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported");
2495 break;
2496 case 0x01:
2497 PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported");
2498 break;
2499 case 0x0E:
2500 PrintAndLogEx(SUCCESS, " xE......... no VCS command supported");
2501 break;
2503 } else {
2505 if (card.ats[pos] == 0x80 || card.ats[pos] == 0x00) {
2506 PrintAndLogEx(SUCCESS, "%s (compact TLV data object)", sprint_hex_inrow(&card.ats[pos], calen));
2507 get_compact_tlv(card.ats + pos, calen);
2508 } else {
2509 PrintAndLogEx(SUCCESS, "%s - %s"
2510 , sprint_hex_inrow(card.ats + pos, calen)
2511 , sprint_ascii(card.ats + pos, calen)
2515 PrintAndLogEx(NORMAL, "");
2521 if (do_aid_search) {
2523 PrintAndLogEx(INFO, "-------------------- " _CYAN_("AID Search") " --------------------");
2525 json_t *root = AIDSearchInit(verbose);
2526 if (root != NULL) {
2527 bool found = false;
2528 bool ActivateField = true;
2529 for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) {
2531 if (kbd_enter_pressed()) {
2532 break;
2535 json_t *data = AIDSearchGetElm(root, elmindx);
2536 uint8_t vaid[200] = {0};
2537 int vaidlen = 0;
2538 if (!AIDGetFromElm(data, vaid, sizeof(vaid), &vaidlen) || !vaidlen)
2539 continue;
2541 uint16_t sw = 0;
2542 uint8_t result[1024] = {0};
2543 size_t resultlen = 0;
2544 int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, vaid, vaidlen, result, sizeof(result), &resultlen, &sw);
2545 ActivateField = false;
2546 if (res)
2547 continue;
2549 uint8_t dfname[200] = {0};
2550 size_t dfnamelen = 0;
2551 if (resultlen > 3) {
2552 struct tlvdb *tlv = tlvdb_parse_multi(result, resultlen);
2553 if (tlv) {
2554 // 0x84 Dedicated File (DF) Name
2555 const struct tlv *dfnametlv = tlvdb_get_tlv(tlvdb_find_full(tlv, 0x84));
2556 if (dfnametlv) {
2557 dfnamelen = dfnametlv->len;
2558 memcpy(dfname, dfnametlv->value, dfnamelen);
2560 tlvdb_free(tlv);
2564 if (sw == ISO7816_OK || sw == ISO7816_INVALID_DF || sw == ISO7816_FILE_TERMINATED) {
2565 if (sw == ISO7816_OK) {
2566 if (verbose) PrintAndLogEx(SUCCESS, "Application ( " _GREEN_("ok") " )");
2567 } else {
2568 if (verbose) PrintAndLogEx(WARNING, "Application ( " _RED_("blocked") " )");
2571 PrintAIDDescriptionBuf(root, vaid, vaidlen, verbose);
2573 if (dfnamelen) {
2574 if (dfnamelen == vaidlen) {
2575 if (memcmp(dfname, vaid, vaidlen) == 0) {
2576 if (verbose) PrintAndLogEx(INFO, "(DF) Name found and equal to AID");
2577 } else {
2578 PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
2579 PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
2581 } else {
2582 PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
2583 PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
2585 } else {
2586 if (verbose) PrintAndLogEx(INFO, "(DF) Name not found");
2589 if (verbose) PrintAndLogEx(SUCCESS, "----------------------------------------------------");
2590 found = true;
2591 isEMV = true;
2595 DropField();
2596 if (verbose == false && found)
2597 PrintAndLogEx(INFO, "----------------------------------------------------");
2601 } else {
2603 if (isISO18092) {
2604 PrintAndLogEx(INFO, "proprietary iso18092 card found");
2605 } else {
2607 PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
2608 if ((card.sak & 0x20) == 0x20) {
2609 PrintAndLogEx(INFO, "--> SAK incorrectly claims that card supports RATS <--");
2613 if (select_status == 1) {
2614 select_status = 2;
2618 if (setDeviceDebugLevel(verbose ? MAX(dbg_curr, DBG_INFO) : DBG_NONE, false) != PM3_SUCCESS) {
2619 return PM3_EFAILED;
2622 PrintAndLogEx(INFO, "");
2624 uint16_t isMagic = 0;
2626 if (isMifareClassic || isMifareMini) {
2627 isMagic = detect_mf_magic(true, MF_KEY_B, 0xFFFFFFFFFFFF);
2630 if (isMifareUltralight) {
2631 isMagic = detect_mf_magic(false, MF_KEY_A, 0);
2634 if (isMifareClassic || isMifareMini) {
2635 int res = detect_classic_static_nonce();
2636 if (res == NONCE_STATIC) {
2637 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
2640 if (res == NONCE_NORMAL) {
2641 // not static
2642 res = detect_classic_prng();
2643 if (res == 1) {
2644 PrintAndLogEx(SUCCESS, "Prng detection....... " _GREEN_("weak"));
2645 } else if (res == 0) {
2646 PrintAndLogEx(SUCCESS, "Prng detection....... " _YELLOW_("hard"));
2647 } else {
2648 PrintAndLogEx(FAILED, "Prng detection........ " _RED_("fail"));
2651 if (do_nack_test) {
2652 detect_classic_nackbug(false);
2656 uint8_t signature[32] = {0};
2657 res = read_mfc_ev1_signature(signature);
2658 if (res == PM3_SUCCESS) {
2659 mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
2663 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
2664 return PM3_EFAILED;
2667 PrintAndLogEx(NORMAL, "");
2668 if (isMifareUltralight) {
2670 if (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) {
2671 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands");
2674 if ((isMagic & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
2675 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands");
2678 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`");
2681 if (isMifarePlus && (isMagic == MAGIC_FLAG_NONE)) {
2682 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfp info") "`");
2685 if (isMifareDESFire && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) {
2686 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfdes info") "`");
2689 if (isST) {
2690 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st info") "`");
2693 if (isEMV) {
2694 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv reader") "`");
2697 if (isSEOS) {
2698 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf seos info") "`");
2701 if (isFUDAN) {
2702 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`");
2704 PrintAndLogEx(HINT, " hf 14a raw -a -b 7 -k 26");
2705 PrintAndLogEx(HINT, " hf 14a raw -k -c 3000");
2706 PrintAndLogEx(HINT, " hf 14a raw -k -c 3001");
2707 PrintAndLogEx(HINT, " hf 14a raw -k -c 3002");
2708 PrintAndLogEx(HINT, " hf 14a raw -k -c 3003");
2709 PrintAndLogEx(HINT, " hf 14a raw -k -c 3004");
2710 PrintAndLogEx(HINT, " hf 14a raw -k -c 3005");
2711 PrintAndLogEx(HINT, " hf 14a raw -k -c 3006");
2712 PrintAndLogEx(HINT, " hf 14a raw -c 3007");
2716 if (isNTAG424) {
2717 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf ntag424 info") "`");
2720 if (isMifareClassic || isMifareMini) {
2721 if (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) {
2722 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf c*") "` magic commands");
2724 // if GEN4 GDM in Gen1a more, hint about it
2725 if ((isMagic & MAGIC_FLAG_GDM_WUP_40) == MAGIC_FLAG_GDM_WUP_40) {
2726 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf gdm* --gen1a") "` magic commands");
2730 if ((isMagic & MAGIC_FLAG_GEN_3) == MAGIC_FLAG_GEN_3) {
2731 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf gen3*") "` magic commands");
2734 if ((isMagic & MAGIC_FLAG_GEN_4GTU) == MAGIC_FLAG_GEN_4GTU) {
2735 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf g*") "` magic commands");
2738 if ((isMagic & MAGIC_FLAG_GDM_AUTH) == MAGIC_FLAG_GDM_AUTH) {
2739 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf gdm*") "` magic commands");
2742 if ((isMagic & MAGIC_FLAG_GEN_2) == MAGIC_FLAG_GEN_2) {
2743 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf") "` commands");
2744 } else {
2745 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands");
2750 PrintAndLogEx(NORMAL, "");
2751 DropField();
2752 return select_status;
2755 int infoHF14A4Applications(bool verbose) {
2756 bool cardFound[ARRAYLEN(hintAIDList)] = {0};
2757 bool ActivateField = true;
2758 int found = 0;
2759 for (int i = 0; i < ARRAYLEN(hintAIDList); i++) {
2760 uint16_t sw = 0;
2761 uint8_t result[1024] = {0};
2762 size_t resultlen = 0;
2763 int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, (uint8_t *)hintAIDList[i].aid, hintAIDList[i].aid_length, result, sizeof(result), &resultlen, &sw);
2764 ActivateField = false;
2765 if (res)
2766 break;
2768 if (sw == ISO7816_OK || sw == ISO7816_INVALID_DF || sw == ISO7816_FILE_TERMINATED) {
2769 if (!found) {
2770 if (verbose)
2771 PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------");
2773 found++;
2775 if (sw == ISO7816_OK) {
2776 if (verbose)
2777 PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc);
2778 cardFound[i] = true;
2779 } else {
2780 if (verbose)
2781 PrintAndLogEx(WARNING, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList[i].desc);
2786 if (found) {
2787 if (verbose) {
2788 PrintAndLogEx(INFO, "---------------------------------------------------");
2791 if (found >= ARRAYLEN(hintAIDList) - 1) {
2792 PrintAndLogEx(HINT, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card.");
2793 } else {
2794 for (int i = 0; i < ARRAYLEN(hintAIDList); i++) {
2795 if (cardFound[i] && strlen(hintAIDList[i].hint))
2796 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("%s") "` commands", hintAIDList[i].hint);
2801 DropField();
2802 return found;
2805 static uint32_t inc_sw_error_occurrence(uint16_t sw, uint32_t *all_sw) {
2806 uint8_t sw1 = (uint8_t)(sw >> 8);
2807 uint8_t sw2 = (uint8_t)(0xff & sw);
2809 // Don't count successes
2810 if (sw1 == 0x90 && sw2 == 0x00) {
2811 return 0;
2814 // Always max "Instruction not supported"
2815 if (sw1 == 0x6D && sw2 == 0x00) {
2816 return 0xFFFFFFFFUL;
2819 all_sw[(sw1 * 256) + sw2]++;
2821 return all_sw[(sw1 * 256) + sw2];
2824 static int CmdHf14AFindapdu(const char *Cmd) {
2825 // TODO: Option to select AID/File (and skip INS 0xA4).
2826 // TODO: Check all instructions with extended APDUs if the card support it.
2827 // TODO: Option to reset tag before every command.
2828 CLIParserContext *ctx;
2829 CLIParserInit(&ctx, "hf 14a apdufind",
2830 "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands.\n"
2831 "It loops all 256 possible values for each byte.\n"
2832 "The loop oder is INS -> P1/P2 (alternating) -> CLA.\n"
2833 "Tag must be on antenna before running.",
2834 "hf 14a apdufind\n"
2835 "hf 14a apdufind --cla 80\n"
2836 "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le\n"
2839 void *argtable[] = {
2840 arg_param_begin,
2841 arg_str0("c", "cla", "<hex>", "Start value of CLASS (1 hex byte)"),
2842 arg_str0("i", "ins", "<hex>", "Start value of INSTRUCTION (1 hex byte)"),
2843 arg_str0(NULL, "p1", "<hex>", "Start value of P1 (1 hex byte)"),
2844 arg_str0(NULL, "p2", "<hex>", "Start value of P2 (1 hex byte)"),
2845 arg_u64_0("r", "reset", "<number>", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"),
2846 arg_u64_0("e", "error-limit", "<number>", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."),
2847 arg_strx0("s", "skip-ins", "<hex>", "Do not test an instruction (can be specified multiple times)"),
2848 arg_lit0("l", "with-le", "Search for APDUs with Le=0 (case 2S) as well"),
2849 arg_lit0("v", "verbose", "Verbose output"),
2850 arg_param_end
2852 CLIExecWithReturn(ctx, Cmd, argtable, true);
2854 int cla_len = 0;
2855 uint8_t cla_arg[1] = {0};
2856 CLIGetHexWithReturn(ctx, 1, cla_arg, &cla_len);
2858 int ins_len = 0;
2859 uint8_t ins_arg[1] = {0};
2860 CLIGetHexWithReturn(ctx, 2, ins_arg, &ins_len);
2862 int p1_len = 0;
2863 uint8_t p1_arg[1] = {0};
2864 CLIGetHexWithReturn(ctx, 3, p1_arg, &p1_len);
2866 int p2_len = 0;
2867 uint8_t p2_arg[1] = {0};
2868 CLIGetHexWithReturn(ctx, 4, p2_arg, &p2_len);
2870 uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60);
2871 uint32_t error_limit = arg_get_u64_def(ctx, 6, 512);
2873 int ignore_ins_len = 0;
2874 uint8_t ignore_ins_arg[250] = {0};
2875 CLIGetHexWithReturn(ctx, 7, ignore_ins_arg, &ignore_ins_len);
2877 bool with_le = arg_get_lit(ctx, 8);
2878 bool verbose = arg_get_lit(ctx, 9);
2880 CLIParserFree(ctx);
2882 bool activate_field = true;
2883 bool keep_field_on = true;
2884 uint8_t cla = cla_arg[0];
2885 uint8_t ins = ins_arg[0];
2886 uint8_t p1 = p1_arg[0];
2887 uint8_t p2 = p2_arg[0];
2889 uint8_t response[PM3_CMD_DATA_SIZE] = {0};
2890 int response_n = 0;
2891 uint8_t aSELECT_AID[80];
2892 int aSELECT_AID_n = 0;
2894 // Check if the tag reponds to APDUs.
2895 PrintAndLogEx(INFO, "Sending a test APDU (select file command) to check if the tag is responding to APDU");
2896 param_gethex_to_eol("00a404000aa000000440000101000100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
2897 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, true, false, response, sizeof(response), &response_n);
2898 if (res != PM3_SUCCESS) {
2899 PrintAndLogEx(FAILED, "Tag did not respond to a test APDU (select file command). Aborting...");
2900 return res;
2903 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
2904 PrintAndLogEx(NORMAL, "");
2905 PrintAndLogEx(SUCCESS, "Starting the APDU finder [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2907 bool inc_p1 = false;
2908 bool skip_ins = false;
2909 uint32_t all_sw[256][256] = { { 0 } };
2910 uint32_t sw_occurrences = 0;
2912 uint64_t t_start = msclock();
2913 uint64_t t_last_reset = msclock();
2915 // Enumerate APDUs.
2916 do {
2917 do {
2918 do {
2919 retry_ins:
2920 // Exit (was the Enter key pressed)?
2921 if (kbd_enter_pressed()) {
2922 PrintAndLogEx(INFO, "User interrupted detected. Aborting");
2923 goto out;
2926 // Skip/Ignore this instrctuion?
2927 for (int i = 0; i < ignore_ins_len; i++) {
2928 if (ins == ignore_ins_arg[i]) {
2929 skip_ins = true;
2930 break;
2934 if (skip_ins) {
2935 skip_ins = false;
2936 continue;
2939 if (verbose) {
2940 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2943 // Send APDU without Le (case 1) and with Le = 0 (case 2S), if "with-le" was set.
2944 uint8_t command[5] = {cla, ins, p1, p2, 0x00};
2945 int command_n = 4;
2946 for (int i = 0; i < 1 + with_le; i++) {
2947 // Send APDU.
2948 res = ExchangeAPDU14a(command, command_n + i, activate_field, keep_field_on, response, sizeof(response), &response_n);
2949 if (res != PM3_SUCCESS) {
2950 DropField();
2951 activate_field = true;
2952 goto retry_ins;
2955 uint16_t sw = get_sw(response, response_n);
2956 sw_occurrences = inc_sw_error_occurrence(sw, all_sw[0]);
2958 // Show response.
2959 if (sw_occurrences < error_limit) {
2960 logLevel_t log_level = INFO;
2961 if (sw == ISO7816_OK) {
2962 log_level = SUCCESS;
2965 if (verbose == true || sw != 0x6e00) {
2966 PrintAndLogEx(log_level, "Got response for APDU \"%s\": %04X (%s)",
2967 sprint_hex_inrow(command, command_n + i),
2969 GetAPDUCodeDescription(sw >> 8, sw & 0xff)
2972 if (response_n > 2) {
2973 PrintAndLogEx(SUCCESS, "Response data is: %s | %s",
2974 sprint_hex_inrow(response, response_n - 2),
2975 sprint_ascii(response, response_n - 2)
2981 // Do not reativate the filed until the next reset.
2982 activate_field = false;
2983 } while (++ins != ins_arg[0]);
2985 // Increment P1/P2 in an alternating fashion.
2986 if (inc_p1) {
2987 p1++;
2988 } else {
2989 p2++;
2992 inc_p1 = !inc_p1;
2994 // Check if re-selecting the card is needed.
2995 uint64_t t_since_last_reset = ((msclock() - t_last_reset) / 1000);
2996 if (t_since_last_reset > reset_time) {
2997 DropField();
2998 activate_field = true;
2999 t_last_reset = msclock();
3000 PrintAndLogEx(INFO, "Last reset was %" PRIu64 " seconds ago. Resetting the tag to prevent timeout issues", t_since_last_reset);
3002 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
3004 } while (p1 != p1_arg[0] || p2 != p2_arg[0]);
3006 cla++;
3007 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
3009 } while (cla != cla_arg[0]);
3011 out:
3012 PrintAndLogEx(SUCCESS, "Runtime: %" PRIu64 " seconds\n", (msclock() - t_start) / 1000);
3013 DropField();
3014 return PM3_SUCCESS;
3017 int CmdHF14ANdefRead(const char *Cmd) {
3018 CLIParserContext *ctx;
3019 CLIParserInit(&ctx, "hf 14a ndefread",
3020 "Read NFC Data Exchange Format (NDEF) file on Type 4 NDEF tag",
3021 "hf 14a ndefread\n"
3022 "hf 14a ndefread -f myfilename -> save raw NDEF to file"
3025 void *argtable[] = {
3026 arg_param_begin,
3027 arg_str0("f", "file", "<fn>", "save raw NDEF to file"),
3028 arg_litn("v", "verbose", 0, 2, "verbose output"),
3029 arg_param_end
3031 CLIExecWithReturn(ctx, Cmd, argtable, true);
3032 int fnlen = 0;
3033 char filename[FILE_PATH_SIZE] = {0};
3034 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3036 bool verbose = arg_get_lit(ctx, 2);
3037 bool verbose2 = arg_get_lit(ctx, 2) > 1;
3038 CLIParserFree(ctx);
3040 bool activate_field = true;
3041 bool keep_field_on = true;
3042 uint8_t response[PM3_CMD_DATA_SIZE];
3043 int resplen = 0;
3044 bool backward_compatibility_v1 = false;
3046 // --------------- Select NDEF Tag application ----------------
3047 uint8_t aSELECT_AID[80];
3048 int aSELECT_AID_n = 0;
3049 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
3050 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3051 if (res != PM3_SUCCESS) {
3052 DropField();
3053 return res;
3056 if (resplen < 2) {
3057 DropField();
3058 return PM3_ESOFT;
3061 uint16_t sw = get_sw(response, resplen);
3062 if (sw != ISO7816_OK) {
3063 // Try NDEF Type 4 Tag v1.0
3064 param_gethex_to_eol("00a4040007d2760000850100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
3065 res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3066 if (res != PM3_SUCCESS) {
3067 DropField();
3068 return res;
3070 if (resplen < 2) {
3071 DropField();
3072 return PM3_ESOFT;
3075 sw = get_sw(response, resplen);
3076 if (sw != ISO7816_OK) {
3077 PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3078 DropField();
3079 return PM3_ESOFT;
3081 backward_compatibility_v1 = true;
3084 activate_field = false;
3085 keep_field_on = true;
3087 // --------------- CC file reading ----------------
3088 uint8_t aSELECT_FILE_CC[30];
3089 int aSELECT_FILE_CC_n = 0;
3090 if (backward_compatibility_v1) {
3091 param_gethex_to_eol("00a4000002e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
3092 } else {
3093 param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
3095 res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3096 if (res != PM3_SUCCESS) {
3097 DropField();
3098 return res;
3101 sw = get_sw(response, resplen);
3102 if (sw != ISO7816_OK) {
3103 PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3104 DropField();
3105 return PM3_ESOFT;
3108 uint8_t aREAD_CC[30];
3109 int aREAD_CC_n = 0;
3110 param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n);
3111 res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3112 if (res != PM3_SUCCESS) {
3113 DropField();
3114 return res;
3116 sw = get_sw(response, resplen);
3117 if (sw != ISO7816_OK) {
3118 PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3119 DropField();
3120 return PM3_ESOFT;
3123 // Parse CC data
3124 uint8_t cc_data[resplen - 2];
3125 memcpy(cc_data, response, sizeof(cc_data));
3126 uint8_t file_id[2] = {cc_data[9], cc_data[10]};
3128 if (verbose) {
3129 print_type4_cc_info(cc_data, sizeof(cc_data));
3132 uint16_t max_rapdu_size = (cc_data[3] << 8 | cc_data[4]) - 2;
3133 max_rapdu_size = max_rapdu_size < sizeof(response) - 2 ? max_rapdu_size : sizeof(response) - 2;
3135 // --------------- NDEF file reading ----------------
3136 uint8_t aSELECT_FILE_NDEF[30];
3137 int aSELECT_FILE_NDEF_n = 0;
3138 if (backward_compatibility_v1) {
3139 param_gethex_to_eol("00a4000002", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
3140 } else {
3141 param_gethex_to_eol("00a4000c02", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
3143 memcpy(aSELECT_FILE_NDEF + aSELECT_FILE_NDEF_n, file_id, sizeof(file_id));
3144 res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n + sizeof(file_id), activate_field, keep_field_on, response, sizeof(response), &resplen);
3145 if (res != PM3_SUCCESS) {
3146 DropField();
3147 return res;
3150 sw = get_sw(response, resplen);
3151 if (sw != ISO7816_OK) {
3152 PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3153 DropField();
3154 return PM3_ESOFT;
3157 // read first 2 bytes to get NDEF length
3158 uint8_t aREAD_NDEF[30];
3159 int aREAD_NDEF_n = 0;
3160 param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
3161 res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3162 if (res != PM3_SUCCESS) {
3163 DropField();
3164 return res;
3167 sw = get_sw(response, resplen);
3168 if (sw != ISO7816_OK) {
3169 PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3170 DropField();
3171 return PM3_ESOFT;
3174 uint16_t ndef_size = (response[0] << 8) + response[1];
3175 uint16_t offset = 2;
3176 uint8_t *ndef_file = calloc(ndef_size, sizeof(uint8_t));
3177 if (ndef_file == NULL) {
3178 PrintAndLogEx(ERR, "Out of memory error in CmdHF14ANdef(). Aborting...\n");
3179 DropField();
3180 return PM3_EMALLOC;
3183 if (ndef_size + offset > 0xFFFF) {
3184 PrintAndLogEx(ERR, "NDEF size abnormally large in CmdHF14ANdef(). Aborting...\n");
3185 free(ndef_file);
3186 DropField();
3187 return PM3_EOVFLOW;
3190 for (uint16_t i = offset; i < ndef_size + offset; i += max_rapdu_size) {
3191 uint16_t segment_size = max_rapdu_size < ndef_size + offset - i ? max_rapdu_size : ndef_size + offset - i;
3192 keep_field_on = i < ndef_size + offset - max_rapdu_size;
3193 aREAD_NDEF_n = 0;
3194 param_gethex_to_eol("00b00000", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
3195 aREAD_NDEF[2] = i >> 8;
3196 aREAD_NDEF[3] = i & 0xFF;
3197 aREAD_NDEF[4] = segment_size;
3199 res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n + 1, activate_field, keep_field_on, response, sizeof(response), &resplen);
3200 if (res != PM3_SUCCESS) {
3201 DropField();
3202 free(ndef_file);
3203 return res;
3206 sw = get_sw(response, resplen);
3207 if (sw != ISO7816_OK) {
3208 PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3209 DropField();
3210 free(ndef_file);
3211 return PM3_ESOFT;
3214 if (resplen != segment_size + 2) {
3215 PrintAndLogEx(ERR, "reading NDEF file failed, expected %i bytes, got %i bytes.", segment_size, resplen - 2);
3216 DropField();
3217 free(ndef_file);
3218 return PM3_ESOFT;
3221 memcpy(ndef_file + (i - offset), response, segment_size);
3224 if (verbose2) {
3225 PrintAndLogEx(NORMAL, "");
3226 PrintAndLogEx(INFO, "--- " _CYAN_("NDEF raw") " ----------------");
3227 print_buffer(ndef_file, ndef_size, 1);
3230 NDEFRecordsDecodeAndPrint(ndef_file, ndef_size, verbose);
3232 pm3_save_dump(filename, ndef_file, ndef_size, jsfNDEF);
3234 if (verbose == false) {
3235 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf 14a ndefread -v`") " for more details");
3236 } else {
3237 if (verbose2 == false) {
3238 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf 14a ndefread -vv`") " for more details");
3242 free(ndef_file);
3243 return PM3_SUCCESS;
3246 int CmdHF14ANdefFormat(const char *Cmd) {
3247 CLIParserContext *ctx;
3248 CLIParserInit(&ctx, "hf 14a ndefformat",
3249 "Format ISO14443-a Tag as a NFC tag with Data Exchange Format (NDEF)",
3250 "hf 14a ndefformat\n"
3253 void *argtable[] = {
3254 arg_param_begin,
3255 arg_lit0("v", "verbose", "verbose output"),
3256 arg_param_end
3258 CLIExecWithReturn(ctx, Cmd, argtable, true);
3259 bool verbose = arg_get_lit(ctx, 1);
3260 CLIParserFree(ctx);
3262 if (g_session.pm3_present == false)
3263 return PM3_ENOTTY;
3265 bool activate_field = true;
3266 bool keep_field_on = false;
3267 uint8_t response[PM3_CMD_DATA_SIZE];
3268 int resplen = 0;
3270 SetAPDULogging(false);
3272 // step 1 - Select NDEF Tag application
3273 uint8_t aSELECT_AID[80];
3274 int aSELECT_AID_n = 0;
3275 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
3276 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3278 if (res != PM3_SUCCESS) {
3279 return res;
3282 if (resplen < 2) {
3283 return PM3_ESOFT;
3286 bool have_application = true;
3287 uint16_t sw = get_sw(response, resplen);
3288 if (sw != ISO7816_OK) {
3289 have_application = false;
3290 PrintAndLogEx(INFO, "no NDEF application found");
3291 } else {
3292 PrintAndLogEx(INFO, "found ndef application");
3296 // setup desfire authentication context
3297 uint8_t empty_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3298 DesfireContext_t dctx;
3299 dctx.secureChannel = DACNone;
3300 DesfireSetKey(&dctx, 0, T_DES, empty_key);
3301 DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
3302 DesfireSetCommandSet(&dctx, DCCNativeISO);
3303 DesfireSetCommMode(&dctx, DCMPlain);
3305 // step 1 - create application
3306 if (have_application == false) {
3307 // "hf mfdes createapp --aid 000001 --fid E110 --ks1 0B --ks2 A1 --dfhex D2760000850101 -t des -n 0 -k 0000000000000000"
3308 PrintAndLogEx(INFO, "creating NDEF application...");
3310 // authenticae first to AID 00 00 00
3311 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000000, false, verbose);
3312 if (res != PM3_SUCCESS) {
3313 DropField();
3314 PrintAndLogEx(INFO, "failed empty auth..");
3315 return res;
3318 // create application
3319 uint8_t dfname[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
3320 uint8_t ks1 = 0x0B;
3321 uint8_t ks2 = 0xA1; // bit FileID in ks2
3322 uint32_t appid = 0x0000001;
3323 uint16_t fileid = 0xE110;
3324 uint8_t data[250] = {0};
3325 size_t datalen = 0;
3327 DesfireAIDUintToByte(appid, &data[0]);
3328 data[3] = ks1;
3329 data[4] = ks2;
3330 Uint2byteToMemLe(&data[5], fileid);
3331 memcpy(&data[7], dfname, sizeof(dfname));
3332 datalen = 14;
3334 if (verbose) {
3335 PrintAndLogEx(INFO, "---------------------------");
3336 PrintAndLogEx(INFO, _CYAN_("Creating Application using:"));
3337 PrintAndLogEx(INFO, "AID........... 0x%02X%02X%02X", data[2], data[1], data[0]);
3338 PrintAndLogEx(INFO, "Key Set 1..... 0x%02X", data[3]);
3339 PrintAndLogEx(INFO, "Key Set 2..... 0x%02X", data[4]);
3340 PrintAndLogEx(INFO, "ISO file ID... %s", (data[4] & 0x20) ? "enabled" : "disabled");
3341 if ((data[4] & 0x20)) {
3342 PrintAndLogEx(INFO, "ISO file ID... 0x%04X", MemLeToUint2byte(&data[5]));
3343 PrintAndLogEx(INFO, "DF Name[%02d] %s | %s\n", 7, sprint_ascii(dfname, sizeof(dfname)), sprint_hex(dfname, sizeof(dfname)));
3345 PrintKeySettings(data[3], data[4], true, true);
3346 PrintAndLogEx(INFO, "---------------------------");
3349 res = DesfireCreateApplication(&dctx, data, datalen);
3350 if (res != PM3_SUCCESS) {
3351 PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res);
3352 DropField();
3353 return PM3_ESOFT;
3356 PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid);
3359 // step 2 - create capability container (CC File)
3361 // authenticae to the new AID 00 00 01
3362 uint8_t aes_key[] = {
3363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3366 dctx.secureChannel = DACNone;
3367 DesfireSetKey(&dctx, 0, T_AES, aes_key);
3368 DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
3369 DesfireSetCommandSet(&dctx, DCCNativeISO);
3370 DesfireSetCommMode(&dctx, DCMPlain);
3371 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose);
3372 if (res != PM3_SUCCESS) {
3373 DropField();
3374 PrintAndLogEx(INFO, "failed aid auth..");
3375 return res;
3378 // hf mfdes createfile --aid 000001 --fid 01 --isofid E103 --amode plain --size 00000F
3379 // --rrights free --wrights key0 --rwrights key0 --chrights key0
3380 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3381 uint8_t fid = 0x01;
3382 uint16_t isofid = 0xE103;
3383 uint32_t fsize = 0x0F;
3384 uint8_t filetype = 0x00; // standard file
3386 // file access mode: plain 0x00
3387 // read access: free 0x0E
3388 // write access: key0 0x00
3389 // r/w access: key0 0x00
3390 // change access: key0 0x00
3391 memset(data, 0x00, sizeof(data));
3392 datalen = 0;
3394 data[0] = fid;
3395 data[1] = isofid & 0xff;
3396 data[2] = (isofid >> 8) & 0xff;
3397 datalen = 3;
3399 uint8_t *settings = &data[datalen];
3400 settings[0] = 0x00;
3401 datalen++;
3403 DesfireEncodeFileAcessMode(&settings[1], 0x0E, 0x00, 0x00, 0x00) ;
3404 datalen += 2;
3406 Uint3byteToMemLe(&data[datalen], fsize);
3407 datalen += 3;
3409 if (verbose) {
3410 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
3413 DesfirePrintCreateFileSettings(filetype, data, datalen);
3415 res = DesfireCreateFile(&dctx, filetype, data, datalen, true); // check length only if we dont use raw mode
3416 if (res != PM3_SUCCESS) {
3417 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
3418 DropField();
3419 return PM3_ESOFT;
3422 PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
3426 // hf mfdes write --aid 000001 --fid 01 -d 000F20003B00340406E10400FF00FF
3427 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3428 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose);
3429 if (res != PM3_SUCCESS) {
3430 DropField();
3431 PrintAndLogEx(INFO, "failed aid auth..");
3432 return res;
3435 uint8_t fnum = 0x01;
3436 uint32_t offset = 0;
3437 uint8_t cc_data[] = {0x00, 0x0F, 0x20, 0x00, 0x3B, 0x00, 0x34, 0x04, 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00};
3439 res = DesfireWriteFile(&dctx, fnum, offset, sizeof(cc_data), cc_data);
3440 if (res != PM3_SUCCESS) {
3441 PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res);
3442 DropField();
3443 return PM3_ESOFT;
3446 if (verbose) {
3447 PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum);
3452 // step 3 - create NDEF record file
3453 // hf mfdes write --aid 000001 --fid 02 -d 000CD1010855016E78702E636F6DFE
3454 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3456 fid = 0x02;
3457 isofid = 0xE104;
3458 fsize = 0xFF;
3459 filetype = 0x00; // standard file
3461 // file access mode: plain 0x00
3462 // read access: free 0x0E
3463 // write access: key0 0x00
3464 // r/w access: key0 0x00
3465 // change access: key0 0x00
3466 memset(data, 0x00, sizeof(data));
3467 datalen = 0;
3469 data[0] = fid;
3470 data[1] = isofid & 0xff;
3471 data[2] = (isofid >> 8) & 0xff;
3472 datalen = 3;
3474 settings = &data[datalen];
3475 settings[0] = 0x00;
3476 datalen++;
3478 DesfireEncodeFileAcessMode(&settings[1], 0x0E, 0x00, 0x00, 0x00) ;
3479 datalen += 2;
3481 Uint3byteToMemLe(&data[datalen], fsize);
3482 datalen += 3;
3484 if (verbose) {
3485 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
3488 DesfirePrintCreateFileSettings(filetype, data, datalen);
3490 res = DesfireCreateFile(&dctx, filetype, data, datalen, true); // check length only if we dont use raw mode
3491 if (res != PM3_SUCCESS) {
3492 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
3493 DropField();
3494 return PM3_ESOFT;
3497 PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
3499 DropField();
3502 PrintAndLogEx(NORMAL, "");
3503 PrintAndLogEx(INFO, "finished");
3504 return PM3_SUCCESS;
3507 int CmdHF14ANdefWrite(const char *Cmd) {
3508 CLIParserContext *ctx;
3509 CLIParserInit(&ctx, "hf 14a ndefwrite",
3510 "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n",
3511 "hf 14a ndefwrite -d 0300FE -> write empty record to tag\n"
3512 "hf 14a ndefwrite -f myfilename\n"
3513 "hf 14a ndefwrite -d 003fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\n"
3516 void *argtable[] = {
3517 arg_param_begin,
3518 arg_str0("d", NULL, "<hex>", "raw NDEF hex bytes"),
3519 arg_str0("f", "file", "<fn>", "write raw NDEF file to tag"),
3520 arg_lit0("p", NULL, "fix NDEF record headers / terminator block if missing"),
3521 arg_lit0("v", "verbose", "verbose output"),
3522 arg_param_end
3524 CLIExecWithReturn(ctx, Cmd, argtable, false);
3526 uint8_t raw[256] = {0};
3527 int rawlen = 0;
3528 CLIGetHexWithReturn(ctx, 1, raw, &rawlen);
3530 int fnlen = 0;
3531 char filename[FILE_PATH_SIZE] = {0};
3532 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3534 bool fix_msg = arg_get_lit(ctx, 3);
3535 bool verbose = arg_get_lit(ctx, 4);
3536 CLIParserFree(ctx);
3538 if (g_session.pm3_present == false) {
3539 return PM3_ENOTTY;
3542 if ((rawlen && fnlen) || (rawlen == 0 && fnlen == 0)) {
3543 PrintAndLogEx(WARNING, "Please specify either raw hex or filename");
3544 return PM3_EINVARG;
3547 int res = PM3_SUCCESS;
3548 int32_t bytes = rawlen;
3550 // read dump file
3551 if (fnlen) {
3552 uint8_t *dump = NULL;
3553 size_t bytes_read = 0;
3554 res = pm3_load_dump(filename, (void **)&dump, &bytes_read, sizeof(raw));
3555 if (res != PM3_SUCCESS) {
3556 return res;
3558 memcpy(raw, dump, bytes_read);
3559 bytes = bytes_read;
3560 free(dump);
3563 if (verbose) {
3564 PrintAndLogEx(INFO, "Num of bytes... %i (raw %i)", bytes, rawlen);
3567 // Has raw bytes ndef message header?bytes
3568 switch (raw[0]) {
3569 case 0x00:
3570 case 0x01:
3571 case 0x02:
3572 case 0x03:
3573 case 0xFD:
3574 case 0xFE:
3575 break;
3576 default: {
3577 if (fix_msg == false) {
3578 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a proper header, continuing...");
3579 } else {
3580 if (bytes + 2 > sizeof(raw)) {
3581 PrintAndLogEx(WARNING, "no room for header, exiting...");
3582 return PM3_EMALLOC;
3584 uint8_t tmp_raw[256];
3585 memcpy(tmp_raw, raw, sizeof(tmp_raw));
3586 raw[0] = 0x00;
3587 raw[1] = bytes;
3588 memcpy(raw + 2, tmp_raw, sizeof(raw) - 2);
3589 bytes += 2;
3590 PrintAndLogEx(SUCCESS, "Added generic message header (0x03)");
3595 // Has raw bytes ndef a terminator block?
3596 if (raw[bytes - 1] != 0xFE) {
3597 if (fix_msg == false) {
3598 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a terminator block, continuing...");
3599 } else {
3601 if (bytes + 1 > sizeof(raw)) {
3602 PrintAndLogEx(WARNING, "no room for terminator block, exiting...");
3603 return PM3_EMALLOC;
3605 raw[bytes] = 0xFE;
3606 bytes++;
3607 PrintAndLogEx(SUCCESS, "Added terminator block (0xFE)");
3611 if (verbose) {
3612 PrintAndLogEx(INFO, "Num of Bytes... %u", bytes);
3613 print_buffer(raw, bytes, 0);
3617 // setup desfire authentication context
3618 // authenticae to the new AID 00 00 01
3619 uint8_t aes_key[] = {
3620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3624 DesfireContext_t dctx;
3625 dctx.secureChannel = DACNone;
3626 DesfireSetKey(&dctx, 0, T_AES, aes_key);
3627 DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
3628 DesfireSetCommandSet(&dctx, DCCNativeISO);
3629 DesfireSetCommMode(&dctx, DCMPlain);
3630 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose);
3631 if (res != PM3_SUCCESS) {
3632 DropField();
3633 PrintAndLogEx(INFO, "failed aid auth..");
3634 return res;
3637 // write ndef file
3639 // hf mfdes write --aid 000002 --fid 02 -
3640 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3641 uint8_t fnum = 0x02;
3642 uint32_t offset = 0;
3644 res = DesfireWriteFile(&dctx, fnum, offset, bytes, raw);
3645 if (res != PM3_SUCCESS) {
3646 PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res);
3647 DropField();
3648 return PM3_ESOFT;
3651 if (verbose) {
3652 PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum);
3655 PrintAndLogEx(NORMAL, "");
3656 PrintAndLogEx(INFO, "finished");
3657 return PM3_SUCCESS;
3661 * Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values
3662 * These AID Values can be responded to and include extra APDU commands after verification
3665 int CmdHF14AAIDSim(const char *Cmd) {
3666 CLIParserContext *ctx;
3667 CLIParserInit(&ctx, "hf 14a simaid",
3668 "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values\n"
3669 "These AID Values can be responded to and include extra APDU commands on GetData after response\n",
3670 "hf 14a simaid -t 3 -> MIFARE Desfire\n"
3671 "hf 14a simaid -t 4 -> ISO/IEC 14443-4\n"
3672 "hf 14a simaid -t 11 -> Javacard (JCOP)\n"
3673 "hf 14a simaid -t 3 --aid a000000000000000000000 --response 9000 --apdu 9000 -> AID, Response and APDU\n"
3674 "hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added\n"
3675 "hf 14a simaid -t 3 --rats 05788172220101 -x -> Enumerate AID Values\n"
3678 void *argtable[] = {
3679 arg_param_begin,
3680 arg_int1("t", "type", "<1-12> ", "Simulation type to use"),
3681 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
3682 arg_str0("r", "rats", "<hex>", "<0-20> hex bytes RATS"),
3683 arg_str0("a", "aid", "<hex>", "<0-100> hex bytes for AID to respond to (Default: A000000000000000000000)"),
3684 arg_str0("e", "response", "<hex>", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"),
3685 arg_str0("p", "apdu", "<hex>", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"),
3686 arg_lit0("x", "enumerate", "Enumerate all AID values via returning Not Found and print them to console "),
3687 arg_param_end
3689 CLIExecWithReturn(ctx, Cmd, argtable, false);
3691 int tagtype = arg_get_int_def(ctx, 1, 1);
3693 bool enumerate = arg_get_lit(ctx, 7);
3695 int uid_len = 0;
3696 int rats_len = 0;
3697 int aid_len = 0;
3698 int respond_len = 0;
3699 int apdu_len = 0;
3701 uint8_t uid[10] = {0};
3702 uint8_t rats[20] = {0};
3703 uint8_t aid[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3704 uint8_t response[100] = {0x90, 0x00};
3705 uint8_t apdu[100] = {0x90, 0x00};
3707 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
3708 CLIGetHexWithReturn(ctx, 3, rats, &rats_len);
3709 CLIGetHexWithReturn(ctx, 4, aid, &aid_len);
3710 CLIGetHexWithReturn(ctx, 5, response, &respond_len);
3711 CLIGetHexWithReturn(ctx, 6, apdu, &apdu_len);
3713 // default value fill for the AID, response, and apdu
3714 if (aid_len == 0) {
3715 aid_len = 11;
3717 if (respond_len == 0) {
3718 respond_len = 2;
3720 if (apdu_len == 0) {
3721 apdu_len = 2;
3724 uint16_t flags = 0;
3725 bool useUIDfromEML = true;
3727 if (uid_len > 0) {
3728 switch (uid_len) {
3729 case 10:
3730 flags |= FLAG_10B_UID_IN_DATA;
3731 break;
3732 case 7:
3733 flags |= FLAG_7B_UID_IN_DATA;
3734 break;
3735 case 4:
3736 flags |= FLAG_4B_UID_IN_DATA;
3737 break;
3738 default:
3739 PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
3740 CLIParserFree(ctx);
3741 return PM3_EINVARG;
3743 PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
3744 useUIDfromEML = false;
3747 if (rats_len > 0) {
3748 flags |= FLAG_RATS_IN_DATA;
3752 CLIParserFree(ctx);
3754 if (tagtype > 12) {
3755 PrintAndLogEx(ERR, "Undefined tag %d", tagtype);
3756 return PM3_EINVARG;
3759 if (useUIDfromEML) {
3760 flags |= FLAG_UID_IN_EMUL;
3763 struct {
3764 uint8_t tagtype;
3765 uint16_t flags;
3766 uint8_t uid[10];
3767 uint8_t rats[20];
3768 uint8_t aid[30];
3769 uint8_t response[100];
3770 uint8_t apdu[100];
3771 int aid_len;
3772 int respond_len;
3773 int apdu_len;
3774 bool enumerate;
3775 } PACKED payload;
3777 payload.tagtype = tagtype;
3778 payload.flags = flags;
3779 payload.enumerate = enumerate;
3781 // Copy data to payload
3782 memcpy(payload.uid, uid, uid_len);
3783 memcpy(payload.rats, rats, rats_len);
3784 memcpy(payload.aid, aid, aid_len);
3785 memcpy(payload.response, response, respond_len);
3786 memcpy(payload.apdu, apdu, apdu_len);
3788 // copy the lengths data to the payload
3789 memcpy(&payload.aid_len, &aid_len, sizeof(aid_len));
3790 memcpy(&payload.respond_len, &respond_len, sizeof(respond_len));
3791 memcpy(&payload.apdu_len, &apdu_len, sizeof(apdu_len));
3793 clearCommandBuffer();
3794 SendCommandNG(CMD_HF_ISO14443A_SIM_AID, (uint8_t *)&payload, sizeof(payload));
3795 PacketResponseNG resp = {0};
3797 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
3798 bool keypress = kbd_enter_pressed();
3799 while (keypress == false) {
3801 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
3802 continue;
3804 if (resp.status != PM3_SUCCESS)
3805 break;
3807 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
3808 break;
3810 keypress = kbd_enter_pressed();
3813 if (keypress) {
3814 if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
3815 // inform device to break the sim loop since client has exited
3816 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
3821 PrintAndLogEx(INFO, "Done!");
3822 PrintAndLogEx(HINT, "Try `" _YELLOW_("trace list -t 14a")"` to view captured tracelog");
3823 PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
3825 return PM3_SUCCESS;
3829 static command_t CommandTable[] = {
3830 {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
3831 {"help", CmdHelp, AlwaysAvailable, "This help"},
3832 {"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"},
3833 {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("Operations") " ---------------------"},
3834 {"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
3835 {"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
3836 {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"},
3837 {"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"},
3838 {"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"},
3839 {"simaid", CmdHF14AAIDSim, IfPm3Iso14443a, "Simulate ISO 14443-a AID Selection"},
3840 {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"},
3841 {"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
3842 {"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"},
3843 {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------- " _CYAN_("APDU") " -------------------------"},
3844 {"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"},
3845 {"apdufind", CmdHf14AFindapdu, IfPm3Iso14443a, "Enumerate APDUs - CLA/INS/P1P2"},
3846 {"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
3847 {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------- " _CYAN_("NDEF") " -------------------------"},
3848 {"ndefformat", CmdHF14ANdefFormat, IfPm3Iso14443a, "Format ISO 14443-A as NFC Type 4 tag"},
3849 {"ndefread", CmdHF14ANdefRead, IfPm3Iso14443a, "Read an NDEF file from ISO 14443-A Type 4 tag"},
3850 {"ndefwrite", CmdHF14ANdefWrite, IfPm3Iso14443a, "Write NDEF records to ISO 14443-A tag"},
3851 {NULL, NULL, NULL, NULL}
3854 static int CmdHelp(const char *Cmd) {
3855 (void)Cmd; // Cmd is not used so far
3856 CmdsHelp(CommandTable);
3857 return PM3_SUCCESS;
3860 int CmdHF14A(const char *Cmd) {
3861 clearCommandBuffer();
3862 return CmdsParse(CommandTable, Cmd);