fix one too small
[RRG-proxmark3.git] / client / src / cmdhf14a.c
blobc3b5936ea6ce82a4d1e4c80e84e4a37919fb975c
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 WaitForResponse(CMD_ACK, &resp);
461 memcpy(card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
463 uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
465 if (select_status == 0) {
466 PrintAndLogEx(ERR, "E->iso14443a card select failed");
467 return PM3_EFAILED;
470 if (select_status == 2) {
471 PrintAndLogEx(ERR, "E->Card doesn't support iso14443-4 mode");
472 return PM3_EFAILED;
475 if (select_status == 3) {
476 PrintAndLogEx(INFO, "E->Card doesn't support standard iso14443-3 anticollision");
477 // identify TOPAZ
478 if (card->atqa[1] == 0x0C && card->atqa[0] == 0x00) {
479 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
480 } else {
481 PrintAndLogEx(SUCCESS, "\tATQA : %02X %02X", card->atqa[1], card->atqa[0]);
483 return PM3_EFAILED;
486 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card->uid, card->uidlen));
487 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card->atqa[1], card->atqa[0]);
488 PrintAndLogEx(SUCCESS, " SAK: %02X [%" PRIu64 "]", card->sak, resp.oldarg[0]);
490 // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
491 if (card->ats_len < 3) {
492 PrintAndLogEx(INFO, "E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len));
493 return PM3_ECARDEXCHANGE;
496 if (card->ats_len == card->ats[0] + 2)
497 PrintAndLogEx(SUCCESS, " ATS: [%d] %s", card->ats[0], sprint_hex(card->ats, card->ats[0]));
498 else
499 PrintAndLogEx(SUCCESS, " ATS: [%d] %s", card->ats_len, sprint_hex(card->ats, card->ats_len));
501 return PM3_SUCCESS;
504 iso14a_polling_parameters_t iso14a_get_polling_parameters(bool use_ecp, bool use_magsafe) {
505 // Extra 100ms give enough time for Apple (ECP) devices to proccess field info and make a decision
507 if (use_ecp && use_magsafe) {
508 iso14a_polling_parameters_t full_polling_parameters = {
509 .frames = { WUPA_FRAME, ECP_FRAME, MAGWUPA1_FRAME, MAGWUPA2_FRAME, MAGWUPA3_FRAME, MAGWUPA4_FRAME },
510 .frame_count = 6,
511 .extra_timeout = 100
513 return full_polling_parameters;
514 } else if (use_ecp) {
515 iso14a_polling_parameters_t ecp_polling_parameters = {
516 .frames = { WUPA_FRAME, ECP_FRAME },
517 .frame_count = 2,
518 .extra_timeout = 100
520 return ecp_polling_parameters;
521 } else if (use_magsafe) {
522 iso14a_polling_parameters_t magsafe_polling_parameters = {
523 .frames = { WUPA_FRAME, MAGWUPA1_FRAME, MAGWUPA2_FRAME, MAGWUPA3_FRAME, MAGWUPA4_FRAME },
524 .frame_count = 5,
525 .extra_timeout = 0
527 return magsafe_polling_parameters;
530 iso14a_polling_parameters_t wupa_polling_parameters = {
531 .frames = { WUPA_FRAME },
532 .frame_count = 1,
533 .extra_timeout = 0,
535 return wupa_polling_parameters;
538 static int CmdHF14AReader(const char *Cmd) {
539 CLIParserContext *ctx;
540 CLIParserInit(&ctx, "hf 14a reader",
541 "Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
542 "hf 14a reader\n"
543 "hf 14a reader -@ -> Continuous mode\n"
544 "hf 14a reader --ecp -> trigger apple enhanced contactless polling\n"
545 "hf 14a reader --mag -> trigger apple magsafe polling\n"
548 void *argtable[] = {
549 arg_param_begin,
550 arg_lit0("k", "keep", "keep the field active after command executed"),
551 arg_lit0("s", "silent", "silent (no messages)"),
552 arg_lit0(NULL, "drop", "just drop the signal field"),
553 arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"),
554 arg_lit0(NULL, "ecp", "Use enhanced contactless polling"),
555 arg_lit0(NULL, "mag", "Use Apple magsafe polling"),
556 arg_lit0("@", NULL, "continuous reader mode"),
557 arg_param_end
559 CLIExecWithReturn(ctx, Cmd, argtable, true);
561 bool disconnectAfter = true;
562 if (arg_get_lit(ctx, 1)) {
563 disconnectAfter = false;
566 bool silent = arg_get_lit(ctx, 2);
568 uint32_t cm = ISO14A_CONNECT;
569 if (arg_get_lit(ctx, 3)) {
570 cm &= ~ISO14A_CONNECT;
573 if (arg_get_lit(ctx, 4)) {
574 cm |= ISO14A_NO_RATS;
577 bool use_ecp = arg_get_lit(ctx, 5);
578 bool use_magsafe = arg_get_lit(ctx, 6);
580 iso14a_polling_parameters_t *polling_parameters = NULL;
581 iso14a_polling_parameters_t parameters = iso14a_get_polling_parameters(use_ecp, use_magsafe);
582 if (use_ecp || use_magsafe) {
583 cm |= ISO14A_USE_CUSTOM_POLLING;
584 polling_parameters = &parameters;
587 bool continuous = arg_get_lit(ctx, 7);
588 CLIParserFree(ctx);
590 if (disconnectAfter == false) {
591 cm |= ISO14A_NO_DISCONNECT;
594 if (continuous) {
595 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
598 int res = PM3_SUCCESS;
599 do {
600 clearCommandBuffer();
602 if ((cm & ISO14A_USE_CUSTOM_POLLING) == ISO14A_USE_CUSTOM_POLLING) {
603 SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, (uint8_t *)polling_parameters, sizeof(iso14a_polling_parameters_t));
604 } else {
605 SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
608 if ((cm & ISO14A_CONNECT) == ISO14A_CONNECT) {
609 PacketResponseNG resp;
610 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
611 DropField();
612 res = PM3_ESOFT;
613 goto plot;
616 iso14a_card_select_t card;
617 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
620 0: couldn't read
621 1: OK, with ATS
622 2: OK, no ATS
623 3: proprietary Anticollision
625 uint64_t select_status = resp.oldarg[0];
627 if (select_status == 0) {
628 DropField();
629 res = PM3_ESOFT;
630 goto plot;
633 if (select_status == 3) {
634 if (!(silent && continuous)) {
635 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
637 // identify TOPAZ
638 if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) {
639 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
640 } else {
641 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
643 PrintAndLogEx(NORMAL, "");
645 DropField();
646 res = PM3_ESOFT;
647 goto plot;
650 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
652 if (!(silent && continuous)) {
653 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
654 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
656 if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
657 if (card.ats_len == card.ats[0] + 2)
658 PrintAndLogEx(SUCCESS, " ATS: " _GREEN_("%s"), sprint_hex(card.ats, card.ats[0]));
659 else {
660 PrintAndLogEx(SUCCESS, " ATS: [%d] " _GREEN_("%s"), card.ats_len, sprint_hex(card.ats, card.ats_len));
663 PrintAndLogEx(NORMAL, "");
665 if ((disconnectAfter == false) && (silent == false)) {
666 PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands");
669 plot:
670 if (continuous) {
671 res = handle_hf_plot(false);
672 if (res != PM3_SUCCESS) {
673 PrintAndLogEx(DEBUG, "plot failed");
677 if (kbd_enter_pressed()) {
678 break;
681 } while (continuous);
683 if (disconnectAfter == false) {
684 if (silent == false) {
685 PrintAndLogEx(INFO, "field is on");
689 if (continuous)
690 return PM3_SUCCESS;
691 else
692 return res;
695 static int CmdHF14AInfo(const char *Cmd) {
696 bool verbose = true;
697 bool do_nack_test = false;
698 bool do_aid_search = false;
700 CLIParserContext *ctx;
701 CLIParserInit(&ctx, "hf 14a info",
702 "This command makes more extensive tests against a ISO14443a tag in order to collect information",
703 "hf 14a info -nsv -> shows full information about the card\n");
705 void *argtable[] = {
706 arg_param_begin,
707 arg_lit0("v", "verbose", "verbose output"),
708 arg_lit0("n", "nacktest", "test for nack bug"),
709 arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
710 arg_param_end
712 CLIExecWithReturn(ctx, Cmd, argtable, true);
714 verbose = arg_get_lit(ctx, 1);
715 do_nack_test = arg_get_lit(ctx, 2);
716 do_aid_search = arg_get_lit(ctx, 3);
718 CLIParserFree(ctx);
720 infoHF14A(verbose, do_nack_test, do_aid_search);
721 return PM3_SUCCESS;
724 // Collect ISO14443 Type A UIDs
725 static int CmdHF14ACUIDs(const char *Cmd) {
726 CLIParserContext *ctx;
727 CLIParserInit(&ctx, "hf 14a cuids",
728 "Collect n>0 ISO14443-a UIDs in one go",
729 "hf 14a cuids -n 5 --> Collect 5 UIDs");
731 void *argtable[] = {
732 arg_param_begin,
733 arg_int0("n", "num", "<dec>", "Number of UIDs to collect"),
734 arg_param_end
736 CLIExecWithReturn(ctx, Cmd, argtable, true);
738 // requested number of UIDs
739 // collect at least 1 (e.g. if no parameter was given)
740 int n = arg_get_int_def(ctx, 1, 1);
742 CLIParserFree(ctx);
744 uint64_t t1 = msclock();
745 PrintAndLogEx(SUCCESS, "collecting %d UIDs", n);
747 // repeat n times
748 for (int i = 0; i < n; i++) {
750 if (kbd_enter_pressed()) {
751 PrintAndLogEx(WARNING, "aborted via keyboard!\n");
752 break;
755 // execute anticollision procedure
756 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
758 PacketResponseNG resp;
759 WaitForResponse(CMD_ACK, &resp);
761 iso14a_card_select_t *card = (iso14a_card_select_t *) resp.data.asBytes;
763 // check if command failed
764 if (resp.oldarg[0] == 0) {
765 PrintAndLogEx(WARNING, "card select failed.");
766 } else {
767 char uid_string[20];
768 for (uint16_t m = 0; m < card->uidlen; m++) {
769 int offset = 2 * m;
770 snprintf(uid_string + offset, sizeof(uid_string) - offset, "%02X", card->uid[m]);
772 PrintAndLogEx(SUCCESS, "%s", uid_string);
775 PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000);
776 return 1;
779 // ## simulate iso14443a tag
780 int CmdHF14ASim(const char *Cmd) {
781 CLIParserContext *ctx;
782 CLIParserInit(&ctx, "hf 14a sim",
783 "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
784 "Use type 7 for Mifare Ultralight EV1, Amiibo (NTAG215 pack 0x8080)",
785 "hf 14a sim -t 1 --uid 11223344 -> MIFARE Classic 1k\n"
786 "hf 14a sim -t 2 -> MIFARE Ultralight\n"
787 "hf 14a sim -t 3 -> MIFARE Desfire\n"
788 "hf 14a sim -t 4 -> ISO/IEC 14443-4\n"
789 "hf 14a sim -t 5 -> MIFARE Tnp3xxx\n"
790 "hf 14a sim -t 6 -> MIFARE Mini\n"
791 "hf 14a sim -t 7 -> MFU EV1 / NTAG 215 Amiibo\n"
792 "hf 14a sim -t 8 -> MIFARE Classic 4k\n"
793 "hf 14a sim -t 9 -> FM11RF005SH Shanghai Metro\n"
794 "hf 14a sim -t 10 -> ST25TA IKEA Rothult\n"
795 "hf 14a sim -t 11 -> Javacard (JCOP)\n"
796 "hf 14a sim -t 12 -> 4K Seos card\n"
799 void *argtable[] = {
800 arg_param_begin,
801 arg_int1("t", "type", "<1-12> ", "Simulation type to use"),
802 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
803 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
804 arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader"),
805 arg_lit0(NULL, "sk", "Fill simulator keys from found keys"),
806 arg_lit0("v", "verbose", "verbose output"),
807 arg_param_end
809 CLIExecWithReturn(ctx, Cmd, argtable, false);
811 int tagtype = arg_get_int_def(ctx, 1, 1);
813 int uid_len = 0;
814 uint8_t uid[10] = {0};
815 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
817 uint16_t flags = 0;
818 bool useUIDfromEML = true;
820 if (uid_len > 0) {
821 switch (uid_len) {
822 case 10:
823 flags |= FLAG_10B_UID_IN_DATA;
824 break;
825 case 7:
826 flags |= FLAG_7B_UID_IN_DATA;
827 break;
828 case 4:
829 flags |= FLAG_4B_UID_IN_DATA;
830 break;
831 default:
832 PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
833 CLIParserFree(ctx);
834 return PM3_EINVARG;
836 PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
837 useUIDfromEML = false;
840 uint8_t exitAfterNReads = arg_get_int_def(ctx, 3, 0);
842 if (arg_get_lit(ctx, 4)) {
843 flags |= FLAG_NR_AR_ATTACK;
846 bool setEmulatorMem = arg_get_lit(ctx, 5);
847 bool verbose = arg_get_lit(ctx, 6);
849 CLIParserFree(ctx);
851 if (tagtype > 12) {
852 PrintAndLogEx(ERR, "Undefined tag %d", tagtype);
853 return PM3_EINVARG;
856 if (useUIDfromEML) {
857 flags |= FLAG_UID_IN_EMUL;
860 struct {
861 uint8_t tagtype;
862 uint16_t flags;
863 uint8_t uid[10];
864 uint8_t exitAfter;
865 } PACKED payload;
867 payload.tagtype = tagtype;
868 payload.flags = flags;
869 payload.exitAfter = exitAfterNReads;
870 memcpy(payload.uid, uid, uid_len);
872 clearCommandBuffer();
873 SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload));
874 PacketResponseNG resp = {0};
876 sector_t *k_sector = NULL;
877 size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR;
879 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort simulation");
880 bool keypress = kbd_enter_pressed();
881 while (keypress == false) {
883 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
884 continue;
886 if (resp.status != PM3_SUCCESS)
887 break;
889 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)
890 break;
892 const nonces_t *data = (nonces_t *)resp.data.asBytes;
893 readerAttack(k_sector, k_sectors_cnt, data[0], setEmulatorMem, verbose);
895 keypress = kbd_enter_pressed();
898 if (keypress) {
899 if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
900 // inform device to break the sim loop since client has exited
901 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
904 if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) {
905 //iceman: readerAttack call frees k_sector , this call is useless.
906 showSectorTable(k_sector, k_sectors_cnt);
910 PrintAndLogEx(INFO, "Done!");
911 return PM3_SUCCESS;
914 int CmdHF14ASniff(const char *Cmd) {
915 CLIParserContext *ctx;
916 CLIParserInit(&ctx, "hf 14a sniff",
917 "Sniff the communication between Hitag reader and tag.\n"
918 "Use `hf 14a list` to view collected data.",
919 " hf 14a sniff -c -r"
921 void *argtable[] = {
922 arg_param_begin,
923 arg_lit0("c", "card", "triggered by first data from card"),
924 arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ, WUP)"),
925 arg_lit0("i", "interactive", "Console will not be returned until sniff finishes or is aborted"),
926 arg_param_end
928 CLIExecWithReturn(ctx, Cmd, argtable, true);
930 uint8_t param = 0;
932 if (arg_get_lit(ctx, 1)) {
933 param |= 0x01;
936 if (arg_get_lit(ctx, 2)) {
937 param |= 0x02;
940 bool interactive = arg_get_lit(ctx, 3);
941 CLIParserFree(ctx);
943 clearCommandBuffer();
944 SendCommandNG(CMD_HF_ISO14443A_SNIFF, (uint8_t *)&param, sizeof(uint8_t));
946 PrintAndLogEx(INFO, "Press " _GREEN_("pm3 button") " to abort sniffing");
948 if (interactive) {
949 PacketResponseNG resp;
950 WaitForResponse(CMD_HF_ISO14443A_SNIFF, &resp);
951 PrintAndLogEx(INFO, "Done!");
952 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14a list")"` to view captured tracelog");
953 PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -h") "` to save tracelog for later analysing");
955 return PM3_SUCCESS;
958 int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode) {
960 uint16_t cmdc = 0;
961 *dataoutlen = 0;
963 if (activateField) {
964 // select with no disconnect and set gs_frame_len
965 int selres = SelectCard14443A_4(false, !silentMode, NULL);
966 gs_frames_num = 0;
967 if (selres != PM3_SUCCESS) {
968 return selres;
972 if (leaveSignalON) {
973 cmdc |= ISO14A_NO_DISCONNECT;
976 uint8_t data[PM3_CMD_DATA_SIZE] = { 0x0a | gs_frames_num, 0x00 };
977 gs_frames_num ^= 1;
979 int min = MIN((PM3_CMD_DATA_SIZE - 2), (datainlen & 0x1FF));
980 memcpy(&data[2], datain, min);
981 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0, data, min + 2);
983 uint8_t *recv;
984 PacketResponseNG resp;
985 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
986 recv = resp.data.asBytes;
987 int iLen = resp.oldarg[0];
989 if (iLen == 0) {
990 if (silentMode == false) {
991 PrintAndLogEx(ERR, "No card response");
993 return PM3_ECARDEXCHANGE;
996 *dataoutlen = iLen - 2;
997 if (*dataoutlen < 0) {
998 *dataoutlen = 0;
1001 if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
1002 if (silentMode == false) {
1003 PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen);
1005 return PM3_ELENGTH;
1008 if (recv[0] != data[0]) {
1009 if (silentMode == false) {
1010 PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", recv[0], data[0]);
1012 return PM3_ELENGTH;
1015 memcpy(dataout, &recv[2], *dataoutlen);
1017 // CRC Check
1018 if (iLen == -1) {
1019 if (silentMode == false) {
1020 PrintAndLogEx(ERR, "ISO 14443A CRC error");
1022 return PM3_ECRC;
1025 } else {
1026 if (silentMode == false) {
1027 PrintAndLogEx(ERR, "Reply timeout.");
1029 return PM3_ETIMEOUT;
1032 return PM3_SUCCESS;
1035 int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters) {
1036 // global vars should be prefixed with g_
1037 gs_frame_len = 0;
1038 gs_frames_num = 0;
1040 if (card) {
1041 memset(card, 0, sizeof(iso14a_card_select_t));
1044 DropField();
1046 // Anticollision + SELECT card
1047 PacketResponseNG resp;
1048 if (polling_parameters != NULL) {
1049 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));
1050 } else {
1051 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
1054 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1055 PrintAndLogEx(WARNING, "Command execute timeout");
1056 return PM3_ETIMEOUT;
1059 // check result
1060 if (resp.oldarg[0] == 0) {
1061 if (verbose) {
1062 PrintAndLogEx(WARNING, "No ISO1443-A Card in field");
1064 return PM3_ECARDEXCHANGE;
1067 if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) {
1068 PrintAndLogEx(WARNING, "Card not in iso14443-4, res=%" PRId64 ".", resp.oldarg[0]);
1069 return PM3_ECARDEXCHANGE;
1072 iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.data.asBytes;
1073 if (card) {
1074 memcpy(card, vcard, sizeof(iso14a_card_select_t));
1077 if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
1078 // get ATS
1079 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
1080 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats));
1081 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1082 PrintAndLogEx(WARNING, "Command execute timeout");
1083 return PM3_ETIMEOUT;
1086 if (resp.oldarg[0] == 0) { // ats_len
1087 if (verbose) {
1088 PrintAndLogEx(FAILED, "Can't get ATS");
1090 return PM3_ECARDEXCHANGE;
1093 // get frame length from ATS in data field
1094 if (resp.oldarg[0] > 1) {
1095 uint8_t fsci = resp.data.asBytes[1] & 0x0f;
1096 if (fsci < ARRAYLEN(atsFSC)) {
1097 gs_frame_len = atsFSC[fsci];
1101 if (card) {
1102 card->ats_len = resp.oldarg[0];
1103 memcpy(card->ats, resp.data.asBytes, card->ats_len);
1105 } else {
1106 // get frame length from ATS in card data structure
1107 if (vcard->ats_len > 1) {
1108 uint8_t fsci = vcard->ats[1] & 0x0f;
1109 if (fsci < ARRAYLEN(atsFSC)) {
1110 gs_frame_len = atsFSC[fsci];
1115 SetISODEPState(ISODEP_NFCA);
1117 if (disconnect) {
1118 DropField();
1121 return PM3_SUCCESS;
1124 int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card) {
1125 return SelectCard14443A_4_WithParameters(disconnect, verbose, card, NULL);
1128 static int CmdExchangeAPDU(bool chainingin, const uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
1129 *chainingout = false;
1131 size_t timeout = 1500;
1132 if (activateField) {
1133 // select with no disconnect and set gs_frame_len
1134 iso14a_card_select_t card;
1135 int selres = SelectCard14443A_4(false, true, &card);
1136 if (selres != PM3_SUCCESS) {
1137 return selres;
1140 // Extract FWI and SFGI from ATS and increase timeout by the indicated values
1141 // for most cards these values are trivially small so will make no practical
1142 // difference but some "cards" like hf_cardhopper overwrite these to their
1143 // maximum values resulting in ~5 seconds each which can cause timeouts if we
1144 // just ignore it
1145 if (((card.ats[1] & 0x20) == 0x20) && card.ats_len > 2) {
1146 // TB is present in ATS
1148 uint8_t tb;
1149 if ((card.ats[1] & 0x10) == 0x10 && card.ats_len > 3) {
1150 // TA is also present, so TB at ats[3]
1151 tb = card.ats[3];
1152 } else {
1153 // TA is not present, so TB is at ats[2]
1154 tb = card.ats[2];
1157 uint8_t fwi = (tb & 0xF0) >> 4;
1158 if (fwi != 0x0F) {
1159 uint32_t fwt = 256 * 16 * (1 << fwi);
1160 timeout += fwt;
1163 uint8_t sfgi = tb & 0x0F;
1164 if (sfgi != 0x0F) {
1165 uint32_t sgft = 256 * 16 * (1 << sfgi);
1166 timeout += sgft;
1171 uint16_t cmdc = 0;
1172 if (chainingin)
1173 cmdc = ISO14A_SEND_CHAINING;
1175 // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
1176 // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
1177 // here length PM3_CMD_DATA_SIZE=512
1178 // timeout must be authomatically set by "get ATS"
1179 if (datain)
1180 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0x1FF), 0, datain, datainlen & 0x1FF);
1181 else
1182 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, 0, 0, NULL, 0);
1184 PacketResponseNG resp;
1186 if (WaitForResponseTimeout(CMD_ACK, &resp, timeout)) {
1187 const uint8_t *recv = resp.data.asBytes;
1188 int iLen = resp.oldarg[0];
1189 uint8_t res = resp.oldarg[1];
1191 int dlen = iLen - 2;
1192 if (dlen < 0)
1193 dlen = 0;
1194 *dataoutlen += dlen;
1196 if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
1197 PrintAndLogEx(DEBUG, "ERR: APDU: Buffer too small(%d), needs %d bytes", *dataoutlen, maxdataoutlen);
1198 return PM3_EAPDU_FAIL;
1201 // I-block ACK
1202 if ((res & 0xF2) == 0xA2) {
1203 *dataoutlen = 0;
1204 *chainingout = true;
1205 return PM3_SUCCESS;
1208 if (!iLen) {
1209 PrintAndLogEx(DEBUG, "ERR: APDU: No APDU response");
1210 return PM3_EAPDU_FAIL;
1213 // check apdu length
1214 if (iLen < 2 && iLen >= 0) {
1215 PrintAndLogEx(DEBUG, "ERR: APDU: Small APDU response, len %d", iLen);
1216 return PM3_EAPDU_FAIL;
1219 // check block TODO
1220 if (iLen == -2) {
1221 PrintAndLogEx(DEBUG, "ERR: APDU: Block type mismatch");
1222 return PM3_EAPDU_FAIL;
1225 memcpy(dataout, recv, dlen);
1227 // chaining
1228 if ((res & 0x10) != 0) {
1229 *chainingout = true;
1232 // CRC Check
1233 if (iLen == -1) {
1234 PrintAndLogEx(DEBUG, "ERR: APDU: ISO 14443A CRC error");
1235 return PM3_EAPDU_FAIL;
1237 } else {
1238 PrintAndLogEx(DEBUG, "ERR: APDU: Reply timeout");
1239 return PM3_EAPDU_FAIL;
1242 return PM3_SUCCESS;
1245 int ExchangeAPDU14a(const uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
1246 *dataoutlen = 0;
1247 bool chaining = false;
1248 int res;
1250 // 3 byte here - 1b framing header, 2b crc16
1251 if (g_apdu_in_framing_enable &&
1252 ((gs_frame_len && (datainlen > gs_frame_len - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) {
1254 int clen = 0;
1256 bool vActivateField = activateField;
1258 do {
1259 int vlen = MIN(gs_frame_len - 3, datainlen - clen);
1260 bool chainBlockNotLast = ((clen + vlen) < datainlen);
1262 *dataoutlen = 0;
1263 res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining);
1264 if (res != PM3_SUCCESS) {
1265 if (leaveSignalON == false)
1266 DropField();
1268 return 200;
1271 // check R-block ACK
1272 // TODO check this one...
1273 if ((*dataoutlen == 0) && (chaining != chainBlockNotLast)) {
1274 if (leaveSignalON == false)
1275 DropField();
1277 return 201;
1280 clen += vlen;
1281 vActivateField = false;
1282 if (*dataoutlen) {
1283 if (clen != datainlen) {
1284 PrintAndLogEx(ERR, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen);
1286 break;
1288 } while (clen < datainlen);
1290 } else {
1291 res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining);
1292 if (res != PM3_SUCCESS) {
1293 if (leaveSignalON == false) {
1294 DropField();
1296 return res;
1300 while (chaining) {
1301 // I-block with chaining
1302 res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining);
1303 if (res != PM3_SUCCESS) {
1304 if (leaveSignalON == false) {
1305 DropField();
1307 return 100;
1311 if (leaveSignalON == false) {
1312 DropField();
1315 return PM3_SUCCESS;
1318 // ISO14443-4. 7. Half-duplex block transmission protocol
1319 static int CmdHF14AAPDU(const char *Cmd) {
1320 CLIParserContext *ctx;
1321 CLIParserInit(&ctx, "hf 14a apdu",
1322 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL).\n"
1323 "Works with all APDU types from ISO 7816-4:2013\n"
1324 "\n"
1325 "note:\n"
1326 " `-m` and `-d` goes hand in hand\n"
1327 " -m <CLA INS P1 P2> -d 325041592E5359532E4444463031\n"
1328 "\n"
1329 " OR\n"
1330 "\n"
1331 " use `-d` with complete APDU data\n"
1332 " -d 00A404000E325041592E5359532E444446303100",
1333 "hf 14a apdu -st -d 00A404000E325041592E5359532E444446303100\n"
1334 "hf 14a apdu -sd -d 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
1335 "hf 14a apdu -sm 00A40400 -d 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
1336 "hf 14a apdu -sm 00A40400 -d 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
1338 void *argtable[] = {
1339 arg_param_begin,
1340 arg_lit0("s", "select", "activate field and select card"),
1341 arg_lit0("k", "keep", "keep signal field ON after receive"),
1342 arg_lit0("t", "tlv", "decode TLV"),
1343 arg_lit0(NULL, "decode", "decode APDU request"),
1344 arg_str0("m", "make", "<hex>", "APDU header, 4 bytes <CLA INS P1 P2>"),
1345 arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
1346 arg_int0("l", "le", "<dec>", "Le APDU parameter if `m` parameter included"),
1347 arg_strx1("d", "data", "<hex>", "full APDU package or data if `m` parameter included"),
1348 arg_param_end
1350 CLIExecWithReturn(ctx, Cmd, argtable, false);
1352 bool activateField = arg_get_lit(ctx, 1);
1353 bool leaveSignalON = arg_get_lit(ctx, 2);
1354 bool decodeTLV = arg_get_lit(ctx, 3);
1355 bool decodeAPDU = arg_get_lit(ctx, 4);
1357 uint8_t header[PM3_CMD_DATA_SIZE];
1358 int headerlen = 0;
1359 CLIGetHexWithReturn(ctx, 5, header, &headerlen);
1361 bool makeAPDU = (headerlen > 0);
1363 if (makeAPDU && headerlen != 4) {
1364 PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen);
1365 CLIParserFree(ctx);
1366 return PM3_EINVARG;
1368 bool extendedAPDU = arg_get_lit(ctx, 6);
1369 int le = arg_get_int_def(ctx, 7, 0);
1371 uint8_t data[PM3_CMD_DATA_SIZE];
1372 int datalen = 0;
1374 if (makeAPDU) {
1375 uint8_t apdudata[PM3_CMD_DATA_SIZE] = {0};
1376 int apdudatalen = 0;
1378 CLIGetHexBLessWithReturn(ctx, 8, apdudata, &apdudatalen, 1 + 2);
1380 APDU_t apdu;
1381 apdu.cla = header[0];
1382 apdu.ins = header[1];
1383 apdu.p1 = header[2];
1384 apdu.p2 = header[3];
1386 apdu.lc = apdudatalen;
1387 apdu.data = apdudata;
1389 apdu.extended_apdu = extendedAPDU;
1390 apdu.le = le;
1392 if (APDUEncode(&apdu, data, &datalen)) {
1393 PrintAndLogEx(ERR, "can't make apdu with provided parameters.");
1394 CLIParserFree(ctx);
1395 return PM3_EINVARG;
1398 } else {
1399 if (extendedAPDU) {
1400 PrintAndLogEx(ERR, "make mode not set but here `e` option.");
1401 CLIParserFree(ctx);
1402 return PM3_EINVARG;
1404 if (le > 0) {
1405 PrintAndLogEx(ERR, "make mode not set but here `l` option.");
1406 CLIParserFree(ctx);
1407 return PM3_EINVARG;
1410 // len = data + PCB(1b) + CRC(2b)
1411 CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2);
1413 CLIParserFree(ctx);
1415 PrintAndLogEx(SUCCESS, _YELLOW_("%s%s%s"),
1416 activateField ? "select card" : "",
1417 leaveSignalON ? ", keep field on" : "",
1418 decodeTLV ? ", TLV" : ""
1420 PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen));
1422 if (decodeAPDU) {
1423 APDU_t apdu;
1425 if (APDUDecode(data, datalen, &apdu) == 0)
1426 APDUPrint(apdu);
1427 else
1428 PrintAndLogEx(WARNING, "can't decode APDU.");
1431 int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, PM3_CMD_DATA_SIZE, &datalen);
1432 if (res != PM3_SUCCESS)
1433 return res;
1435 PrintAndLogEx(SUCCESS, "<<< %s | %s", sprint_hex_inrow(data, datalen), sprint_ascii(data, datalen));
1436 PrintAndLogEx(SUCCESS, "<<< status: %02X %02X - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1]));
1438 // TLV decoder
1439 if (decodeTLV && datalen > 4) {
1440 TLVPrintFromBuffer(data, datalen - 2);
1443 return PM3_SUCCESS;
1446 static int CmdHF14ACmdRaw(const char *Cmd) {
1447 CLIParserContext *ctx;
1448 CLIParserInit(&ctx, "hf 14a raw",
1449 "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
1450 "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
1451 "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
1452 "hf 14a raw --ecp -s -> send ECP before select"
1455 void *argtable[] = {
1456 arg_param_begin,
1457 arg_lit0("a", NULL, "Active signal field ON without select"),
1458 arg_lit0("c", NULL, "Calculate and append CRC"),
1459 arg_lit0("k", NULL, "Keep signal field ON after receive"),
1460 arg_lit0("3", NULL, "ISO14443-3 select only (skip RATS)"),
1461 arg_lit0("r", NULL, "Do not read response"),
1462 arg_lit0("s", NULL, "Active signal field ON with select"),
1463 arg_int0("t", "timeout", "<ms>", "Timeout in milliseconds"),
1464 arg_int0("b", NULL, "<dec>", "Number of bits to send. Useful for send partial byte"),
1465 arg_lit0("v", "verbose", "Verbose output"),
1466 arg_lit0(NULL, "ecp", "Use enhanced contactless polling"),
1467 arg_lit0(NULL, "mag", "Use Apple magsafe polling"),
1468 arg_lit0(NULL, "topaz", "Use Topaz protocol to send command"),
1469 arg_strx1(NULL, NULL, "<hex>", "Raw bytes to send"),
1470 arg_param_end
1472 CLIExecWithReturn(ctx, Cmd, argtable, false);
1474 bool active = arg_get_lit(ctx, 1);
1475 bool crc = arg_get_lit(ctx, 2);
1476 bool keep_field_on = arg_get_lit(ctx, 3);
1477 bool no_rats = arg_get_lit(ctx, 4);
1478 bool reply = (arg_get_lit(ctx, 5) == false);
1479 bool active_select = arg_get_lit(ctx, 6);
1480 uint32_t timeout = (uint32_t)arg_get_int_def(ctx, 7, 0);
1481 uint16_t numbits = (uint16_t)arg_get_int_def(ctx, 8, 0);
1482 bool verbose = arg_get_lit(ctx, 9);
1483 bool use_ecp = arg_get_lit(ctx, 10);
1484 bool use_magsafe = arg_get_lit(ctx, 11);
1485 bool topazmode = arg_get_lit(ctx, 12);
1487 int datalen = 0;
1488 uint8_t data[PM3_CMD_DATA_SIZE_MIX] = {0};
1489 CLIGetHexWithReturn(ctx, 13, data, &datalen);
1490 CLIParserFree(ctx);
1492 bool bTimeout = (timeout) ? true : false;
1494 // ensure we can add 2byte crc to input data
1495 if (datalen >= sizeof(data) + 2) {
1496 if (crc) {
1497 PrintAndLogEx(FAILED, "Buffer is full, we can't add CRC to your data");
1498 return PM3_EINVARG;
1502 if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
1503 uint8_t first, second;
1504 if (topazmode) {
1505 compute_crc(CRC_14443_B, data, datalen, &first, &second);
1506 } else {
1507 compute_crc(CRC_14443_A, data, datalen, &first, &second);
1509 data[datalen++] = first;
1510 data[datalen++] = second;
1513 uint16_t flags = 0;
1514 if (active || active_select) {
1515 flags |= ISO14A_CONNECT;
1516 if (active)
1517 flags |= ISO14A_NO_SELECT;
1520 uint32_t argtimeout = 0;
1521 if (bTimeout) {
1522 #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
1523 flags |= ISO14A_SET_TIMEOUT;
1524 if (timeout > MAX_TIMEOUT) {
1525 timeout = MAX_TIMEOUT;
1526 PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
1528 argtimeout = 13560000 / 1000 / (8 * 16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
1531 if (keep_field_on) {
1532 flags |= ISO14A_NO_DISCONNECT;
1535 if (datalen > 0) {
1536 flags |= ISO14A_RAW;
1539 if (topazmode) {
1540 flags |= ISO14A_TOPAZMODE;
1543 if (no_rats) {
1544 flags |= ISO14A_NO_RATS;
1547 // TODO: allow to use reader command with both data and polling configuration
1548 if (use_ecp || use_magsafe) {
1549 PrintAndLogEx(WARNING, "ECP and Magsafe not supported with this command at this moment. Instead use 'hf 14a reader -sk --ecp/--mag'");
1550 // flags |= ISO14A_USE_MAGSAFE;
1551 // flags |= ISO14A_USE_ECP;
1554 // Max buffer is PM3_CMD_DATA_SIZE_MIX
1555 datalen = (datalen > PM3_CMD_DATA_SIZE_MIX) ? PM3_CMD_DATA_SIZE_MIX : datalen;
1557 clearCommandBuffer();
1558 SendCommandMIX(CMD_HF_ISO14443A_READER, flags, (datalen & 0x1FF) | ((uint32_t)(numbits << 16)), argtimeout, data, datalen);
1560 if (reply) {
1561 int res = 0;
1562 if (active_select)
1563 res = waitCmd(true, timeout, verbose);
1564 if (res == PM3_SUCCESS && datalen > 0)
1565 waitCmd(false, timeout, verbose);
1567 return PM3_SUCCESS;
1570 static int waitCmd(bool i_select, uint32_t timeout, bool verbose) {
1571 PacketResponseNG resp;
1573 if (WaitForResponseTimeout(CMD_ACK, &resp, timeout + 1500)) {
1574 uint16_t len = (resp.oldarg[0] & 0xFFFF);
1575 if (i_select) {
1576 len = (resp.oldarg[1] & 0xFFFF);
1577 if (len) {
1578 if (verbose) {
1579 PrintAndLogEx(SUCCESS, "Card selected. UID[%u]:", len);
1580 } else {
1581 return PM3_SUCCESS;
1584 } else {
1585 PrintAndLogEx(WARNING, "Can't select card.");
1587 } else {
1588 if (verbose) {
1589 PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
1593 if (len == 0) {
1594 return PM3_ESOFT;
1597 uint8_t *data = resp.data.asBytes;
1599 if (i_select == false && len >= 3) {
1600 bool crc = check_crc(CRC_14443_A, data, len);
1602 char s[16];
1603 snprintf(s,
1604 sizeof(s),
1605 (crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
1606 data[len - 2],
1607 data[len - 1]
1610 PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s);
1611 } else {
1612 PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
1615 } else {
1616 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1617 return PM3_ETIMEOUT;
1619 return PM3_SUCCESS;
1622 static int CmdHF14AAntiFuzz(const char *Cmd) {
1624 CLIParserContext *ctx;
1625 CLIParserInit(&ctx, "hf 14a antifuzz",
1626 "Tries to fuzz the ISO14443a anticollision phase",
1627 "hf 14a antifuzz -4\n");
1629 void *argtable[] = {
1630 arg_param_begin,
1631 arg_lit0("4", NULL, "4 byte uid"),
1632 arg_lit0("7", NULL, "7 byte uid"),
1633 arg_lit0(NULL, "10", "10 byte uid"),
1634 arg_param_end
1636 CLIExecWithReturn(ctx, Cmd, argtable, false);
1638 struct {
1639 uint8_t flag;
1640 } PACKED param;
1641 param.flag = FLAG_4B_UID_IN_DATA;
1643 if (arg_get_lit(ctx, 2))
1644 param.flag = FLAG_7B_UID_IN_DATA;
1645 if (arg_get_lit(ctx, 3))
1646 param.flag = FLAG_10B_UID_IN_DATA;
1648 CLIParserFree(ctx);
1649 clearCommandBuffer();
1650 SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t *)&param, sizeof(param));
1651 return PM3_SUCCESS;
1654 static int CmdHF14AChaining(const char *Cmd) {
1656 CLIParserContext *ctx;
1657 CLIParserInit(&ctx, "hf 14a chaining",
1658 "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
1659 "hf 14a chaining -> show chaining enable/disable state\n"
1660 "hf 14a chaining --off -> disable chaining\n"
1663 void *argtable[] = {
1664 arg_param_begin,
1665 arg_lit0("1", "on", "enabled chaining"),
1666 arg_lit0("0", "off", "disable chaining"),
1667 arg_param_end
1669 CLIExecWithReturn(ctx, Cmd, argtable, true);
1671 bool on = arg_get_lit(ctx, 1);
1672 bool off = arg_get_lit(ctx, 2);
1673 CLIParserFree(ctx);
1675 if ((on + off) > 1) {
1676 PrintAndLogEx(INFO, "Select only one option");
1677 return PM3_EINVARG;
1680 if (on)
1681 Set_apdu_in_framing(true);
1683 if (off)
1684 Set_apdu_in_framing(false);
1686 PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", g_apdu_in_framing_enable ? "enabled" : "disabled");
1687 return PM3_SUCCESS;
1690 static void printTag(const char *tag) {
1691 PrintAndLogEx(SUCCESS, " " _YELLOW_("%s"), tag);
1694 int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status) {
1696 int type = MTNONE;
1698 if ((sak & 0x02) != 0x02) {
1699 if ((sak & 0x19) == 0x19) {
1700 type |= MTCLASSIC;
1701 } else if ((sak & 0x40) == 0x40) {
1702 type |= MTISO18092;
1703 } else if ((sak & 0x38) == 0x38) {
1704 type |= MTCLASSIC;
1705 } else if ((sak & 0x18) == 0x18) {
1706 if (select_status == 1) {
1707 type |= MTPLUS;
1708 } else {
1709 type |= MTCLASSIC;
1711 } else if ((sak & 0x09) == 0x09) {
1712 type |= MTMINI;
1713 } else if ((sak & 0x28) == 0x28) {
1714 type |= MTCLASSIC;
1715 } else if ((sak & 0x08) == 0x08) {
1716 if (select_status == 1) {
1717 type |= MTPLUS;
1718 } else {
1719 type |= MTCLASSIC;
1721 } else if ((sak & 0x11) == 0x11) {
1722 type |= MTPLUS;
1723 } else if ((sak & 0x10) == 0x10) {
1724 type |= MTPLUS;
1725 } else if ((sak & 0x01) == 0x01) {
1726 type |= MTCLASSIC;
1727 } else if ((sak & 0x24) == 0x24) {
1728 type |= MTDESFIRE;
1729 } else if ((sak & 0x20) == 0x20) {
1730 if (select_status == 1) {
1731 if ((atqa & 0x0040) == 0x0040) {
1732 if ((atqa & 0x0300) == 0x0300) {
1733 type |= MTDESFIRE;
1734 } else {
1735 type |= MTPLUS;
1737 } else {
1739 if ((atqa & 0x0001) == 0x0001) {
1740 type |= HID_SEOS;
1741 } else {
1742 type |= MTPLUS;
1745 if ((atqa & 0x0004) == 0x0004) {
1746 type |= MTEMV;
1749 type |= (MTDESFIRE | MT424);
1751 } else if ((sak & 0x04) == 0x04) {
1752 type |= MTDESFIRE;
1753 } else {
1754 type |= MTULTRALIGHT;
1756 } else if ((sak & 0x0A) == 0x0A) {
1758 if ((atqa & 0x0003) == 0x0003) {
1759 type |= MTFUDAN;
1760 } else if ((atqa & 0x0005) == 0x0005) {
1761 type |= MTFUDAN;
1763 } else if ((sak & 0x53) == 0x53) {
1764 type |= MTFUDAN;
1767 return type;
1771 // Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
1772 static int detect_nxp_card_print(uint8_t sak, uint16_t atqa, uint64_t select_status) {
1773 int type = MTNONE;
1775 PrintAndLogEx(SUCCESS, "Possible types:");
1777 if ((sak & 0x02) != 0x02) {
1778 if ((sak & 0x19) == 0x19) {
1779 printTag("MIFARE Classic 2K");
1780 type |= MTCLASSIC;
1781 } else if ((sak & 0x40) == 0x40) {
1782 if ((atqa & 0x0110) == 0x0110)
1783 printTag("P2P Support / Proprietary");
1784 else
1785 printTag("P2P Support / Android");
1787 type |= MTISO18092;
1788 } else if ((sak & 0x38) == 0x38) {
1789 printTag("SmartMX with MIFARE Classic 4K");
1790 type |= MTCLASSIC;
1791 } else if ((sak & 0x18) == 0x18) {
1792 if (select_status == 1) {
1793 if ((atqa & 0x0040) == 0x0040) {
1794 printTag("MIFARE Plus EV1 4K CL2 in SL1");
1795 printTag("MIFARE Plus S 4K CL2 in SL1");
1796 printTag("MIFARE Plus X 4K CL2 in SL1");
1797 } else {
1798 printTag("MIFARE Plus EV1 4K in SL1");
1799 printTag("MIFARE Plus S 4K in SL1");
1800 printTag("MIFARE Plus X 4K in SL1");
1803 type |= MTPLUS;
1804 } else {
1805 if ((atqa & 0x0040) == 0x0040) {
1806 printTag("MIFARE Classic 4K CL2");
1807 } else {
1808 printTag("MIFARE Classic 4K");
1811 type |= MTCLASSIC;
1813 } else if ((sak & 0x09) == 0x09) {
1814 if ((atqa & 0x0040) == 0x0040) {
1815 printTag("MIFARE Mini 0.3K CL2");
1816 } else {
1817 printTag("MIFARE Mini 0.3K");
1820 type |= MTMINI;
1821 } else if ((sak & 0x28) == 0x28) {
1822 printTag("SmartMX with MIFARE Classic 1K");
1823 type |= MTCLASSIC;
1824 } else if ((sak & 0x08) == 0x08) {
1825 if (select_status == 1) {
1826 if ((atqa & 0x0040) == 0x0040) {
1827 printTag("MIFARE Plus EV1 2K CL2 in SL1");
1828 printTag("MIFARE Plus S 2K CL2 in SL1");
1829 printTag("MIFARE Plus X 2K CL2 in SL1");
1830 printTag("MIFARE Plus SE 1K CL2");
1831 } else {
1832 printTag("MIFARE Plus EV1 2K in SL1");
1833 printTag("MIFARE Plus S 2K in SL1");
1834 printTag("MIFARE Plus X 2K in SL1");
1835 printTag("MIFARE Plus SE 1K");
1838 type |= MTPLUS;
1839 } else {
1840 if ((atqa & 0x0040) == 0x0040) {
1841 printTag("MIFARE Classic 1K CL2");
1842 } else {
1843 printTag("MIFARE Classic 1K");
1846 type |= MTCLASSIC;
1848 } else if ((sak & 0x11) == 0x11) {
1849 printTag("MIFARE Plus 4K in SL2");
1850 type |= MTPLUS;
1851 } else if ((sak & 0x10) == 0x10) {
1852 printTag("MIFARE Plus 2K in SL2");
1853 type |= MTPLUS;
1854 } else if ((sak & 0x01) == 0x01) {
1855 printTag("TNP3xxx (TagNPlay, Activision Game Appliance)");
1856 type |= MTCLASSIC;
1857 } else if ((sak & 0x24) == 0x24) {
1858 printTag("MIFARE DESFire CL1");
1859 printTag("MIFARE DESFire EV1 CL1");
1860 type |= MTDESFIRE;
1861 } else if ((sak & 0x20) == 0x20) {
1862 if (select_status == 1) {
1863 if ((atqa & 0x0040) == 0x0040) {
1864 if ((atqa & 0x0300) == 0x0300) {
1865 printTag("MIFARE DESFire CL2");
1866 printTag("MIFARE DESFire EV1 256B/2K/4K/8K CL2");
1867 printTag("MIFARE DESFire EV2 2K/4K/8K/16K/32K");
1868 printTag("MIFARE DESFire EV3 2K/4K/8K");
1869 printTag("MIFARE DESFire Light 640B");
1870 type |= MTDESFIRE;
1871 } else {
1872 printTag("MIFARE Plus EV1 2K/4K CL2 in SL3");
1873 printTag("MIFARE Plus S 2K/4K CL2 in SL3");
1874 printTag("MIFARE Plus X 2K/4K CL2 in SL3");
1875 printTag("MIFARE Plus SE 1K CL2");
1876 type |= MTPLUS;
1878 } else {
1880 if ((atqa & 0x0001) == 0x0001) {
1881 printTag("HID SEOS (smartmx / javacard)");
1882 type |= HID_SEOS;
1883 } else {
1884 printTag("MIFARE Plus EV1 2K/4K in SL3");
1885 printTag("MIFARE Plus S 2K/4K in SL3");
1886 printTag("MIFARE Plus X 2K/4K in SL3");
1887 printTag("MIFARE Plus SE 1K");
1888 type |= MTPLUS;
1891 if ((atqa & 0x0004) == 0x0004) {
1892 printTag("EMV");
1893 type |= MTEMV;
1897 printTag("NTAG 4xx");
1898 type |= (MTDESFIRE | MT424);
1900 } else if ((sak & 0x04) == 0x04) {
1901 printTag("Any MIFARE CL1");
1902 type |= MTDESFIRE;
1903 } else {
1904 printTag("MIFARE Ultralight");
1905 printTag("MIFARE Ultralight C");
1906 printTag("MIFARE Ultralight EV1");
1907 printTag("MIFARE Ultralight Nano");
1908 printTag("MIFARE Ultralight AES");
1909 printTag("MIFARE Hospitality");
1910 printTag("NTAG 2xx");
1911 type |= MTULTRALIGHT;
1913 } else if ((sak & 0x0A) == 0x0A) {
1915 if ((atqa & 0x0003) == 0x0003) {
1916 // Uses Shanghai algo
1917 printTag("FM11RF005SH (FUDAN Shanghai Metro)");
1918 type |= MTFUDAN;
1919 } else if ((atqa & 0x0005) == 0x0005) {
1920 printTag("FM11RF005M (FUDAN ISO14443A w Crypto-1 algo)");
1921 type |= MTFUDAN;
1923 } else if ((sak & 0x53) == 0x53) {
1924 printTag("FM11RF08SH (FUDAN)");
1925 type |= MTFUDAN;
1928 if (type == MTNONE) {
1929 PrintAndLogEx(WARNING, " failed to fingerprint");
1931 return type;
1934 typedef struct {
1935 uint8_t uid0;
1936 uint8_t uid1;
1937 const char *desc;
1938 } uid_label_name_t;
1940 static const uid_label_name_t uid_label_map[] = {
1941 // UID0, UID1, TEXT
1942 {0x02, 0x84, "M24SR64-Y"},
1943 {0x02, 0xA3, "25TA02KB-P"},
1944 {0x02, 0xC4, "25TA64K"},
1945 {0x02, 0xE3, "25TA02KB"},
1946 {0x02, 0xE4, "25TA512B"},
1947 {0x02, 0xF3, "25TA02KB-D"},
1948 {0x11, 0x22, "NTAG21x Modifiable"},
1949 {0x00, 0x00, "None"}
1952 static void getTagLabel(uint8_t uid0, uint8_t uid1) {
1953 int i = 0;
1954 while (uid_label_map[i].uid0 != 0x00) {
1955 if ((uid_label_map[i].uid0 == uid0) && (uid_label_map[i].uid1 == uid1)) {
1956 PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uid_label_map[i].desc);
1957 return;
1959 i += 1;
1963 static void get_compact_tlv(uint8_t *d, uint8_t n) {
1964 d++;
1965 n--;
1967 while (n > 0) {
1968 uint8_t tag = NIBBLE_HIGH(d[0]);
1969 uint8_t len = NIBBLE_LOW(d[0]);
1971 switch (tag) {
1972 case 1:
1973 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Country code in (ISO 3166-1)", tag, len, sprint_hex_inrow(d + 1, len));
1974 // iso3166 script in cmdlffdb.c is buggy, Ã…land, Australia not showing. getline issues
1975 break;
1976 case 2:
1977 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Issuer identification number (ISO 7812-1)", tag, len, sprint_hex_inrow(d + 1, len));
1978 break;
1979 case 3:
1980 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Card service data byte", tag, len, sprint_hex_inrow(d + 1, len));
1981 PrintAndLogEx(INFO, " %c....... Application selection: by full DF name", (d[1] & 0x80) ? '1' : '0');
1982 PrintAndLogEx(INFO, " .%c...... Application selection: by partial DF name", (d[1] & 0x40) ? '1' : '0');
1983 PrintAndLogEx(INFO, " ..%c..... BER-TLV data objects available in EF.DIR", (d[1] & 0x20) ? '1' : '0');
1984 PrintAndLogEx(INFO, " ...%c.... BER-TLV data objects available in EF.ATR", (d[1] & 0x10) ? '1' : '0');
1985 PrintAndLogEx(INFO, " ....%c... EF.DIR and EF.ATR access services: by READ BINARY command", (d[1] & 0x08) ? '1' : '0');
1986 PrintAndLogEx(INFO, " .....%c.. EF.DIR and EF.ATR access services: by GET DATA command", (d[1] & 0x04) ? '1' : '0');
1987 PrintAndLogEx(INFO, " ......%c. EF.DIR and EF.ATR access services: by GET RECORD(s) command", (d[1] & 0x02) ? '1' : '0');
1988 PrintAndLogEx(INFO, " .......%c EF.DIR and EF.ATR access services: RFU", (d[1] & 0x01) ? '1' : '0');
1989 break;
1990 case 4:
1991 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Initial access data", tag, len, sprint_hex_inrow(d + 1, len));
1992 break;
1993 case 5:
1994 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Card issuer data", tag, len, sprint_hex_inrow(d + 1, len));
1995 break;
1996 case 6:
1997 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Pre-issuing data", tag, len, sprint_hex_inrow(d + 1, len));
1998 break;
1999 case 7:
2000 PrintAndLogEx(INFO, " %1x%1x " _YELLOW_("%s") " Card capabilities", tag, len, sprint_hex_inrow(d + 1, len));
2002 PrintAndLogEx(INFO, " " _YELLOW_("%02X") " - Selection methods", d[1]);
2003 PrintAndLogEx(INFO, " %c....... DF selection by full DF name", (d[1] & 0x80) ? '1' : '0');
2004 PrintAndLogEx(INFO, " .%c...... DF selection by partial DF name", (d[1] & 0x40) ? '1' : '0');
2005 PrintAndLogEx(INFO, " ..%c..... DF selection by path", (d[1] & 0x20) ? '1' : '0');
2006 PrintAndLogEx(INFO, " ...%c.... DF selection by file identifier", (d[1] & 0x10) ? '1' : '0');
2007 PrintAndLogEx(INFO, " ....%c... Implicit DF selection", (d[1] & 0x08) ? '1' : '0');
2008 PrintAndLogEx(INFO, " .....%c.. Short EF identifier supported", (d[1] & 0x04) ? '1' : '0');
2009 PrintAndLogEx(INFO, " ......%c. Record number supported", (d[1] & 0x02) ? '1' : '0');
2010 PrintAndLogEx(INFO, " .......%c Record identifier supported", (d[1] & 0x01) ? '1' : '0');
2012 if (len > 1) {
2013 PrintAndLogEx(INFO, " " _YELLOW_("%02X") " - Data coding byte", d[2]);
2015 if (len > 2) {
2016 PrintAndLogEx(INFO, " " _YELLOW_("%02X") " - Command chaining, length fields and logical channels", d[3]);
2018 break;
2019 case 8:
2020 PrintAndLogEx(INFO, " %1x%1x ... " _YELLOW_("%s") " Status indicator", tag, len, sprint_hex_inrow(d + 1, len));
2021 break;
2022 case 0xE:
2023 PrintAndLogEx(INFO, " %1x%1x ... " _YELLOW_("%s") " Application identifier", tag, len, sprint_hex_inrow(d + 1, len));
2024 break;
2027 if (len > n)
2028 break;
2030 n -= (1 + len);
2031 d += (1 + len);
2035 int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
2037 uint8_t dbg_curr = DBG_NONE;
2038 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
2039 return PM3_EFAILED;
2042 clearCommandBuffer();
2043 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
2044 PacketResponseNG resp;
2045 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
2046 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
2047 DropField();
2048 return 0;
2051 iso14a_card_select_t card;
2052 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
2055 0: couldn't read
2056 1: OK, with ATS
2057 2: OK, no ATS
2058 3: proprietary Anticollision
2060 uint64_t select_status = resp.oldarg[0];
2062 if (select_status == 0) {
2063 PrintAndLogEx(DEBUG, "iso14443a card select failed");
2064 DropField();
2065 return select_status;
2068 PrintAndLogEx(NORMAL, "");
2070 if (select_status == 3) {
2071 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
2073 if (verbose) {
2074 PrintAndLogEx(SUCCESS, "ATQA: %02X %02X", card.atqa[1], card.atqa[0]);
2077 // identify TOPAZ
2078 if (card.atqa[1] == 0x0C && card.atqa[0] == 0x00) {
2079 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf topaz info`"));
2082 DropField();
2083 return select_status;
2086 if (verbose) {
2087 PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------");
2090 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s") " %s", sprint_hex(card.uid, card.uidlen), get_uid_type(&card));
2091 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
2092 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
2094 bool isMifareMini = false;
2095 bool isMifareClassic = true;
2096 bool isMifareDESFire = false;
2097 bool isMifarePlus = false;
2098 bool isMifareUltralight = false;
2099 bool isST = false;
2100 bool isEMV = false;
2101 bool isFUDAN = false;
2102 bool isISO18092 = false;
2103 bool isNTAG424 = false;
2104 bool isSEOS = false;
2105 int nxptype = MTNONE;
2107 if (card.uidlen <= 4) {
2108 nxptype = detect_nxp_card_print(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
2110 isMifareMini = ((nxptype & MTMINI) == MTMINI);
2111 isMifareClassic = ((nxptype & MTCLASSIC) == MTCLASSIC);
2112 isMifareDESFire = ((nxptype & MTDESFIRE) == MTDESFIRE);
2113 isMifarePlus = ((nxptype & MTPLUS) == MTPLUS);
2114 isMifareUltralight = ((nxptype & MTULTRALIGHT) == MTULTRALIGHT);
2115 isNTAG424 = ((nxptype & MT424) == MT424);
2116 isFUDAN = ((nxptype & MTFUDAN) == MTFUDAN);
2117 isEMV = ((nxptype & MTEMV) == MTEMV);
2118 isISO18092 = ((nxptype & MTISO18092) == MTISO18092);
2119 isSEOS = ((nxptype & HID_SEOS) == HID_SEOS);
2121 // generic catch, we assume MIFARE Classic for all unknown ISO14443a tags
2122 isMifareClassic |= ((nxptype & MTOTHER) == MTOTHER);
2124 } else {
2126 // Double & triple sized UID, can be mapped to a manufacturer.
2127 PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0]));
2129 switch (card.uid[0]) {
2130 case 0x02: // ST
2131 isST = true;
2132 isMifareClassic = false;
2133 break;
2134 case 0x04: // NXP
2135 nxptype = detect_nxp_card_print(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
2137 isMifareMini = ((nxptype & MTMINI) == MTMINI);
2138 isMifareClassic = ((nxptype & MTCLASSIC) == MTCLASSIC);
2139 isMifareDESFire = ((nxptype & MTDESFIRE) == MTDESFIRE);
2140 isMifarePlus = ((nxptype & MTPLUS) == MTPLUS);
2141 isMifareUltralight = ((nxptype & MTULTRALIGHT) == MTULTRALIGHT);
2142 isNTAG424 = ((nxptype & MT424) == MT424);
2144 if ((nxptype & MTOTHER) == MTOTHER)
2145 isMifareClassic = true;
2147 if ((nxptype & MTFUDAN) == MTFUDAN)
2148 isFUDAN = true;
2150 if ((nxptype & MTEMV) == MTEMV)
2151 isEMV = true;
2153 break;
2154 case 0x05: // Infineon
2155 if ((card.uid[1] & 0xF0) == 0x10) {
2156 printTag("my-d(tm) command set SLE 66R04/16/32P, SLE 66R04/16/32S");
2157 } else if ((card.uid[1] & 0xF0) == 0x20) {
2158 printTag("my-d(tm) command set SLE 66R01/16/32P (Type 2 Tag)");
2159 } else if ((card.uid[1] & 0xF0) == 0x30) {
2160 printTag("my-d(tm) move lean SLE 66R01P/66R01PN");
2161 } else if ((card.uid[1] & 0xF0) == 0x70) {
2162 printTag("my-d(tm) move lean SLE 66R01L");
2164 isMifareUltralight = true;
2165 isMifareClassic = false;
2167 if (card.sak == 0x88) {
2168 printTag("Infineon MIFARE CLASSIC 1K");
2169 isMifareUltralight = false;
2170 isMifareClassic = true;
2172 getTagLabel(card.uid[0], card.uid[1]);
2173 break;
2174 case 0x46:
2175 if (memcmp(card.uid, "FSTN10m", 7) == 0) {
2176 isMifareClassic = false;
2177 printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
2179 break;
2180 case 0x57:
2181 if (memcmp(card.uid, "WSDZ10m", 7) == 0) {
2182 isMifareClassic = false;
2183 printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
2185 break;
2186 default:
2187 getTagLabel(card.uid[0], card.uid[1]);
2188 switch (card.sak) {
2189 case 0x00: {
2190 isMifareClassic = false;
2192 // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc)
2193 DropField();
2195 uint64_t tagT = GetHF14AMfU_Type();
2196 if (tagT != MFU_TT_UL_ERROR) {
2197 ul_print_type(tagT, 0);
2198 isMifareUltralight = true;
2199 printTag("MIFARE Ultralight/C/NTAG Compatible");
2200 } else {
2201 printTag("Possible AZTEK (iso14443a compliant)");
2204 // reconnect for further tests
2205 clearCommandBuffer();
2206 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
2207 WaitForResponse(CMD_ACK, &resp);
2209 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
2211 select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
2213 if (select_status == 0) {
2214 DropField();
2215 return select_status;
2217 break;
2219 case 0x0A: {
2220 if (card.atqa[0] == 0x03) {
2221 // Uses Shanghai algo
2222 printTag("FM11RF005SH (FUDAN Shanghai Metro)");
2224 } else if (card.atqa[0] == 0x05) {
2225 // Uses MIFARE Crypto-1 algo
2226 printTag("FM11RF005M (FUDAN ISO14443A w Crypto-1 algo)");
2228 break;
2230 case 0x20: {
2231 printTag("JCOP 31/41");
2232 break;
2234 case 0x28: {
2235 printTag("JCOP31 or JCOP41 v2.3.1");
2236 break;
2238 case 0x38: {
2239 printTag("Nokia 6212 or 6131");
2240 break;
2242 case 0x53: {
2243 printTag("FM11RF08SH (FUDAN)");
2244 break;
2246 case 0x98: {
2247 printTag("Gemplus MPCOS");
2248 break;
2250 default: {
2251 break;
2254 break;
2258 // try to request ATS even if tag claims not to support it
2259 if (select_status == 2) {
2260 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
2261 clearCommandBuffer();
2262 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats));
2263 WaitForResponse(CMD_ACK, &resp);
2265 memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]);
2266 card.ats_len = resp.oldarg[0]; // note: ats_len includes CRC Bytes
2267 if (card.ats_len > 3)
2268 select_status = 1;
2271 if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
2273 PrintAndLogEx(INFO, "-------------------------- " _CYAN_("ATS") " --------------------------");
2274 bool ta1 = 0, tb1 = 0, tc1 = 0;
2276 if (select_status == 2) {
2277 PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--");
2280 bool bad_ats = false;
2281 if (card.ats[0] != card.ats_len - 2) {
2282 PrintAndLogEx(WARNING, _RED_("ATS may be corrupted."));
2283 PrintAndLogEx(INFO, "Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
2284 bad_ats = true;
2287 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]);
2288 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]);
2290 if (bad_ats == false) {
2292 if ((card.ats[0] > 1) && (card.ats_len > 3)) { // there is a format byte (T0)
2293 ta1 = (card.ats[1] & 0x10) == 0x10;
2294 tb1 = (card.ats[1] & 0x20) == 0x20;
2295 tc1 = (card.ats[1] & 0x40) == 0x40;
2296 int16_t fsci = card.ats[1] & 0x0f;
2298 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
2299 "TC1 is%s present, FSCI is %d (FSC = %d)",
2300 card.ats[1],
2301 (ta1 ? "" : _RED_(" NOT")),
2302 (tb1 ? "" : _RED_(" NOT")),
2303 (tc1 ? "" : _RED_(" NOT")),
2304 fsci,
2305 fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1
2308 int pos = 2;
2309 if (ta1 && (card.ats_len > pos + 2)) {
2310 char dr[16], ds[16];
2311 dr[0] = ds[0] = '\0';
2312 if (card.ats[pos] & 0x10) strcat(ds, "2, ");
2313 if (card.ats[pos] & 0x20) strcat(ds, "4, ");
2314 if (card.ats[pos] & 0x40) strcat(ds, "8, ");
2315 if (card.ats[pos] & 0x01) strcat(dr, "2, ");
2316 if (card.ats[pos] & 0x02) strcat(dr, "4, ");
2317 if (card.ats[pos] & 0x04) strcat(dr, "8, ");
2318 if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
2319 if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
2320 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
2321 "DR: [%s], DS: [%s]",
2322 card.ats[pos],
2323 ((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""),
2328 pos++;
2331 if (tb1 && (card.ats_len > pos + 2)) {
2332 uint32_t sfgi = card.ats[pos] & 0x0F;
2333 uint32_t fwi = card.ats[pos] >> 4;
2335 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
2336 card.ats[pos],
2337 (sfgi),
2338 sfgi ? "" : "(not needed) ",
2339 sfgi ? (1 << 12) << sfgi : 0,
2340 fwi,
2341 (1 << 12) << fwi
2343 pos++;
2346 if (tc1 && (card.ats_len > pos + 2)) {
2347 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
2348 card.ats[pos],
2349 (card.ats[pos] & 0x01) ? "" : _RED_(" NOT"),
2350 (card.ats[pos] & 0x02) ? "" : _RED_(" NOT")
2352 pos++;
2355 // ATS - Historial bytes and identify based on it
2356 if ((card.ats[0] > pos) && (card.ats_len >= card.ats[0] + 2)) {
2357 char tip[60];
2358 tip[0] = '\0';
2359 if (card.ats[0] - pos >= 7) {
2361 snprintf(tip, sizeof(tip), " ");
2363 if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
2365 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2366 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
2368 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2370 if ((card.atqa[0] & 0x02) == 0x02) {
2371 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
2372 } else if ((card.atqa[0] & 0x04) == 0x04) {
2373 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
2376 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
2377 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
2379 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
2380 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
2383 } else { //SAK B4,5,6
2385 if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
2387 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2388 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
2389 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2390 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
2391 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
2392 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
2393 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
2394 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
2396 } else {
2397 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
2398 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
2399 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
2400 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
2406 uint8_t calen = card.ats[0] - pos;
2407 PrintAndLogEx(NORMAL, "");
2408 PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------");
2410 if (card.ats[pos] == 0xC1) {
2411 PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip);
2412 PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type");
2413 PrintAndLogEx(SUCCESS, " %02X.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]);
2414 switch (card.ats[pos + 2] & 0xf0) {
2415 case 0x10:
2416 PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire");
2417 isMifareDESFire = true;
2418 isMifareClassic = false;
2419 isMifarePlus = false;
2420 break;
2421 case 0x20:
2422 PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus");
2423 isMifarePlus = true;
2424 isMifareDESFire = false;
2425 isMifareClassic = false;
2426 break;
2428 switch (card.ats[pos + 2] & 0x0f) {
2429 case 0x00:
2430 PrintAndLogEx(SUCCESS, " x0............... < 1 kByte");
2431 break;
2432 case 0x01:
2433 PrintAndLogEx(SUCCESS, " x1............... 1 kByte");
2434 break;
2435 case 0x02:
2436 PrintAndLogEx(SUCCESS, " x2............... 2 kByte");
2437 break;
2438 case 0x03:
2439 PrintAndLogEx(SUCCESS, " x3............... 4 kByte");
2440 break;
2441 case 0x04:
2442 PrintAndLogEx(SUCCESS, " x4............... 8 kByte");
2443 break;
2445 switch (card.ats[pos + 3] & 0xf0) {
2446 case 0x00:
2447 PrintAndLogEx(SUCCESS, " 0x............ Engineering sample");
2448 break;
2449 case 0x20:
2450 PrintAndLogEx(SUCCESS, " 2x............ Released");
2451 break;
2453 switch (card.ats[pos + 3] & 0x0f) {
2454 case 0x00:
2455 PrintAndLogEx(SUCCESS, " x0............ Generation 1");
2456 break;
2457 case 0x01:
2458 PrintAndLogEx(SUCCESS, " x1............ Generation 2");
2459 break;
2460 case 0x02:
2461 PrintAndLogEx(SUCCESS, " x2............ Generation 3");
2462 break;
2464 switch (card.ats[pos + 4] & 0x0f) {
2465 case 0x00:
2466 PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported");
2467 break;
2468 case 0x01:
2469 PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported");
2470 break;
2471 case 0x0E:
2472 PrintAndLogEx(SUCCESS, " xE......... no VCS command supported");
2473 break;
2475 } else {
2477 if (card.ats[pos] == 0x80 || card.ats[pos] == 0x00) {
2478 PrintAndLogEx(SUCCESS, "%s (compact TLV data object)", sprint_hex_inrow(&card.ats[pos], calen));
2479 get_compact_tlv(card.ats + pos, calen);
2480 } else {
2481 PrintAndLogEx(SUCCESS, "%s - %s"
2482 , sprint_hex_inrow(card.ats + pos, calen)
2483 , sprint_ascii(card.ats + pos, calen)
2487 PrintAndLogEx(NORMAL, "");
2493 if (do_aid_search) {
2495 PrintAndLogEx(INFO, "-------------------- " _CYAN_("AID Search") " --------------------");
2497 json_t *root = AIDSearchInit(verbose);
2498 if (root != NULL) {
2499 bool found = false;
2500 bool ActivateField = true;
2501 for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) {
2503 if (kbd_enter_pressed()) {
2504 break;
2507 json_t *data = AIDSearchGetElm(root, elmindx);
2508 uint8_t vaid[200] = {0};
2509 int vaidlen = 0;
2510 if (!AIDGetFromElm(data, vaid, sizeof(vaid), &vaidlen) || !vaidlen)
2511 continue;
2513 uint16_t sw = 0;
2514 uint8_t result[1024] = {0};
2515 size_t resultlen = 0;
2516 int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, vaid, vaidlen, result, sizeof(result), &resultlen, &sw);
2517 ActivateField = false;
2518 if (res)
2519 continue;
2521 uint8_t dfname[200] = {0};
2522 size_t dfnamelen = 0;
2523 if (resultlen > 3) {
2524 struct tlvdb *tlv = tlvdb_parse_multi(result, resultlen);
2525 if (tlv) {
2526 // 0x84 Dedicated File (DF) Name
2527 const struct tlv *dfnametlv = tlvdb_get_tlv(tlvdb_find_full(tlv, 0x84));
2528 if (dfnametlv) {
2529 dfnamelen = dfnametlv->len;
2530 memcpy(dfname, dfnametlv->value, dfnamelen);
2532 tlvdb_free(tlv);
2536 if (sw == ISO7816_OK || sw == ISO7816_INVALID_DF || sw == ISO7816_FILE_TERMINATED) {
2537 if (sw == ISO7816_OK) {
2538 if (verbose) PrintAndLogEx(SUCCESS, "Application ( " _GREEN_("ok") " )");
2539 } else {
2540 if (verbose) PrintAndLogEx(WARNING, "Application ( " _RED_("blocked") " )");
2543 PrintAIDDescriptionBuf(root, vaid, vaidlen, verbose);
2545 if (dfnamelen) {
2546 if (dfnamelen == vaidlen) {
2547 if (memcmp(dfname, vaid, vaidlen) == 0) {
2548 if (verbose) PrintAndLogEx(INFO, "(DF) Name found and equal to AID");
2549 } else {
2550 PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
2551 PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
2553 } else {
2554 PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
2555 PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
2557 } else {
2558 if (verbose) PrintAndLogEx(INFO, "(DF) Name not found");
2561 if (verbose) PrintAndLogEx(SUCCESS, "----------------------------------------------------");
2562 found = true;
2563 isEMV = true;
2567 DropField();
2568 if (verbose == false && found)
2569 PrintAndLogEx(INFO, "----------------------------------------------------");
2573 } else {
2575 if (isISO18092) {
2576 PrintAndLogEx(INFO, "proprietary iso18092 card found");
2577 } else {
2579 PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
2580 if ((card.sak & 0x20) == 0x20) {
2581 PrintAndLogEx(INFO, "--> SAK incorrectly claims that card supports RATS <--");
2585 if (select_status == 1) {
2586 select_status = 2;
2590 if (setDeviceDebugLevel(verbose ? DBG_INFO : DBG_NONE, false) != PM3_SUCCESS) {
2591 return PM3_EFAILED;
2594 PrintAndLogEx(INFO, "");
2596 uint16_t isMagic = 0;
2598 if (isMifareClassic || isMifareMini) {
2599 isMagic = detect_mf_magic(true, MF_KEY_B, 0xFFFFFFFFFFFF);
2602 if (isMifareUltralight) {
2603 isMagic = detect_mf_magic(false, MF_KEY_A, 0);
2606 if (isMifareClassic || isMifareMini) {
2607 int res = detect_classic_static_nonce();
2608 if (res == NONCE_STATIC) {
2609 PrintAndLogEx(SUCCESS, "Static nonce......... " _YELLOW_("yes"));
2612 if (res == NONCE_FAIL && verbose) {
2613 PrintAndLogEx(SUCCESS, "Static nonce......... " _RED_("read failed"));
2616 if (res == NONCE_NORMAL) {
2618 // not static
2619 res = detect_classic_prng();
2620 if (res == 1) {
2621 PrintAndLogEx(SUCCESS, "Prng detection....... " _GREEN_("weak"));
2622 } else if (res == 0) {
2623 PrintAndLogEx(SUCCESS, "Prng detection....... " _YELLOW_("hard"));
2624 } else {
2625 PrintAndLogEx(FAILED, "Prng detection........ " _RED_("fail"));
2628 if (do_nack_test) {
2629 detect_classic_nackbug(false);
2633 uint8_t signature[32] = {0};
2634 res = read_mfc_ev1_signature(signature);
2635 if (res == PM3_SUCCESS) {
2636 mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
2640 if (setDeviceDebugLevel(dbg_curr, false) != PM3_SUCCESS) {
2641 return PM3_EFAILED;
2644 PrintAndLogEx(NORMAL, "");
2645 if (isMifareUltralight) {
2647 if (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) {
2648 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands");
2651 if ((isMagic & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
2652 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mfu *") "` magic commands");
2655 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfu info") "`");
2658 if (isMifarePlus && (isMagic == MAGIC_FLAG_NONE)) {
2659 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfp info") "`");
2662 if (isMifareDESFire && (isMagic == MAGIC_FLAG_NONE) && isEMV == false) {
2663 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf mfdes info") "`");
2666 if (isST) {
2667 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf st info") "`");
2670 if (isEMV) {
2671 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("emv reader") "`");
2674 if (isSEOS) {
2675 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf seos info") "`");
2678 if (isFUDAN) {
2679 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf fudan dump") "`");
2681 PrintAndLogEx(HINT, " hf 14a raw -a -b 7 -k 26");
2682 PrintAndLogEx(HINT, " hf 14a raw -k -c 3000");
2683 PrintAndLogEx(HINT, " hf 14a raw -k -c 3001");
2684 PrintAndLogEx(HINT, " hf 14a raw -k -c 3002");
2685 PrintAndLogEx(HINT, " hf 14a raw -k -c 3003");
2686 PrintAndLogEx(HINT, " hf 14a raw -k -c 3004");
2687 PrintAndLogEx(HINT, " hf 14a raw -k -c 3005");
2688 PrintAndLogEx(HINT, " hf 14a raw -k -c 3006");
2689 PrintAndLogEx(HINT, " hf 14a raw -c 3007");
2693 if (isNTAG424) {
2694 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("hf ntag424 info") "`");
2697 if (isMifareClassic || isMifareMini) {
2698 if (((isMagic & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) || ((isMagic & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B)) {
2699 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf c*") "` magic commands");
2701 // if GEN4 GDM in Gen1a more, hint about it
2702 if ((isMagic & MAGIC_FLAG_GDM_WUP_40) == MAGIC_FLAG_GDM_WUP_40) {
2703 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf gdm* --gen1a") "` magic commands");
2707 if ((isMagic & MAGIC_FLAG_GEN_3) == MAGIC_FLAG_GEN_3) {
2708 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf gen3*") "` magic commands");
2711 if ((isMagic & MAGIC_FLAG_GEN_4GTU) == MAGIC_FLAG_GEN_4GTU) {
2712 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf g*") "` magic commands");
2715 if ((isMagic & MAGIC_FLAG_GDM_AUTH) == MAGIC_FLAG_GDM_AUTH) {
2716 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf gdm*") "` magic commands");
2719 if ((isMagic & MAGIC_FLAG_GEN_2) == MAGIC_FLAG_GEN_2) {
2720 PrintAndLogEx(HINT, "Hint: use `" _YELLOW_("hf mf") "` commands");
2721 } else {
2722 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands");
2727 PrintAndLogEx(NORMAL, "");
2728 DropField();
2729 return select_status;
2732 int infoHF14A4Applications(bool verbose) {
2733 bool cardFound[ARRAYLEN(hintAIDList)] = {0};
2734 bool ActivateField = true;
2735 int found = 0;
2736 for (int i = 0; i < ARRAYLEN(hintAIDList); i++) {
2737 uint16_t sw = 0;
2738 uint8_t result[1024] = {0};
2739 size_t resultlen = 0;
2740 int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, (uint8_t *)hintAIDList[i].aid, hintAIDList[i].aid_length, result, sizeof(result), &resultlen, &sw);
2741 ActivateField = false;
2742 if (res)
2743 break;
2745 if (sw == ISO7816_OK || sw == ISO7816_INVALID_DF || sw == ISO7816_FILE_TERMINATED) {
2746 if (!found) {
2747 if (verbose)
2748 PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------");
2750 found++;
2752 if (sw == ISO7816_OK) {
2753 if (verbose)
2754 PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc);
2755 cardFound[i] = true;
2756 } else {
2757 if (verbose)
2758 PrintAndLogEx(WARNING, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList[i].desc);
2763 if (found) {
2764 if (verbose) {
2765 PrintAndLogEx(INFO, "---------------------------------------------------");
2768 if (found >= ARRAYLEN(hintAIDList) - 1) {
2769 PrintAndLogEx(HINT, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card.");
2770 } else {
2771 for (int i = 0; i < ARRAYLEN(hintAIDList); i++) {
2772 if (cardFound[i] && strlen(hintAIDList[i].hint))
2773 PrintAndLogEx(HINT, "Hint: try `" _YELLOW_("%s") "` commands", hintAIDList[i].hint);
2778 DropField();
2779 return found;
2782 static uint32_t inc_sw_error_occurrence(uint16_t sw, uint32_t *all_sw) {
2783 uint8_t sw1 = (uint8_t)(sw >> 8);
2784 uint8_t sw2 = (uint8_t)(0xff & sw);
2786 // Don't count successes
2787 if (sw1 == 0x90 && sw2 == 0x00) {
2788 return 0;
2791 // Always max "Instruction not supported"
2792 if (sw1 == 0x6D && sw2 == 0x00) {
2793 return 0xFFFFFFFFUL;
2796 all_sw[(sw1 * 256) + sw2]++;
2798 return all_sw[(sw1 * 256) + sw2];
2801 static int CmdHf14AFindapdu(const char *Cmd) {
2802 // TODO: Option to select AID/File (and skip INS 0xA4).
2803 // TODO: Check all instructions with extended APDUs if the card support it.
2804 // TODO: Option to reset tag before every command.
2805 CLIParserContext *ctx;
2806 CLIParserInit(&ctx, "hf 14a apdufind",
2807 "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands.\n"
2808 "It loops all 256 possible values for each byte.\n"
2809 "The loop oder is INS -> P1/P2 (alternating) -> CLA.\n"
2810 "Tag must be on antenna before running.",
2811 "hf 14a apdufind\n"
2812 "hf 14a apdufind --cla 80\n"
2813 "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le\n"
2816 void *argtable[] = {
2817 arg_param_begin,
2818 arg_str0("c", "cla", "<hex>", "Start value of CLASS (1 hex byte)"),
2819 arg_str0("i", "ins", "<hex>", "Start value of INSTRUCTION (1 hex byte)"),
2820 arg_str0(NULL, "p1", "<hex>", "Start value of P1 (1 hex byte)"),
2821 arg_str0(NULL, "p2", "<hex>", "Start value of P2 (1 hex byte)"),
2822 arg_u64_0("r", "reset", "<number>", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"),
2823 arg_u64_0("e", "error-limit", "<number>", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."),
2824 arg_strx0("s", "skip-ins", "<hex>", "Do not test an instruction (can be specified multiple times)"),
2825 arg_lit0("l", "with-le", "Search for APDUs with Le=0 (case 2S) as well"),
2826 arg_lit0("v", "verbose", "Verbose output"),
2827 arg_param_end
2829 CLIExecWithReturn(ctx, Cmd, argtable, true);
2831 int cla_len = 0;
2832 uint8_t cla_arg[1] = {0};
2833 CLIGetHexWithReturn(ctx, 1, cla_arg, &cla_len);
2835 int ins_len = 0;
2836 uint8_t ins_arg[1] = {0};
2837 CLIGetHexWithReturn(ctx, 2, ins_arg, &ins_len);
2839 int p1_len = 0;
2840 uint8_t p1_arg[1] = {0};
2841 CLIGetHexWithReturn(ctx, 3, p1_arg, &p1_len);
2843 int p2_len = 0;
2844 uint8_t p2_arg[1] = {0};
2845 CLIGetHexWithReturn(ctx, 4, p2_arg, &p2_len);
2847 uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60);
2848 uint32_t error_limit = arg_get_u64_def(ctx, 6, 512);
2850 int ignore_ins_len = 0;
2851 uint8_t ignore_ins_arg[250] = {0};
2852 CLIGetHexWithReturn(ctx, 7, ignore_ins_arg, &ignore_ins_len);
2854 bool with_le = arg_get_lit(ctx, 8);
2855 bool verbose = arg_get_lit(ctx, 9);
2857 CLIParserFree(ctx);
2859 bool activate_field = true;
2860 bool keep_field_on = true;
2861 uint8_t cla = cla_arg[0];
2862 uint8_t ins = ins_arg[0];
2863 uint8_t p1 = p1_arg[0];
2864 uint8_t p2 = p2_arg[0];
2866 uint8_t response[PM3_CMD_DATA_SIZE] = {0};
2867 int response_n = 0;
2868 uint8_t aSELECT_AID[80];
2869 int aSELECT_AID_n = 0;
2871 // Check if the tag reponds to APDUs.
2872 PrintAndLogEx(INFO, "Sending a test APDU (select file command) to check if the tag is responding to APDU");
2873 param_gethex_to_eol("00a404000aa000000440000101000100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
2874 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, true, false, response, sizeof(response), &response_n);
2875 if (res != PM3_SUCCESS) {
2876 PrintAndLogEx(FAILED, "Tag did not respond to a test APDU (select file command). Aborting...");
2877 return res;
2880 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
2881 PrintAndLogEx(NORMAL, "");
2882 PrintAndLogEx(SUCCESS, "Starting the APDU finder [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2884 bool inc_p1 = false;
2885 bool skip_ins = false;
2886 uint32_t all_sw[256][256] = { { 0 } };
2887 uint32_t sw_occurrences = 0;
2889 uint64_t t_start = msclock();
2890 uint64_t t_last_reset = msclock();
2892 // Enumerate APDUs.
2893 do {
2894 do {
2895 do {
2896 retry_ins:
2897 // Exit (was the Enter key pressed)?
2898 if (kbd_enter_pressed()) {
2899 PrintAndLogEx(INFO, "User interrupted detected. Aborting");
2900 goto out;
2903 // Skip/Ignore this instrctuion?
2904 for (int i = 0; i < ignore_ins_len; i++) {
2905 if (ins == ignore_ins_arg[i]) {
2906 skip_ins = true;
2907 break;
2911 if (skip_ins) {
2912 skip_ins = false;
2913 continue;
2916 if (verbose) {
2917 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2920 // Send APDU without Le (case 1) and with Le = 0 (case 2S), if "with-le" was set.
2921 uint8_t command[5] = {cla, ins, p1, p2, 0x00};
2922 int command_n = 4;
2923 for (int i = 0; i < 1 + with_le; i++) {
2924 // Send APDU.
2925 res = ExchangeAPDU14a(command, command_n + i, activate_field, keep_field_on, response, sizeof(response), &response_n);
2926 if (res != PM3_SUCCESS) {
2927 DropField();
2928 activate_field = true;
2929 goto retry_ins;
2932 uint16_t sw = get_sw(response, response_n);
2933 sw_occurrences = inc_sw_error_occurrence(sw, all_sw[0]);
2935 // Show response.
2936 if (sw_occurrences < error_limit) {
2937 logLevel_t log_level = INFO;
2938 if (sw == ISO7816_OK) {
2939 log_level = SUCCESS;
2942 if (verbose == true || sw != 0x6e00) {
2943 PrintAndLogEx(log_level, "Got response for APDU \"%s\": %04X (%s)",
2944 sprint_hex_inrow(command, command_n + i),
2946 GetAPDUCodeDescription(sw >> 8, sw & 0xff)
2949 if (response_n > 2) {
2950 PrintAndLogEx(SUCCESS, "Response data is: %s | %s",
2951 sprint_hex_inrow(response, response_n - 2),
2952 sprint_ascii(response, response_n - 2)
2958 // Do not reativate the filed until the next reset.
2959 activate_field = false;
2960 } while (++ins != ins_arg[0]);
2962 // Increment P1/P2 in an alternating fashion.
2963 if (inc_p1) {
2964 p1++;
2965 } else {
2966 p2++;
2969 inc_p1 = !inc_p1;
2971 // Check if re-selecting the card is needed.
2972 uint64_t t_since_last_reset = ((msclock() - t_last_reset) / 1000);
2973 if (t_since_last_reset > reset_time) {
2974 DropField();
2975 activate_field = true;
2976 t_last_reset = msclock();
2977 PrintAndLogEx(INFO, "Last reset was %" PRIu64 " seconds ago. Resetting the tag to prevent timeout issues", t_since_last_reset);
2979 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2981 } while (p1 != p1_arg[0] || p2 != p2_arg[0]);
2983 cla++;
2984 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2986 } while (cla != cla_arg[0]);
2988 out:
2989 PrintAndLogEx(SUCCESS, "Runtime: %" PRIu64 " seconds\n", (msclock() - t_start) / 1000);
2990 DropField();
2991 return PM3_SUCCESS;
2994 int CmdHF14ANdefRead(const char *Cmd) {
2995 CLIParserContext *ctx;
2996 CLIParserInit(&ctx, "hf 14a ndefread",
2997 "Read NFC Data Exchange Format (NDEF) file on Type 4 NDEF tag",
2998 "hf 14a ndefread\n"
2999 "hf 14a ndefread -f myfilename -> save raw NDEF to file"
3002 void *argtable[] = {
3003 arg_param_begin,
3004 arg_str0("f", "file", "<fn>", "save raw NDEF to file"),
3005 arg_litn("v", "verbose", 0, 2, "verbose output"),
3006 arg_param_end
3008 CLIExecWithReturn(ctx, Cmd, argtable, true);
3009 int fnlen = 0;
3010 char filename[FILE_PATH_SIZE] = {0};
3011 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3013 bool verbose = arg_get_lit(ctx, 2);
3014 bool verbose2 = arg_get_lit(ctx, 2) > 1;
3015 CLIParserFree(ctx);
3017 bool activate_field = true;
3018 bool keep_field_on = true;
3019 uint8_t response[PM3_CMD_DATA_SIZE];
3020 int resplen = 0;
3021 bool backward_compatibility_v1 = false;
3023 // --------------- Select NDEF Tag application ----------------
3024 uint8_t aSELECT_AID[80];
3025 int aSELECT_AID_n = 0;
3026 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
3027 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3028 if (res != PM3_SUCCESS) {
3029 DropField();
3030 return res;
3033 if (resplen < 2) {
3034 DropField();
3035 return PM3_ESOFT;
3038 uint16_t sw = get_sw(response, resplen);
3039 if (sw != ISO7816_OK) {
3040 // Try NDEF Type 4 Tag v1.0
3041 param_gethex_to_eol("00a4040007d2760000850100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
3042 res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3043 if (res != PM3_SUCCESS) {
3044 DropField();
3045 return res;
3047 if (resplen < 2) {
3048 DropField();
3049 return PM3_ESOFT;
3052 sw = get_sw(response, resplen);
3053 if (sw != ISO7816_OK) {
3054 PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3055 DropField();
3056 return PM3_ESOFT;
3058 backward_compatibility_v1 = true;
3061 activate_field = false;
3062 keep_field_on = true;
3064 // --------------- CC file reading ----------------
3065 uint8_t aSELECT_FILE_CC[30];
3066 int aSELECT_FILE_CC_n = 0;
3067 if (backward_compatibility_v1) {
3068 param_gethex_to_eol("00a4000002e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
3069 } else {
3070 param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
3072 res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3073 if (res != PM3_SUCCESS) {
3074 DropField();
3075 return res;
3078 sw = get_sw(response, resplen);
3079 if (sw != ISO7816_OK) {
3080 PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3081 DropField();
3082 return PM3_ESOFT;
3085 uint8_t aREAD_CC[30];
3086 int aREAD_CC_n = 0;
3087 param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n);
3088 res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3089 if (res != PM3_SUCCESS) {
3090 DropField();
3091 return res;
3093 sw = get_sw(response, resplen);
3094 if (sw != ISO7816_OK) {
3095 PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3096 DropField();
3097 return PM3_ESOFT;
3100 // Parse CC data
3101 uint8_t cc_data[resplen - 2];
3102 memcpy(cc_data, response, sizeof(cc_data));
3103 uint8_t file_id[2] = {cc_data[9], cc_data[10]};
3105 if (verbose) {
3106 print_type4_cc_info(cc_data, sizeof(cc_data));
3109 uint16_t max_rapdu_size = (cc_data[3] << 8 | cc_data[4]) - 2;
3110 max_rapdu_size = max_rapdu_size < sizeof(response) - 2 ? max_rapdu_size : sizeof(response) - 2;
3112 // --------------- NDEF file reading ----------------
3113 uint8_t aSELECT_FILE_NDEF[30];
3114 int aSELECT_FILE_NDEF_n = 0;
3115 if (backward_compatibility_v1) {
3116 param_gethex_to_eol("00a4000002", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
3117 } else {
3118 param_gethex_to_eol("00a4000c02", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
3120 memcpy(aSELECT_FILE_NDEF + aSELECT_FILE_NDEF_n, file_id, sizeof(file_id));
3121 res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n + sizeof(file_id), activate_field, keep_field_on, response, sizeof(response), &resplen);
3122 if (res != PM3_SUCCESS) {
3123 DropField();
3124 return res;
3127 sw = get_sw(response, resplen);
3128 if (sw != ISO7816_OK) {
3129 PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3130 DropField();
3131 return PM3_ESOFT;
3134 // read first 2 bytes to get NDEF length
3135 uint8_t aREAD_NDEF[30];
3136 int aREAD_NDEF_n = 0;
3137 param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
3138 res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3139 if (res != PM3_SUCCESS) {
3140 DropField();
3141 return res;
3144 sw = get_sw(response, resplen);
3145 if (sw != ISO7816_OK) {
3146 PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3147 DropField();
3148 return PM3_ESOFT;
3151 uint16_t ndef_size = (response[0] << 8) + response[1];
3152 uint16_t offset = 2;
3153 uint8_t *ndef_file = calloc(ndef_size, sizeof(uint8_t));
3154 if (ndef_file == NULL) {
3155 PrintAndLogEx(ERR, "Out of memory error in CmdHF14ANdef(). Aborting...\n");
3156 DropField();
3157 return PM3_EMALLOC;
3160 if (ndef_size + offset > 0xFFFF) {
3161 PrintAndLogEx(ERR, "NDEF size abnormally large in CmdHF14ANdef(). Aborting...\n");
3162 free(ndef_file);
3163 DropField();
3164 return PM3_EOVFLOW;
3167 for (uint16_t i = offset; i < ndef_size + offset; i += max_rapdu_size) {
3168 uint16_t segment_size = max_rapdu_size < ndef_size + offset - i ? max_rapdu_size : ndef_size + offset - i;
3169 keep_field_on = i < ndef_size + offset - max_rapdu_size;
3170 aREAD_NDEF_n = 0;
3171 param_gethex_to_eol("00b00000", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
3172 aREAD_NDEF[2] = i >> 8;
3173 aREAD_NDEF[3] = i & 0xFF;
3174 aREAD_NDEF[4] = segment_size;
3176 res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n + 1, activate_field, keep_field_on, response, sizeof(response), &resplen);
3177 if (res != PM3_SUCCESS) {
3178 DropField();
3179 free(ndef_file);
3180 return res;
3183 sw = get_sw(response, resplen);
3184 if (sw != ISO7816_OK) {
3185 PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
3186 DropField();
3187 free(ndef_file);
3188 return PM3_ESOFT;
3191 if (resplen != segment_size + 2) {
3192 PrintAndLogEx(ERR, "reading NDEF file failed, expected %i bytes, got %i bytes.", segment_size, resplen - 2);
3193 DropField();
3194 free(ndef_file);
3195 return PM3_ESOFT;
3198 memcpy(ndef_file + (i - offset), response, segment_size);
3201 if (verbose2) {
3202 PrintAndLogEx(NORMAL, "");
3203 PrintAndLogEx(INFO, "--- " _CYAN_("NDEF raw") " ----------------");
3204 print_buffer(ndef_file, ndef_size, 1);
3207 NDEFRecordsDecodeAndPrint(ndef_file, ndef_size, verbose);
3209 pm3_save_dump(filename, ndef_file, ndef_size, jsfNDEF);
3211 if (verbose == false) {
3212 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf 14a ndefread -v`") " for more details");
3213 } else {
3214 if (verbose2 == false) {
3215 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf 14a ndefread -vv`") " for more details");
3219 free(ndef_file);
3220 return PM3_SUCCESS;
3223 int CmdHF14ANdefFormat(const char *Cmd) {
3224 CLIParserContext *ctx;
3225 CLIParserInit(&ctx, "hf 14a ndefformat",
3226 "Format ISO14443-a Tag as a NFC tag with Data Exchange Format (NDEF)",
3227 "hf 14a ndefformat\n"
3230 void *argtable[] = {
3231 arg_param_begin,
3232 arg_lit0("v", "verbose", "verbose output"),
3233 arg_param_end
3235 CLIExecWithReturn(ctx, Cmd, argtable, true);
3236 bool verbose = arg_get_lit(ctx, 1);
3237 CLIParserFree(ctx);
3239 if (g_session.pm3_present == false)
3240 return PM3_ENOTTY;
3242 bool activate_field = true;
3243 bool keep_field_on = false;
3244 uint8_t response[PM3_CMD_DATA_SIZE];
3245 int resplen = 0;
3247 SetAPDULogging(false);
3249 // step 1 - Select NDEF Tag application
3250 uint8_t aSELECT_AID[80];
3251 int aSELECT_AID_n = 0;
3252 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
3253 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
3255 if (res != PM3_SUCCESS) {
3256 return res;
3259 if (resplen < 2) {
3260 return PM3_ESOFT;
3263 bool have_application = true;
3264 uint16_t sw = get_sw(response, resplen);
3265 if (sw != ISO7816_OK) {
3266 have_application = false;
3267 PrintAndLogEx(INFO, "no NDEF application found");
3268 } else {
3269 PrintAndLogEx(INFO, "found ndef application");
3273 // setup desfire authentication context
3274 uint8_t empty_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
3275 DesfireContext_t dctx;
3276 dctx.secureChannel = DACNone;
3277 DesfireSetKey(&dctx, 0, T_DES, empty_key);
3278 DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
3279 DesfireSetCommandSet(&dctx, DCCNativeISO);
3280 DesfireSetCommMode(&dctx, DCMPlain);
3282 // step 1 - create application
3283 if (have_application == false) {
3284 // "hf mfdes createapp --aid 000001 --fid E110 --ks1 0B --ks2 A1 --dfhex D2760000850101 -t des -n 0 -k 0000000000000000"
3285 PrintAndLogEx(INFO, "creating NDEF application...");
3287 // authenticae first to AID 00 00 00
3288 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000000, false, verbose);
3289 if (res != PM3_SUCCESS) {
3290 DropField();
3291 PrintAndLogEx(INFO, "failed empty auth..");
3292 return res;
3295 // create application
3296 uint8_t dfname[] = {0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01};
3297 uint8_t ks1 = 0x0B;
3298 uint8_t ks2 = 0xA1; // bit FileID in ks2
3299 uint32_t appid = 0x0000001;
3300 uint16_t fileid = 0xE110;
3301 uint8_t data[250] = {0};
3302 size_t datalen = 0;
3304 DesfireAIDUintToByte(appid, &data[0]);
3305 data[3] = ks1;
3306 data[4] = ks2;
3307 Uint2byteToMemLe(&data[5], fileid);
3308 memcpy(&data[7], dfname, sizeof(dfname));
3309 datalen = 14;
3311 if (verbose) {
3312 PrintAndLogEx(INFO, "---------------------------");
3313 PrintAndLogEx(INFO, _CYAN_("Creating Application using:"));
3314 PrintAndLogEx(INFO, "AID........... 0x%02X%02X%02X", data[2], data[1], data[0]);
3315 PrintAndLogEx(INFO, "Key Set 1..... 0x%02X", data[3]);
3316 PrintAndLogEx(INFO, "Key Set 2..... 0x%02X", data[4]);
3317 PrintAndLogEx(INFO, "ISO file ID... %s", (data[4] & 0x20) ? "enabled" : "disabled");
3318 if ((data[4] & 0x20)) {
3319 PrintAndLogEx(INFO, "ISO file ID... 0x%04X", MemLeToUint2byte(&data[5]));
3320 PrintAndLogEx(INFO, "DF Name[%02d] %s | %s\n", 7, sprint_ascii(dfname, sizeof(dfname)), sprint_hex(dfname, sizeof(dfname)));
3322 PrintKeySettings(data[3], data[4], true, true);
3323 PrintAndLogEx(INFO, "---------------------------");
3326 res = DesfireCreateApplication(&dctx, data, datalen);
3327 if (res != PM3_SUCCESS) {
3328 PrintAndLogEx(ERR, "Desfire CreateApplication command " _RED_("error") ". Result: %d", res);
3329 DropField();
3330 return PM3_ESOFT;
3333 PrintAndLogEx(SUCCESS, "Desfire application %06x successfully " _GREEN_("created"), appid);
3336 // step 2 - create capability container (CC File)
3338 // authenticae to the new AID 00 00 01
3339 uint8_t aes_key[] = {
3340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3343 dctx.secureChannel = DACNone;
3344 DesfireSetKey(&dctx, 0, T_AES, aes_key);
3345 DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
3346 DesfireSetCommandSet(&dctx, DCCNativeISO);
3347 DesfireSetCommMode(&dctx, DCMPlain);
3348 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose);
3349 if (res != PM3_SUCCESS) {
3350 DropField();
3351 PrintAndLogEx(INFO, "failed aid auth..");
3352 return res;
3355 // hf mfdes createfile --aid 000001 --fid 01 --isofid E103 --amode plain --size 00000F
3356 // --rrights free --wrights key0 --rwrights key0 --chrights key0
3357 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3358 uint8_t fid = 0x01;
3359 uint16_t isofid = 0xE103;
3360 uint32_t fsize = 0x0F;
3361 uint8_t filetype = 0x00; // standard file
3363 // file access mode: plain 0x00
3364 // read access: free 0x0E
3365 // write access: key0 0x00
3366 // r/w access: key0 0x00
3367 // change access: key0 0x00
3368 memset(data, 0x00, sizeof(data));
3369 datalen = 0;
3371 data[0] = fid;
3372 data[1] = isofid & 0xff;
3373 data[2] = (isofid >> 8) & 0xff;
3374 datalen = 3;
3376 uint8_t *settings = &data[datalen];
3377 settings[0] = 0x00;
3378 datalen++;
3380 DesfireEncodeFileAcessMode(&settings[1], 0x0E, 0x00, 0x00, 0x00) ;
3381 datalen += 2;
3383 Uint3byteToMemLe(&data[datalen], fsize);
3384 datalen += 3;
3386 if (verbose) {
3387 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
3390 DesfirePrintCreateFileSettings(filetype, data, datalen);
3392 res = DesfireCreateFile(&dctx, filetype, data, datalen, true); // check length only if we dont use raw mode
3393 if (res != PM3_SUCCESS) {
3394 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
3395 DropField();
3396 return PM3_ESOFT;
3399 PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
3403 // hf mfdes write --aid 000001 --fid 01 -d 000F20003B00340406E10400FF00FF
3404 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3405 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose);
3406 if (res != PM3_SUCCESS) {
3407 DropField();
3408 PrintAndLogEx(INFO, "failed aid auth..");
3409 return res;
3412 uint8_t fnum = 0x01;
3413 uint32_t offset = 0;
3414 uint8_t cc_data[] = {0x00, 0x0F, 0x20, 0x00, 0x3B, 0x00, 0x34, 0x04, 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00};
3416 res = DesfireWriteFile(&dctx, fnum, offset, sizeof(cc_data), cc_data);
3417 if (res != PM3_SUCCESS) {
3418 PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res);
3419 DropField();
3420 return PM3_ESOFT;
3423 if (verbose) {
3424 PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum);
3429 // step 3 - create NDEF record file
3430 // hf mfdes write --aid 000001 --fid 02 -d 000CD1010855016E78702E636F6DFE
3431 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3433 fid = 0x02;
3434 isofid = 0xE104;
3435 fsize = 0xFF;
3436 filetype = 0x00; // standard file
3438 // file access mode: plain 0x00
3439 // read access: free 0x0E
3440 // write access: key0 0x00
3441 // r/w access: key0 0x00
3442 // change access: key0 0x00
3443 memset(data, 0x00, sizeof(data));
3444 datalen = 0;
3446 data[0] = fid;
3447 data[1] = isofid & 0xff;
3448 data[2] = (isofid >> 8) & 0xff;
3449 datalen = 3;
3451 settings = &data[datalen];
3452 settings[0] = 0x00;
3453 datalen++;
3455 DesfireEncodeFileAcessMode(&settings[1], 0x0E, 0x00, 0x00, 0x00) ;
3456 datalen += 2;
3458 Uint3byteToMemLe(&data[datalen], fsize);
3459 datalen += 3;
3461 if (verbose) {
3462 PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen));
3465 DesfirePrintCreateFileSettings(filetype, data, datalen);
3467 res = DesfireCreateFile(&dctx, filetype, data, datalen, true); // check length only if we dont use raw mode
3468 if (res != PM3_SUCCESS) {
3469 PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res);
3470 DropField();
3471 return PM3_ESOFT;
3474 PrintAndLogEx(SUCCESS, "%s file %02x in the app %06x created " _GREEN_("successfully"), GetDesfireFileType(filetype), data[0], appid);
3476 DropField();
3479 PrintAndLogEx(NORMAL, "");
3480 PrintAndLogEx(INFO, "finished");
3481 return PM3_SUCCESS;
3484 int CmdHF14ANdefWrite(const char *Cmd) {
3485 CLIParserContext *ctx;
3486 CLIParserInit(&ctx, "hf 14a ndefwrite",
3487 "Write raw NDEF hex bytes to tag. This commands assumes tag already been NFC/NDEF formatted.\n",
3488 "hf 14a ndefwrite -d 0300FE -> write empty record to tag\n"
3489 "hf 14a ndefwrite -f myfilename\n"
3490 "hf 14a ndefwrite -d 003fd1023a53709101195405656e2d55534963656d616e2054776974746572206c696e6b5101195502747769747465722e636f6d2f686572726d616e6e31303031\n"
3493 void *argtable[] = {
3494 arg_param_begin,
3495 arg_str0("d", NULL, "<hex>", "raw NDEF hex bytes"),
3496 arg_str0("f", "file", "<fn>", "write raw NDEF file to tag"),
3497 arg_lit0("p", NULL, "fix NDEF record headers / terminator block if missing"),
3498 arg_lit0("v", "verbose", "verbose output"),
3499 arg_param_end
3501 CLIExecWithReturn(ctx, Cmd, argtable, false);
3503 uint8_t raw[256] = {0};
3504 int rawlen = 0;
3505 CLIGetHexWithReturn(ctx, 1, raw, &rawlen);
3507 int fnlen = 0;
3508 char filename[FILE_PATH_SIZE] = {0};
3509 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3511 bool fix_msg = arg_get_lit(ctx, 3);
3512 bool verbose = arg_get_lit(ctx, 4);
3513 CLIParserFree(ctx);
3515 if (g_session.pm3_present == false) {
3516 return PM3_ENOTTY;
3519 if ((rawlen && fnlen) || (rawlen == 0 && fnlen == 0)) {
3520 PrintAndLogEx(WARNING, "Please specify either raw hex or filename");
3521 return PM3_EINVARG;
3524 int res = PM3_SUCCESS;
3525 int32_t bytes = rawlen;
3527 // read dump file
3528 if (fnlen) {
3529 uint8_t *dump = NULL;
3530 size_t bytes_read = 0;
3531 res = pm3_load_dump(filename, (void **)&dump, &bytes_read, sizeof(raw));
3532 if (res != PM3_SUCCESS) {
3533 return res;
3535 memcpy(raw, dump, bytes_read);
3536 bytes = bytes_read;
3537 free(dump);
3540 if (verbose) {
3541 PrintAndLogEx(INFO, "Num of bytes... %i (raw %i)", bytes, rawlen);
3544 // Has raw bytes ndef message header?bytes
3545 switch (raw[0]) {
3546 case 0x00:
3547 case 0x01:
3548 case 0x02:
3549 case 0x03:
3550 case 0xFD:
3551 case 0xFE:
3552 break;
3553 default: {
3554 if (fix_msg == false) {
3555 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a proper header, continuing...");
3556 } else {
3557 if (bytes + 2 > sizeof(raw)) {
3558 PrintAndLogEx(WARNING, "no room for header, exiting...");
3559 return PM3_EMALLOC;
3561 uint8_t tmp_raw[256];
3562 memcpy(tmp_raw, raw, sizeof(tmp_raw));
3563 raw[0] = 0x00;
3564 raw[1] = bytes;
3565 memcpy(raw + 2, tmp_raw, sizeof(raw) - 2);
3566 bytes += 2;
3567 PrintAndLogEx(SUCCESS, "Added generic message header (0x03)");
3572 // Has raw bytes ndef a terminator block?
3573 if (raw[bytes - 1] != 0xFE) {
3574 if (fix_msg == false) {
3575 PrintAndLogEx(WARNING, "raw NDEF message doesn't have a terminator block, continuing...");
3576 } else {
3578 if (bytes + 1 > sizeof(raw)) {
3579 PrintAndLogEx(WARNING, "no room for terminator block, exiting...");
3580 return PM3_EMALLOC;
3582 raw[bytes] = 0xFE;
3583 bytes++;
3584 PrintAndLogEx(SUCCESS, "Added terminator block (0xFE)");
3588 if (verbose) {
3589 PrintAndLogEx(INFO, "Num of Bytes... %u", bytes);
3590 print_buffer(raw, bytes, 0);
3594 // setup desfire authentication context
3595 // authenticae to the new AID 00 00 01
3596 uint8_t aes_key[] = {
3597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
3601 DesfireContext_t dctx;
3602 dctx.secureChannel = DACNone;
3603 DesfireSetKey(&dctx, 0, T_AES, aes_key);
3604 DesfireSetKdf(&dctx, MFDES_KDF_ALGO_NONE, NULL, 0);
3605 DesfireSetCommandSet(&dctx, DCCNativeISO);
3606 DesfireSetCommMode(&dctx, DCMPlain);
3607 res = DesfireSelectAndAuthenticateEx(&dctx, DACEV1, 0x000001, false, verbose);
3608 if (res != PM3_SUCCESS) {
3609 DropField();
3610 PrintAndLogEx(INFO, "failed aid auth..");
3611 return res;
3614 // write ndef file
3616 // hf mfdes write --aid 000002 --fid 02 -
3617 // -n 0 -t aes -k 00000000000000000000000000000000 -m plain
3618 uint8_t fnum = 0x02;
3619 uint32_t offset = 0;
3621 res = DesfireWriteFile(&dctx, fnum, offset, bytes, raw);
3622 if (res != PM3_SUCCESS) {
3623 PrintAndLogEx(ERR, "Desfire WriteFile command " _RED_("error") ". Result: %d", res);
3624 DropField();
3625 return PM3_ESOFT;
3628 if (verbose) {
3629 PrintAndLogEx(INFO, "Write data file %02x " _GREEN_("success"), fnum);
3632 PrintAndLogEx(NORMAL, "");
3633 PrintAndLogEx(INFO, "finished");
3634 return PM3_SUCCESS;
3637 static command_t CommandTable[] = {
3638 {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("General") " -----------------------"},
3639 {"help", CmdHelp, AlwaysAvailable, "This help"},
3640 {"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"},
3641 {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("Operations") " ---------------------"},
3642 {"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
3643 {"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
3644 {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"},
3645 {"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"},
3646 {"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"},
3647 {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"},
3648 {"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
3649 {"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"},
3650 {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------- " _CYAN_("APDU") " -------------------------"},
3651 {"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"},
3652 {"apdufind", CmdHf14AFindapdu, IfPm3Iso14443a, "Enumerate APDUs - CLA/INS/P1P2"},
3653 {"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
3654 {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------- " _CYAN_("NDEF") " -------------------------"},
3655 {"ndefformat", CmdHF14ANdefFormat, IfPm3Iso14443a, "Format ISO 14443-A as NFC Type 4 tag"},
3656 {"ndefread", CmdHF14ANdefRead, IfPm3Iso14443a, "Read an NDEF file from ISO 14443-A Type 4 tag"},
3657 {"ndefwrite", CmdHF14ANdefWrite, IfPm3Iso14443a, "Write NDEF records to ISO 14443-A tag"},
3658 {NULL, NULL, NULL, NULL}
3661 static int CmdHelp(const char *Cmd) {
3662 (void)Cmd; // Cmd is not used so far
3663 CmdsHelp(CommandTable);
3664 return PM3_SUCCESS;
3667 int CmdHF14A(const char *Cmd) {
3668 clearCommandBuffer();
3669 return CmdsParse(CommandTable, Cmd);