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