textual
[RRG-proxmark3.git] / client / src / cmdhf14a.c
blobb471ed9fdaabde728c08ee2e18b0b0ef72633aa6
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // 2011, 2017 - 2019 Merlok
4 // 2014, Peter Fillmore
5 // 2015, 2016, 2017 Iceman
6 //
7 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
8 // at your option, any later version. See the LICENSE.txt file for the text of
9 // the license.
10 //-----------------------------------------------------------------------------
11 // High frequency ISO14443A commands
12 //-----------------------------------------------------------------------------
13 #include "cmdhf14a.h"
14 #include <ctype.h>
15 #include <string.h>
16 #include "cmdparser.h" // command_t
17 #include "commonutil.h" // ARRAYLEN
18 #include "comms.h" // clearCommandBuffer
19 #include "cmdtrace.h"
20 #include "cliparser.h"
21 #include "cmdhfmf.h"
22 #include "cmdhfmfu.h"
23 #include "iso7816/iso7816core.h"
24 #include "emv/emvcore.h"
25 #include "ui.h"
26 #include "crc16.h"
27 #include "util_posix.h" // msclock
28 #include "aidsearch.h"
29 #include "cmdhf.h" // handle HF plot
30 #include "cliparser.h"
31 #include "protocols.h" // definitions of ISO14A/7816 protocol, MAGIC_GEN_1A
32 #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
33 #include "nfc/ndef.h" // NDEFRecordsDecodeAndPrint
34 #include "cmdnfc.h" // print_type4_cc_info
36 bool APDUInFramingEnable = true;
38 static int CmdHelp(const char *Cmd);
39 static int waitCmd(bool i_select, uint32_t timeout, bool verbose);
41 static const manufactureName manufactureMapping[] = {
42 // ID, "Vendor Country"
43 { 0x01, "Motorola UK" },
44 { 0x02, "ST Microelectronics SA France" },
45 { 0x03, "Hitachi, Ltd Japan" },
46 { 0x04, "NXP Semiconductors Germany" },
47 { 0x05, "Infineon Technologies AG Germany" },
48 { 0x06, "Cylink USA" },
49 { 0x07, "Texas Instrument France" },
50 { 0x08, "Fujitsu Limited Japan" },
51 { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" },
52 { 0x0A, "NEC Japan" },
53 { 0x0B, "Oki Electric Industry Co. Ltd Japan" },
54 { 0x0C, "Toshiba Corp. Japan" },
55 { 0x0D, "Mitsubishi Electric Corp. Japan" },
56 { 0x0E, "Samsung Electronics Co. Ltd Korea" },
57 { 0x0F, "Hynix / Hyundai, Korea" },
58 { 0x10, "LG-Semiconductors Co. Ltd Korea" },
59 { 0x11, "Emosyn-EM Microelectronics USA" },
60 { 0x12, "INSIDE Technology France" },
61 { 0x13, "ORGA Kartensysteme GmbH Germany" },
62 { 0x14, "SHARP Corporation Japan" },
63 { 0x15, "ATMEL France" },
64 { 0x16, "EM Microelectronic-Marin SA Switzerland" },
65 { 0x17, "KSW Microtec GmbH Germany" },
66 { 0x18, "ZMD AG Germany" },
67 { 0x19, "XICOR, Inc. USA" },
68 { 0x1A, "Sony Corporation Japan" },
69 { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" },
70 { 0x1C, "Emosyn USA" },
71 { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" },
72 { 0x1E, "Magellan Technology Pty Limited Australia" },
73 { 0x1F, "Melexis NV BO Switzerland" },
74 { 0x20, "Renesas Technology Corp. Japan" },
75 { 0x21, "TAGSYS France" },
76 { 0x22, "Transcore USA" },
77 { 0x23, "Shanghai belling corp., ltd. China" },
78 { 0x24, "Masktech Germany Gmbh Germany" },
79 { 0x25, "Innovision Research and Technology Plc UK" },
80 { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" },
81 { 0x27, "Cypak AB Sweden" },
82 { 0x28, "Ricoh Japan" },
83 { 0x29, "ASK France" },
84 { 0x2A, "Unicore Microsystems, LLC Russian Federation" },
85 { 0x2B, "Dallas Semiconductor/Maxim USA" },
86 { 0x2C, "Impinj, Inc. USA" },
87 { 0x2D, "RightPlug Alliance USA" },
88 { 0x2E, "Broadcom Corporation USA" },
89 { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" },
90 { 0x30, "BeeDar Technology Inc. USA" },
91 { 0x31, "RFIDsec Denmark" },
92 { 0x32, "Schweizer Electronic AG Germany" },
93 { 0x33, "AMIC Technology Corp Taiwan" },
94 { 0x34, "Mikron JSC Russia" },
95 { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" },
96 { 0x36, "IDS Microchip AG Switzerland" },
97 { 0x37, "Thinfilm - Kovio USA" },
98 { 0x38, "HMT Microelectronic Ltd Switzerland" },
99 { 0x39, "Silicon Craft Technology Thailand" },
100 { 0x3A, "Advanced Film Device Inc. Japan" },
101 { 0x3B, "Nitecrest Ltd UK" },
102 { 0x3C, "Verayo Inc. USA" },
103 { 0x3D, "HID Global USA" },
104 { 0x3E, "Productivity Engineering Gmbh Germany" },
105 { 0x3F, "Austriamicrosystems AG (reserved) Austria" },
106 { 0x40, "Gemalto SA France" },
107 { 0x41, "Renesas Electronics Corporation Japan" },
108 { 0x42, "3Alogics Inc Korea" },
109 { 0x43, "Top TroniQ Asia Limited Hong Kong" },
110 { 0x44, "Gentag Inc. USA" },
111 { 0x45, "Invengo Information Technology Co.Ltd China" },
112 { 0x46, "Guangzhou Sysur Microelectronics, Inc China" },
113 { 0x47, "CEITEC S.A. Brazil" },
114 { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" },
115 { 0x49, "MediaTek Inc Taiwan" },
116 { 0x4A, "Angstrem PJSC Russia" },
117 { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" },
118 { 0x4C, "LEGIC Identsystems AG Switzerland" },
119 { 0x4D, "Balluff GmbH Germany" },
120 { 0x4E, "Oberthur Technologies France" },
121 { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" },
122 { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" },
123 { 0x51, "Giesecke & Devrient GmbH Germany" },
124 { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" },
125 { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" },
126 { 0x54, "Intel Corporation USA" },
127 { 0x55, "Microsensys GmbH Germany" },
128 { 0x56, "Sonix Technology Co., Ltd. Taiwan" },
129 { 0x57, "Qualcomm Technologies Inc USA" },
130 { 0x58, "Realtek Semiconductor Corp Taiwan" },
131 { 0x59, "Freevision Technologies Co. Ltd China" },
132 { 0x5A, "Giantec Semiconductor Inc. China" },
133 { 0x5B, "JSC Angstrem-T Russia" },
134 { 0x5C, "STARCHIP France" },
135 { 0x5D, "SPIRTECH France" },
136 { 0x5E, "GANTNER Electronic GmbH Austria" },
137 { 0x5F, "Nordic Semiconductor Norway" },
138 { 0x60, "Verisiti Inc USA" },
139 { 0x61, "Wearlinks Technology Inc. China" },
140 { 0x62, "Userstar Information Systems Co., Ltd Taiwan" },
141 { 0x63, "Pragmatic Printing Ltd. UK" },
142 { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico - LSI-TEC Brazil" },
143 { 0x65, "Tendyron Corporation China" },
144 { 0x66, "MUTO Smart Co., Ltd. Korea" },
145 { 0x67, "ON Semiconductor USA" },
146 { 0x68, "TUBITAK BILGEM Turkey" },
147 { 0x69, "Huada Semiconductor Co., Ltd China" },
148 { 0x6A, "SEVENEY France" },
149 { 0x6B, "ISSM France" },
150 { 0x6C, "Wisesec Ltd Israel" },
151 { 0x7C, "DB HiTek Co Ltd Korea" },
152 { 0x7D, "SATO Vicinity Australia" },
153 { 0x7E, "Holtek Taiwan" },
154 { 0x00, "no tag-info available" } // must be the last entry
157 // get a product description based on the UID
158 // uid[8] tag uid
159 // returns description of the best match
160 const char *getTagInfo(uint8_t uid) {
162 int i;
164 for (i = 0; i < ARRAYLEN(manufactureMapping); ++i)
165 if (uid == manufactureMapping[i].uid)
166 return manufactureMapping[i].desc;
168 //No match, return default
169 return manufactureMapping[ARRAYLEN(manufactureMapping) - 1].desc;
172 static const hintAIDListT hintAIDList[] = {
173 // AID, AID len, name, hint - how to use
174 { "\xA0\x00\x00\x06\x47\x2F\x00\x01", 8, "FIDO", "hf fido" },
175 { "\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00", 11, "PIV", "" },
176 { "\xD2\x76\x00\x01\x24\x01", 8, "OpenPGP", "" },
177 { "\x31\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (pse)", "hf emv" },
178 { "\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31", 14, "EMV (ppse)", "hf emv" },
179 { "\x41\x44\x20\x46\x31", 5, "CIPURSE", "hf cipurse" },
180 { "\xd2\x76\x00\x00\x85\x01\x00", 7, "desfire", "hf mfdes" },
183 // iso14a apdu input frame length
184 static uint16_t g_frame_len = 0;
185 uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
187 static int CmdHF14AList(const char *Cmd) {
188 return CmdTraceListAlias(Cmd, "hf 14a", "14a");
191 int hf14a_getconfig(hf14a_config *config) {
192 if (!session.pm3_present) return PM3_ENOTTY;
194 if (config == NULL)
195 return PM3_EINVARG;
197 clearCommandBuffer();
199 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG, NULL, 0);
200 PacketResponseNG resp;
201 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG, &resp, 2000)) {
202 PrintAndLogEx(WARNING, "command execution time out");
203 return PM3_ETIMEOUT;
205 memcpy(config, resp.data.asBytes, sizeof(hf14a_config));
206 return PM3_SUCCESS;
209 int hf14a_setconfig(hf14a_config *config, bool verbose) {
210 if (!session.pm3_present) return PM3_ENOTTY;
212 clearCommandBuffer();
213 if (config != NULL) {
214 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)config, sizeof(hf14a_config));
215 if (verbose) {
216 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0);
218 } else {
219 SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0);
222 return PM3_SUCCESS;
225 static int hf_14a_config_example(void) {
226 PrintAndLogEx(NORMAL, "\nExamples to revive Gen2/DirectWrite magic cards failing at anticollision:");
227 PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 4b UID")":");
228 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
229 PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344440804006263646566676869"));
230 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
231 PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 4b UID")":");
232 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 skip --rats skip"));
233 PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 11223344441802006263646566676869"));
234 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
235 PrintAndLogEx(NORMAL, _CYAN_(" MFC 1k 7b UID")":");
236 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip --rats skip"));
237 PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566084400626364656667"));
238 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
239 PrintAndLogEx(NORMAL, _CYAN_(" MFC 4k 7b UID")":");
240 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa forcce --bcc ignore --cl2 force --cl3 skip --rats skip"));
241 PrintAndLogEx(NORMAL, _YELLOW_(" hf mf wrbl --blk 0 -k FFFFFFFFFFFF -d 04112233445566184200626364656667"));
242 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
243 PrintAndLogEx(NORMAL, _CYAN_(" MFUL ")"/" _CYAN_(" MFUL EV1 ")"/" _CYAN_(" MFULC")":");
244 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --atqa force --bcc ignore --cl2 force --cl3 skip -rats skip"));
245 PrintAndLogEx(NORMAL, _YELLOW_(" hf mfu setuid --uid 04112233445566"));
246 PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config --std"));
247 return PM3_SUCCESS;
249 static int CmdHf14AConfig(const char *Cmd) {
250 if (!session.pm3_present) return PM3_ENOTTY;
252 CLIParserContext *ctx;
253 CLIParserInit(&ctx, "hf 14a config",
254 "Configure 14a settings (use with caution)",
255 "hf 14a config -> Print current configuration\n"
256 "hf 14a config --std -> Reset default configuration (follow standard)\n"
257 "hf 14a config --atqa std -> Follow standard\n"
258 "hf 14a config --atqa force -> Force execution of anticollision\n"
259 "hf 14a config --atqa skip -> Skip anticollision\n"
260 "hf 14a config --bcc std -> Follow standard\n"
261 "hf 14a config --bcc fix -> Fix bad BCC in anticollision\n"
262 "hf 14a config --bcc ignore -> Ignore bad BCC and use it as such\n"
263 "hf 14a config --cl2 std -> Follow standard\n"
264 "hf 14a config --cl2 force -> Execute CL2\n"
265 "hf 14a config --cl2 skip -> Skip CL2\n"
266 "hf 14a config --cl3 std -> Follow standard\n"
267 "hf 14a config --cl3 force -> Execute CL3\n"
268 "hf 14a config --cl3 skip -> Skip CL3\n"
269 "hf 14a config --rats std -> Follow standard\n"
270 "hf 14a config --rats force -> Execute RATS\n"
271 "hf 14a config --rats skip -> Skip RATS");
273 void *argtable[] = {
274 arg_param_begin,
275 arg_str0(NULL, "atqa", "<std|force|skip>", "Configure ATQA<>anticollision behavior"),
276 arg_str0(NULL, "bcc", "<std|fix|ignore>", "Configure BCC behavior"),
277 arg_str0(NULL, "cl2", "<std|force|skip>", "Configure SAK<>CL2 behavior"),
278 arg_str0(NULL, "cl3", "<std|force|skip>", "Configure SAK<>CL3 behavior"),
279 arg_str0(NULL, "rats", "<std|force|skip>", "Configure RATS behavior"),
280 arg_lit0(NULL, "std", "Reset default configuration: follow all standard"),
281 arg_lit0("v", "verbose", "verbose output, also prints examples for reviving Gen2 cards"),
282 arg_param_end
284 CLIExecWithReturn(ctx, Cmd, argtable, true);
285 bool defaults = arg_get_lit(ctx, 6);
286 int vlen = 0;
287 char value[10];
288 int atqa = defaults ? 0 : -1;
289 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)value, sizeof(value), &vlen);
290 if (vlen > 0) {
291 if (strcmp(value, "std") == 0) atqa = 0;
292 else if (strcmp(value, "force") == 0) atqa = 1;
293 else if (strcmp(value, "skip") == 0) atqa = 2;
294 else {
295 PrintAndLogEx(ERR, "atqa argument must be 'std', 'force', or 'skip'");
296 CLIParserFree(ctx);
297 return PM3_EINVARG;
300 int bcc = defaults ? 0 : -1;
301 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)value, sizeof(value), &vlen);
302 if (vlen > 0) {
303 if (strcmp(value, "std") == 0) bcc = 0;
304 else if (strcmp(value, "fix") == 0) bcc = 1;
305 else if (strcmp(value, "ignore") == 0) bcc = 2;
306 else {
307 PrintAndLogEx(ERR, "bcc argument must be 'std', 'fix', or 'ignore'");
308 CLIParserFree(ctx);
309 return PM3_EINVARG;
312 int cl2 = defaults ? 0 : -1;
313 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)value, sizeof(value), &vlen);
314 if (vlen > 0) {
315 if (strcmp(value, "std") == 0) cl2 = 0;
316 else if (strcmp(value, "force") == 0) cl2 = 1;
317 else if (strcmp(value, "skip") == 0) cl2 = 2;
318 else {
319 PrintAndLogEx(ERR, "cl2 argument must be 'std', 'force', or 'skip'");
320 CLIParserFree(ctx);
321 return PM3_EINVARG;
324 int cl3 = defaults ? 0 : -1;
325 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)value, sizeof(value), &vlen);
326 if (vlen > 0) {
327 if (strcmp(value, "std") == 0) cl3 = 0;
328 else if (strcmp(value, "force") == 0) cl3 = 1;
329 else if (strcmp(value, "skip") == 0) cl3 = 2;
330 else {
331 PrintAndLogEx(ERR, "cl3 argument must be 'std', 'force', or 'skip'");
332 CLIParserFree(ctx);
333 return PM3_EINVARG;
336 int rats = defaults ? 0 : -1;
337 CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)value, sizeof(value), &vlen);
338 if (vlen > 0) {
339 if (strcmp(value, "std") == 0) rats = 0;
340 else if (strcmp(value, "force") == 0) rats = 1;
341 else if (strcmp(value, "skip") == 0) rats = 2;
342 else {
343 PrintAndLogEx(ERR, "rats argument must be 'std', 'force', or 'skip'");
344 CLIParserFree(ctx);
345 return PM3_EINVARG;
349 bool verbose = arg_get_lit(ctx, 7);
351 CLIParserFree(ctx);
353 // validations
354 if (strlen(Cmd) == 0) {
355 return hf14a_setconfig(NULL, verbose);
358 if (verbose) {
359 hf_14a_config_example();
362 hf14a_config config = {
363 .forceanticol = atqa,
364 .forcebcc = bcc,
365 .forcecl2 = cl2,
366 .forcecl3 = cl3,
367 .forcerats = rats
370 return hf14a_setconfig(&config, verbose);
373 int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
374 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
376 PacketResponseNG resp;
377 WaitForResponse(CMD_ACK, &resp);
379 memcpy(card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
381 uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
383 if (select_status == 0) {
384 PrintAndLogEx(ERR, "E->iso14443a card select failed");
385 return 1;
388 if (select_status == 2) {
389 PrintAndLogEx(ERR, "E->Card doesn't support iso14443-4 mode");
390 return 1;
393 if (select_status == 3) {
394 PrintAndLogEx(INFO, "E->Card doesn't support standard iso14443-3 anticollision");
395 PrintAndLogEx(SUCCESS, "\tATQA : %02x %02x", card->atqa[1], card->atqa[0]);
396 return 1;
399 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card->uid, card->uidlen));
400 PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card->atqa[1], card->atqa[0]);
401 PrintAndLogEx(SUCCESS, " SAK: %02x [%" PRIu64 "]", card->sak, resp.oldarg[0]);
402 if (card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
403 PrintAndLogEx(INFO, "E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len));
404 return 1;
407 PrintAndLogEx(SUCCESS, " ATS: %s", sprint_hex(card->ats, card->ats_len));
408 return 0;
411 static int CmdHF14AReader(const char *Cmd) {
412 CLIParserContext *ctx;
413 CLIParserInit(&ctx, "hf 14a reader",
414 "Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
415 "hf 14a reader -@ -> Continuous mode");
417 void *argtable[] = {
418 arg_param_begin,
419 arg_lit0("k", "keep", "keep the field active after command executed"),
420 arg_lit0("s", "silent", "silent (no messages)"),
421 arg_lit0(NULL, "drop", "just drop the signal field"),
422 arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"),
423 arg_lit0("@", NULL, "continuous reader mode"),
424 arg_param_end
426 CLIExecWithReturn(ctx, Cmd, argtable, true);
428 bool disconnectAfter = true;
429 if (arg_get_lit(ctx, 1)) {
430 disconnectAfter = false;
433 bool silent = arg_get_lit(ctx, 2);
435 uint32_t cm = ISO14A_CONNECT;
436 if (arg_get_lit(ctx, 3)) {
437 cm &= ~ISO14A_CONNECT;
440 if (arg_get_lit(ctx, 4)) {
441 cm |= ISO14A_NO_RATS;
444 bool continuous = arg_get_lit(ctx, 5);
446 CLIParserFree(ctx);
448 int res = PM3_SUCCESS;
450 if (!disconnectAfter)
451 cm |= ISO14A_NO_DISCONNECT;
452 if (continuous) {
453 PrintAndLogEx(INFO, "Press " _GREEN_("Enter") " to exit");
455 do {
456 clearCommandBuffer();
457 SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
459 if (ISO14A_CONNECT & cm) {
460 PacketResponseNG resp;
461 if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
462 if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed");
463 DropField();
464 res = PM3_ESOFT;
465 goto plot;
468 iso14a_card_select_t card;
469 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
472 0: couldn't read
473 1: OK, with ATS
474 2: OK, no ATS
475 3: proprietary Anticollision
477 uint64_t select_status = resp.oldarg[0];
479 if (select_status == 0) {
480 if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed");
481 DropField();
482 res = PM3_ESOFT;
483 goto plot;
486 if (select_status == 3) {
487 if (!(silent && continuous)) {
488 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
489 PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card.atqa[1], card.atqa[0]);
491 DropField();
492 res = PM3_ESOFT;
493 goto plot;
495 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
496 if (!(silent && continuous)) {
497 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
498 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
500 if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
501 PrintAndLogEx(SUCCESS, " ATS: " _GREEN_("%s"), sprint_hex(card.ats, card.ats_len));
504 if (!disconnectAfter) {
505 if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands");
508 plot:
509 if (continuous) {
510 res = handle_hf_plot();
511 if (res != PM3_SUCCESS) {
512 break;
516 if (kbd_enter_pressed()) {
517 break;
520 } while (continuous);
522 if (disconnectAfter) {
523 if (silent == false) {
524 PrintAndLogEx(INFO, "field dropped.");
528 if (continuous)
529 return PM3_SUCCESS;
530 else
531 return res;
534 static int CmdHF14AInfo(const char *Cmd) {
535 bool verbose = true;
536 bool do_nack_test = false;
537 bool do_aid_search = false;
539 CLIParserContext *ctx;
540 CLIParserInit(&ctx, "hf 14a info",
541 "This command makes more extensive tests against a ISO14443a tag in order to collect information",
542 "hf 14a info -nsv -> shows full information about the card\n");
544 void *argtable[] = {
545 arg_param_begin,
546 arg_lit0("v", "verbose", "adds some information to results"),
547 arg_lit0("n", "nacktest", "test for nack bug"),
548 arg_lit0("s", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
549 arg_param_end
551 CLIExecWithReturn(ctx, Cmd, argtable, true);
553 verbose = arg_get_lit(ctx, 1);
554 do_nack_test = arg_get_lit(ctx, 2);
555 do_aid_search = arg_get_lit(ctx, 3);
557 CLIParserFree(ctx);
559 infoHF14A(verbose, do_nack_test, do_aid_search);
560 return PM3_SUCCESS;
563 // Collect ISO14443 Type A UIDs
564 static int CmdHF14ACUIDs(const char *Cmd) {
565 CLIParserContext *ctx;
566 CLIParserInit(&ctx, "hf 14a cuids",
567 "Collect n>0 ISO14443-a UIDs in one go",
568 "hf 14a cuids -n 5 --> Collect 5 UIDs");
570 void *argtable[] = {
571 arg_param_begin,
572 arg_int0("n", "num", "<dec>", "Number of UIDs to collect"),
573 arg_param_end
575 CLIExecWithReturn(ctx, Cmd, argtable, true);
577 // requested number of UIDs
578 // collect at least 1 (e.g. if no parameter was given)
579 int n = arg_get_int_def(ctx, 1, 1);
581 CLIParserFree(ctx);
583 uint64_t t1 = msclock();
584 PrintAndLogEx(SUCCESS, "collecting %d UIDs", n);
586 // repeat n times
587 for (int i = 0; i < n; i++) {
589 if (kbd_enter_pressed()) {
590 PrintAndLogEx(WARNING, "aborted via keyboard!\n");
591 break;
594 // execute anticollision procedure
595 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
597 PacketResponseNG resp;
598 WaitForResponse(CMD_ACK, &resp);
600 iso14a_card_select_t *card = (iso14a_card_select_t *) resp.data.asBytes;
602 // check if command failed
603 if (resp.oldarg[0] == 0) {
604 PrintAndLogEx(WARNING, "card select failed.");
605 } else {
606 char uid_string[20];
607 for (uint16_t m = 0; m < card->uidlen; m++) {
608 sprintf(&uid_string[2 * m], "%02X", card->uid[m]);
610 PrintAndLogEx(SUCCESS, "%s", uid_string);
613 PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000);
614 return 1;
617 // ## simulate iso14443a tag
618 int CmdHF14ASim(const char *Cmd) {
619 CLIParserContext *ctx;
620 CLIParserInit(&ctx, "hf 14a sim",
621 "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID",
622 "hf 14a sim -t 1 --uid 11223344 -> MIFARE Classic 1k\n"
623 "hf 14a sim -t 2 -> MIFARE Ultralight\n"
624 "hf 14a sim -t 3 -> MIFARE Desfire\n"
625 "hf 14a sim -t 4 -> ISO/IEC 14443-4\n"
626 "hf 14a sim -t 5 -> MIFARE Tnp3xxx\n"
627 "hf 14a sim -t 6 -> MIFARE Mini\n"
628 "hf 14a sim -t 7 -> AMIIBO (NTAG 215), pack 0x8080\n"
629 "hf 14a sim -t 8 -> MIFARE Classic 4k\n"
630 "hf 14a sim -t 9 -> FM11RF005SH Shanghai Metro\n"
631 "hf 14a sim -t 10 -> ST25TA IKEA Rothult\n");
633 void *argtable[] = {
634 arg_param_begin,
635 arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
636 arg_str0("u", "uid", "<hex>", "4, 7 or 10 byte UID"),
637 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
638 arg_lit0("x", NULL, "Performs the 'reader attack', nr/ar attack against a reader"),
639 arg_lit0(NULL, "sk", "Fill simulator keys from found keys"),
640 arg_lit0("v", "verbose", "verbose output"),
641 arg_param_end
643 CLIExecWithReturn(ctx, Cmd, argtable, false);
645 int tagtype = arg_get_int(ctx, 1);
647 int uid_len = 0;
648 uint8_t uid[10] = {0};
649 CLIGetHexWithReturn(ctx, 2, uid, &uid_len);
651 uint8_t flags = 0;
652 bool useUIDfromEML = true;
654 if (uid_len > 0) {
655 switch (uid_len) {
656 case 10:
657 flags |= FLAG_10B_UID_IN_DATA;
658 break;
659 case 7:
660 flags |= FLAG_7B_UID_IN_DATA;
661 break;
662 case 4:
663 flags |= FLAG_4B_UID_IN_DATA;
664 break;
665 default:
666 PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID");
667 CLIParserFree(ctx);
668 return PM3_EINVARG;
670 PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len));
671 useUIDfromEML = false;
674 uint8_t exitAfterNReads = arg_get_int(ctx, 3);
676 if (arg_get_lit(ctx, 4)) {
677 flags |= FLAG_NR_AR_ATTACK;
680 bool setEmulatorMem = arg_get_lit(ctx, 5);
681 bool verbose = arg_get_lit(ctx, 6);
683 CLIParserFree(ctx);
685 sector_t *k_sector = NULL;
686 uint8_t k_sectorsCount = 40;
688 if (useUIDfromEML) {
689 flags |= FLAG_UID_IN_EMUL;
692 struct {
693 uint8_t tagtype;
694 uint8_t flags;
695 uint8_t uid[10];
696 uint8_t exitAfter;
697 } PACKED payload;
699 payload.tagtype = tagtype;
700 payload.flags = flags;
701 payload.exitAfter = exitAfterNReads;
702 memcpy(payload.uid, uid, uid_len);
704 clearCommandBuffer();
705 SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload));
706 PacketResponseNG resp;
708 PrintAndLogEx(INFO, "Press pm3-button to abort simulation");
709 bool keypress = kbd_enter_pressed();
710 while (!keypress) {
712 if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) continue;
713 if (resp.status != PM3_SUCCESS) break;
715 if ((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK) break;
717 nonces_t *data = (nonces_t *)resp.data.asBytes;
718 readerAttack(k_sector, k_sectorsCount, data[0], setEmulatorMem, verbose);
720 keypress = kbd_enter_pressed();
723 if (keypress && (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
724 // inform device to break the sim loop since client has exited
725 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
728 if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK))
729 showSectorTable(k_sector, k_sectorsCount);
731 PrintAndLogEx(INFO, "Done");
732 return PM3_SUCCESS;
735 int CmdHF14ASniff(const char *Cmd) {
736 CLIParserContext *ctx;
737 CLIParserInit(&ctx, "hf 14a sniff",
738 "Collect data from the field and save into command buffer.\n"
739 "Buffer accessible from command 'hf 14a list'",
740 " hf 14a sniff -c -r");
742 void *argtable[] = {
743 arg_param_begin,
744 arg_lit0("c", "card", "triggered by first data from card"),
745 arg_lit0("r", "reader", "triggered by first 7-bit request from reader (REQ,WUP,...)"),
746 arg_param_end
748 CLIExecWithReturn(ctx, Cmd, argtable, true);
750 uint8_t param = 0;
752 if (arg_get_lit(ctx, 1)) {
753 param |= 0x01;
756 if (arg_get_lit(ctx, 2)) {
757 param |= 0x02;
760 CLIParserFree(ctx);
762 clearCommandBuffer();
763 SendCommandNG(CMD_HF_ISO14443A_SNIFF, (uint8_t *)&param, sizeof(uint8_t));
764 return PM3_SUCCESS;
767 int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode) {
768 static uint8_t responseNum = 0;
769 uint16_t cmdc = 0;
770 *dataoutlen = 0;
772 if (activateField) {
773 PacketResponseNG resp;
774 responseNum = 0;
776 // Anticollision + SELECT card
777 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
778 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
779 if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout.");
780 return 1;
783 // check result
784 if (resp.oldarg[0] == 0) {
785 if (!silentMode) PrintAndLogEx(ERR, "No card in field.");
786 return 1;
789 if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) {
790 if (!silentMode) PrintAndLogEx(ERR, "Card not in iso14443-4. res=%" PRId64 ".", resp.oldarg[0]);
791 return 1;
794 if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
795 // get ATS
796 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
797 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats));
798 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
799 if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout.");
800 return 1;
803 if (resp.oldarg[0] == 0) { // ats_len
804 if (!silentMode) PrintAndLogEx(ERR, "Can't get ATS.");
805 return 1;
810 if (leaveSignalON)
811 cmdc |= ISO14A_NO_DISCONNECT;
813 uint8_t data[PM3_CMD_DATA_SIZE] = { 0x0a | responseNum, 0x00};
814 responseNum ^= 1;
815 memcpy(&data[2], datain, datainlen & 0xFFFF);
816 SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0, data, (datainlen & 0xFFFF) + 2);
818 uint8_t *recv;
819 PacketResponseNG resp;
821 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
822 recv = resp.data.asBytes;
823 int iLen = resp.oldarg[0];
825 if (!iLen) {
826 if (!silentMode) PrintAndLogEx(ERR, "No card response.");
827 return 1;
830 *dataoutlen = iLen - 2;
831 if (*dataoutlen < 0)
832 *dataoutlen = 0;
834 if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
835 if (!silentMode) PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen);
836 return 2;
839 if (recv[0] != data[0]) {
840 if (!silentMode) PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], data[0]);
841 return 2;
844 memcpy(dataout, &recv[2], *dataoutlen);
846 // CRC Check
847 if (iLen == -1) {
848 if (!silentMode) PrintAndLogEx(ERR, "ISO 14443A CRC error.");
849 return 3;
852 } else {
853 if (!silentMode) PrintAndLogEx(ERR, "Reply timeout.");
854 return 4;
857 return 0;
860 int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card) {
862 // global vars should be prefixed with g_
863 g_frame_len = 0;
865 if (card) {
866 memset(card, 0, sizeof(iso14a_card_select_t));
869 DropField();
871 // Anticollision + SELECT card
872 PacketResponseNG resp;
873 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
874 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
875 PrintAndLogEx(WARNING, "Command execute timeout");
876 return PM3_ETIMEOUT;
879 // check result
880 if (resp.oldarg[0] == 0) {
881 if (verbose) {
882 PrintAndLogEx(FAILED, "No card in field");
884 return PM3_ECARDEXCHANGE;
887 if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) {
888 PrintAndLogEx(WARNING, "Card not in iso14443-4, res=%" PRId64 ".", resp.oldarg[0]);
889 return PM3_ECARDEXCHANGE;
892 if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
893 // get ATS
894 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
895 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats));
896 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
897 PrintAndLogEx(WARNING, "Command execute timeout");
898 return PM3_ETIMEOUT;
901 if (resp.oldarg[0] == 0) { // ats_len
902 if (verbose) {
903 PrintAndLogEx(FAILED, "Can't get ATS");
905 return PM3_ECARDEXCHANGE;
908 // get frame length from ATS in data field
909 if (resp.oldarg[0] > 1) {
910 uint8_t fsci = resp.data.asBytes[1] & 0x0f;
911 if (fsci < ARRAYLEN(atsFSC)) {
912 g_frame_len = atsFSC[fsci];
915 } else {
916 // get frame length from ATS in card data structure
917 iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.data.asBytes;
918 if (vcard->ats_len > 1) {
919 uint8_t fsci = vcard->ats[1] & 0x0f;
920 if (fsci < ARRAYLEN(atsFSC)) {
921 g_frame_len = atsFSC[fsci];
925 if (card) {
926 memcpy(card, vcard, sizeof(iso14a_card_select_t));
930 SetISODEPState(ISODEP_NFCA);
932 if (disconnect) {
933 DropField();
936 return PM3_SUCCESS;
939 static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
940 *chainingout = false;
942 if (activateField) {
943 // select with no disconnect and set g_frame_len
944 int selres = SelectCard14443A_4(false, true, NULL);
945 if (selres != PM3_SUCCESS)
946 return selres;
949 uint16_t cmdc = 0;
950 if (chainingin)
951 cmdc = ISO14A_SEND_CHAINING;
953 // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
954 // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size
955 // here length PM3_CMD_DATA_SIZE=512
956 // timeout must be authomatically set by "get ATS"
957 if (datain)
958 SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0x1FF), 0, datain, datainlen & 0x1FF);
959 else
960 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, 0, 0, NULL, 0);
962 PacketResponseNG resp;
964 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
965 uint8_t *recv = resp.data.asBytes;
966 int iLen = resp.oldarg[0];
967 uint8_t res = resp.oldarg[1];
969 int dlen = iLen - 2;
970 if (dlen < 0)
971 dlen = 0;
972 *dataoutlen += dlen;
974 if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
975 PrintAndLogEx(ERR, "APDU: Buffer too small(%d), needs %d bytes", *dataoutlen, maxdataoutlen);
976 return PM3_EAPDU_FAIL;
979 // I-block ACK
980 if ((res & 0xF2) == 0xA2) {
981 *dataoutlen = 0;
982 *chainingout = true;
983 return PM3_SUCCESS;
986 if (!iLen) {
987 PrintAndLogEx(ERR, "APDU: No APDU response");
988 return PM3_EAPDU_FAIL;
991 // check apdu length
992 if (iLen < 2 && iLen >= 0) {
993 PrintAndLogEx(ERR, "APDU: Small APDU response, len %d", iLen);
994 return PM3_EAPDU_FAIL;
997 // check block TODO
998 if (iLen == -2) {
999 PrintAndLogEx(ERR, "APDU: Block type mismatch");
1000 return PM3_EAPDU_FAIL;
1003 memcpy(dataout, recv, dlen);
1005 // chaining
1006 if ((res & 0x10) != 0) {
1007 *chainingout = true;
1010 // CRC Check
1011 if (iLen == -1) {
1012 PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error");
1013 return PM3_EAPDU_FAIL;
1015 } else {
1016 PrintAndLogEx(ERR, "APDU: Reply timeout");
1017 return PM3_EAPDU_FAIL;
1020 return PM3_SUCCESS;
1023 int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) {
1024 *dataoutlen = 0;
1025 bool chaining = false;
1026 int res;
1028 // 3 byte here - 1b framing header, 2b crc16
1029 if (APDUInFramingEnable &&
1030 ((g_frame_len && (datainlen > g_frame_len - 3)) || (datainlen > PM3_CMD_DATA_SIZE - 3))) {
1032 int clen = 0;
1034 bool vActivateField = activateField;
1036 do {
1037 int vlen = MIN(g_frame_len - 3, datainlen - clen);
1038 bool chainBlockNotLast = ((clen + vlen) < datainlen);
1040 *dataoutlen = 0;
1041 res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining);
1042 if (res != PM3_SUCCESS) {
1043 if (leaveSignalON == false)
1044 DropField();
1046 return 200;
1049 // check R-block ACK
1050 //TODO check this one...
1051 if ((*dataoutlen == 0) && (chaining != chainBlockNotLast)) {
1052 if (leaveSignalON == false)
1053 DropField();
1055 return 201;
1058 clen += vlen;
1059 vActivateField = false;
1060 if (*dataoutlen) {
1061 if (clen != datainlen) {
1062 PrintAndLogEx(ERR, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen);
1064 break;
1066 } while (clen < datainlen);
1068 } else {
1069 res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining);
1070 if (res != PM3_SUCCESS) {
1071 if (leaveSignalON == false) {
1072 DropField();
1074 return res;
1078 while (chaining) {
1079 // I-block with chaining
1080 res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining);
1081 if (res != PM3_SUCCESS) {
1082 if (leaveSignalON == false) {
1083 DropField();
1085 return 100;
1089 if (leaveSignalON == false) {
1090 DropField();
1093 return PM3_SUCCESS;
1096 // ISO14443-4. 7. Half-duplex block transmission protocol
1097 static int CmdHF14AAPDU(const char *Cmd) {
1098 uint8_t data[PM3_CMD_DATA_SIZE];
1099 int datalen = 0;
1100 uint8_t header[PM3_CMD_DATA_SIZE];
1101 int headerlen = 0;
1102 bool activateField = false;
1103 bool leaveSignalON = false;
1104 bool decodeTLV = false;
1105 bool decodeAPDU = false;
1106 bool makeAPDU = false;
1107 bool extendedAPDU = false;
1108 int le = 0;
1110 CLIParserContext *ctx;
1111 CLIParserInit(&ctx, "hf 14a apdu",
1112 "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
1113 "hf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"
1114 "hf 14a apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
1115 "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n"
1116 "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n");
1118 void *argtable[] = {
1119 arg_param_begin,
1120 arg_lit0("s", "select", "activate field and select card"),
1121 arg_lit0("k", "keep", "keep signal field ON after receive"),
1122 arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
1123 arg_lit0("d", "decapdu", "decode apdu request if it possible"),
1124 arg_str0("m", "make", "<head (CLA INS P1 P2) hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
1125 arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
1126 arg_int0("l", "le", "<Le (int)>", "Le apdu parameter if `m` parameter included"),
1127 arg_strx1(NULL, NULL, "<APDU (hex) | data (hex)>", "data if `m` parameter included"),
1128 arg_param_end
1130 CLIExecWithReturn(ctx, Cmd, argtable, false);
1132 activateField = arg_get_lit(ctx, 1);
1133 leaveSignalON = arg_get_lit(ctx, 2);
1134 decodeTLV = arg_get_lit(ctx, 3);
1135 decodeAPDU = arg_get_lit(ctx, 4);
1137 CLIGetHexWithReturn(ctx, 5, header, &headerlen);
1138 makeAPDU = headerlen > 0;
1139 if (makeAPDU && headerlen != 4) {
1140 PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen);
1141 CLIParserFree(ctx);
1142 return PM3_EINVARG;
1144 extendedAPDU = arg_get_lit(ctx, 6);
1145 le = arg_get_int_def(ctx, 7, 0);
1147 if (makeAPDU) {
1148 uint8_t apdudata[PM3_CMD_DATA_SIZE] = {0};
1149 int apdudatalen = 0;
1151 CLIGetHexBLessWithReturn(ctx, 8, apdudata, &apdudatalen, 1 + 2);
1153 APDUStruct apdu;
1154 apdu.cla = header[0];
1155 apdu.ins = header[1];
1156 apdu.p1 = header[2];
1157 apdu.p2 = header[3];
1159 apdu.lc = apdudatalen;
1160 apdu.data = apdudata;
1162 apdu.extended_apdu = extendedAPDU;
1163 apdu.le = le;
1165 if (APDUEncode(&apdu, data, &datalen)) {
1166 PrintAndLogEx(ERR, "can't make apdu with provided parameters.");
1167 CLIParserFree(ctx);
1168 return PM3_EINVARG;
1171 } else {
1172 if (extendedAPDU) {
1173 PrintAndLogEx(ERR, "make mode not set but here `e` option.");
1174 CLIParserFree(ctx);
1175 return PM3_EINVARG;
1177 if (le > 0) {
1178 PrintAndLogEx(ERR, "make mode not set but here `l` option.");
1179 CLIParserFree(ctx);
1180 return PM3_EINVARG;
1183 // len = data + PCB(1b) + CRC(2b)
1184 CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2);
1186 CLIParserFree(ctx);
1188 PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )",
1189 activateField ? "select" : "",
1190 leaveSignalON ? ", keep" : "",
1191 decodeTLV ? ", TLV" : ""
1193 PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen));
1195 if (decodeAPDU) {
1196 APDUStruct apdu;
1198 if (APDUDecode(data, datalen, &apdu) == 0)
1199 APDUPrint(apdu);
1200 else
1201 PrintAndLogEx(WARNING, "can't decode APDU.");
1204 int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, PM3_CMD_DATA_SIZE, &datalen);
1205 if (res != PM3_SUCCESS)
1206 return res;
1208 PrintAndLogEx(SUCCESS, "<<< %s | %s", sprint_hex_inrow(data, datalen), sprint_ascii(data, datalen));
1209 PrintAndLogEx(SUCCESS, "<<< status: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1]));
1211 // TLV decoder
1212 if (decodeTLV && datalen > 4) {
1213 TLVPrintFromBuffer(data, datalen - 2);
1216 return PM3_SUCCESS;
1219 static int CmdHF14ACmdRaw(const char *Cmd) {
1220 CLIParserContext *ctx;
1221 CLIParserInit(&ctx, "hf 14a raw",
1222 "Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
1223 "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
1224 "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
1227 void *argtable[] = {
1228 arg_param_begin,
1229 arg_lit0("a", NULL, "active signal field ON without select"),
1230 arg_int0("b", NULL, "<dec>", "number of bits to send. Useful for send partial byte"),
1231 arg_lit0("c", NULL, "calculate and append CRC"),
1232 arg_lit0("k", NULL, "keep signal field ON after receive"),
1233 arg_lit0("3", NULL, "ISO14443-3 select only (skip RATS)"),
1234 arg_lit0("r", NULL, "do not read response"),
1235 arg_lit0("s", NULL, "active signal field ON with select"),
1236 arg_int0("t", "timeout", "<ms>", "timeout in milliseconds"),
1237 arg_lit0("v", "verbose", "Verbose output"),
1238 arg_lit0(NULL, "topaz", "use Topaz protocol to send command"),
1239 arg_strx1(NULL, NULL, "<hex>", "raw bytes to send"),
1240 arg_param_end
1242 CLIExecWithReturn(ctx, Cmd, argtable, false);
1244 bool active = arg_get_lit(ctx, 1);
1245 uint16_t numbits = (uint16_t)arg_get_int_def(ctx, 2, 0);
1246 bool crc = arg_get_lit(ctx, 3);
1247 bool keep_field_on = arg_get_lit(ctx, 4);
1248 bool no_rats = arg_get_lit(ctx, 5);
1249 bool reply = (arg_get_lit(ctx, 6) == false);
1250 bool active_select = arg_get_lit(ctx, 7);
1251 uint32_t timeout = (uint32_t)arg_get_int_def(ctx, 8, 0);
1252 bool verbose = arg_get_lit(ctx, 9);
1253 bool topazmode = arg_get_lit(ctx, 10);
1255 int datalen = 0;
1256 uint8_t data[PM3_CMD_DATA_SIZE];
1257 CLIGetHexWithReturn(ctx, 11, data, &datalen);
1258 CLIParserFree(ctx);
1260 bool bTimeout = (timeout) ? true : false;
1262 // ensure we can add 2byte crc to input data
1263 if (datalen >= sizeof(data) + 2) {
1264 if (crc) {
1265 PrintAndLogEx(FAILED, "Buffer is full, we can't add CRC to your data");
1266 return PM3_EINVARG;
1270 if (crc && datalen > 0 && datalen < sizeof(data) - 2) {
1271 uint8_t first, second;
1272 if (topazmode) {
1273 compute_crc(CRC_14443_B, data, datalen, &first, &second);
1274 } else {
1275 compute_crc(CRC_14443_A, data, datalen, &first, &second);
1277 data[datalen++] = first;
1278 data[datalen++] = second;
1281 uint16_t flags = 0;
1282 if (active || active_select) {
1283 flags |= ISO14A_CONNECT;
1284 if (active)
1285 flags |= ISO14A_NO_SELECT;
1288 uint32_t argtimeout = 0;
1289 if (bTimeout) {
1290 #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
1291 flags |= ISO14A_SET_TIMEOUT;
1292 if (timeout > MAX_TIMEOUT) {
1293 timeout = MAX_TIMEOUT;
1294 PrintAndLogEx(INFO, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response");
1296 argtimeout = 13560000 / 1000 / (8 * 16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
1299 if (keep_field_on) {
1300 flags |= ISO14A_NO_DISCONNECT;
1303 if (datalen > 0) {
1304 flags |= ISO14A_RAW;
1307 if (topazmode) {
1308 flags |= ISO14A_TOPAZMODE;
1310 if (no_rats) {
1311 flags |= ISO14A_NO_RATS;
1314 // Max buffer is PM3_CMD_DATA_SIZE
1315 datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
1317 clearCommandBuffer();
1318 SendCommandOLD(CMD_HF_ISO14443A_READER, flags, (datalen & 0xFFFF) | ((uint32_t)(numbits << 16)), argtimeout, data, datalen & 0xFFFF);
1320 if (reply) {
1321 int res = 0;
1322 if (active_select)
1323 res = waitCmd(true, timeout, verbose);
1324 if (res == PM3_SUCCESS && datalen > 0)
1325 waitCmd(false, timeout, verbose);
1327 return PM3_SUCCESS;
1330 static int waitCmd(bool i_select, uint32_t timeout, bool verbose) {
1331 PacketResponseNG resp;
1333 if (WaitForResponseTimeout(CMD_ACK, &resp, timeout + 1500)) {
1334 uint16_t len = (resp.oldarg[0] & 0xFFFF);
1335 if (i_select) {
1336 len = (resp.oldarg[1] & 0xFFFF);
1337 if (len) {
1338 if (verbose) {
1339 PrintAndLogEx(SUCCESS, "Card selected. UID[%u]:", len);
1340 } else {
1341 return PM3_SUCCESS;
1344 } else {
1345 PrintAndLogEx(WARNING, "Can't select card.");
1347 } else {
1348 if (verbose) {
1349 PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
1353 if (len == 0) {
1354 return PM3_ESOFT;
1357 uint8_t *data = resp.data.asBytes;
1359 if (i_select == false && len >= 3) {
1360 bool crc = check_crc(CRC_14443_A, data, len);
1362 char s[16];
1363 sprintf(s,
1364 (crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"),
1365 data[len - 2],
1366 data[len - 1]
1369 PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s);
1370 } else {
1371 PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
1374 } else {
1375 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
1376 return PM3_ETIMEOUT;
1378 return PM3_SUCCESS;
1381 static int CmdHF14AAntiFuzz(const char *Cmd) {
1383 CLIParserContext *ctx;
1384 CLIParserInit(&ctx, "hf 14a antifuzz",
1385 "Tries to fuzz the ISO14443a anticollision phase",
1386 "hf 14a antifuzz -4\n");
1388 void *argtable[] = {
1389 arg_param_begin,
1390 arg_lit0("4", NULL, "4 byte uid"),
1391 arg_lit0("7", NULL, "7 byte uid"),
1392 arg_lit0(NULL, "10", "10 byte uid"),
1393 arg_param_end
1395 CLIExecWithReturn(ctx, Cmd, argtable, false);
1397 struct {
1398 uint8_t flag;
1399 } PACKED param;
1400 param.flag = FLAG_4B_UID_IN_DATA;
1402 if (arg_get_lit(ctx, 2))
1403 param.flag = FLAG_7B_UID_IN_DATA;
1404 if (arg_get_lit(ctx, 3))
1405 param.flag = FLAG_10B_UID_IN_DATA;
1407 CLIParserFree(ctx);
1408 clearCommandBuffer();
1409 SendCommandNG(CMD_HF_ISO14443A_ANTIFUZZ, (uint8_t *)&param, sizeof(param));
1410 return PM3_SUCCESS;
1413 static int CmdHF14AChaining(const char *Cmd) {
1415 CLIParserContext *ctx;
1416 CLIParserInit(&ctx, "hf 14a chaining",
1417 "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
1418 "hf 14a chaining disable -> disable chaining\n"
1419 "hf 14a chaining -> show chaining enable/disable state\n");
1421 void *argtable[] = {
1422 arg_param_begin,
1423 arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL),
1424 arg_param_end
1426 CLIExecWithReturn(ctx, Cmd, argtable, true);
1428 struct arg_str *str = arg_get_str(ctx, 1);
1429 int len = arg_get_str_len(ctx, 1);
1431 if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1")))
1432 APDUInFramingEnable = true;
1434 if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0")))
1435 APDUInFramingEnable = false;
1437 CLIParserFree(ctx);
1439 PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled");
1441 return PM3_SUCCESS;
1444 static void printTag(const char *tag) {
1445 PrintAndLogEx(SUCCESS, " " _YELLOW_("%s"), tag);
1448 typedef enum {
1449 MTNONE = 0,
1450 MTCLASSIC = 1,
1451 MTMINI = 2,
1452 MTDESFIRE = 4,
1453 MTPLUS = 8,
1454 MTULTRALIGHT = 16,
1455 HID_SEOS = 32,
1456 MTOTHER = 64
1457 } nxp_mifare_type_t;
1459 // Based on NXP AN10833 Rev 3.6 and NXP AN10834 Rev 4.1
1460 static int detect_nxp_card(uint8_t sak, uint16_t atqa, uint64_t select_status) {
1461 int type = MTNONE;
1463 PrintAndLogEx(SUCCESS, "Possible types:");
1465 if ((sak & 0x02) != 0x02) {
1466 if ((sak & 0x19) == 0x19) {
1467 printTag("MIFARE Classic 2K");
1468 type |= MTCLASSIC;
1469 } else if ((sak & 0x38) == 0x38) {
1470 printTag("SmartMX with MIFARE Classic 4K");
1471 type |= MTCLASSIC;
1472 } else if ((sak & 0x18) == 0x18) {
1473 if (select_status == 1) {
1474 if ((atqa & 0x0040) == 0x0040) {
1475 printTag("MIFARE Plus EV1 4K CL2 in SL1");
1476 printTag("MIFARE Plus S 4K CL2 in SL1");
1477 printTag("MIFARE Plus X 4K CL2 in SL1");
1478 } else {
1479 printTag("MIFARE Plus EV1 4K in SL1");
1480 printTag("MIFARE Plus S 4K in SL1");
1481 printTag("MIFARE Plus X 4K in SL1");
1484 type |= MTPLUS;
1485 } else {
1486 if ((atqa & 0x0040) == 0x0040) {
1487 printTag("MIFARE Classic 4K CL2");
1488 } else {
1489 printTag("MIFARE Classic 4K");
1492 type |= MTCLASSIC;
1494 } else if ((sak & 0x09) == 0x09) {
1495 if ((atqa & 0x0040) == 0x0040) {
1496 printTag("MIFARE Mini 0.3K CL2");
1497 } else {
1498 printTag("MIFARE Mini 0.3K");
1501 type |= MTMINI;
1502 } else if ((sak & 0x28) == 0x28) {
1503 printTag("SmartMX with MIFARE Classic 1K");
1504 type |= MTCLASSIC;
1505 } else if ((sak & 0x08) == 0x08) {
1506 if (select_status == 1) {
1507 if ((atqa & 0x0040) == 0x0040) {
1508 printTag("MIFARE Plus EV1 2K CL2 in SL1");
1509 printTag("MIFARE Plus S 2K CL2 in SL1");
1510 printTag("MIFARE Plus X 2K CL2 in SL1");
1511 printTag("MIFARE Plus SE 1K CL2");
1512 } else {
1513 printTag("MIFARE Plus EV1 2K in SL1");
1514 printTag("MIFARE Plus S 2K in SL1");
1515 printTag("MIFARE Plus X 2K in SL1");
1516 printTag("MIFARE Plus SE 1K");
1519 type |= MTPLUS;
1520 } else {
1521 if ((atqa & 0x0040) == 0x0040) {
1522 printTag("MIFARE Classic 1K CL2");
1523 } else {
1524 printTag("MIFARE Classic 1K");
1527 type |= MTCLASSIC;
1529 } else if ((sak & 0x11) == 0x11) {
1530 printTag("MIFARE Plus 4K in SL2");
1531 type |= MTPLUS;
1532 } else if ((sak & 0x10) == 0x10) {
1533 printTag("MIFARE Plus 2K in SL2");
1534 type |= MTPLUS;
1535 } else if ((sak & 0x01) == 0x01) {
1536 printTag("TNP3xxx (TagNPlay, Activision Game Appliance)");
1537 type |= MTCLASSIC;
1538 } else if ((sak & 0x24) == 0x24) {
1539 printTag("MIFARE DESFire CL1");
1540 printTag("MIFARE DESFire EV1 CL1");
1541 type |= MTDESFIRE;
1542 } else if ((sak & 0x20) == 0x20) {
1543 if (select_status == 1) {
1544 if ((atqa & 0x0040) == 0x0040) {
1545 if ((atqa & 0x0300) == 0x0300) {
1546 printTag("MIFARE DESFire CL2");
1547 printTag("MIFARE DESFire EV1 256B/2K/4K/8K CL2");
1548 printTag("MIFARE DESFire EV2 2K/4K/8K/16K/32K");
1549 printTag("MIFARE DESFire EV3 2K/4K/8K");
1550 printTag("MIFARE DESFire Light 640B");
1551 } else {
1552 printTag("MIFARE Plus EV1 2K/4K CL2 in SL3");
1553 printTag("MIFARE Plus S 2K/4K CL2 in SL3");
1554 printTag("MIFARE Plus X 2K/4K CL2 in SL3");
1555 printTag("MIFARE Plus SE 1K CL2");
1556 type |= MTPLUS;
1558 } else {
1560 if ((atqa & 0x0001) == 0x0001) {
1561 printTag("HID SEOS (smartmx / javacard)");
1562 type |= HID_SEOS;
1563 } else {
1564 printTag("MIFARE Plus EV1 2K/4K in SL3");
1565 printTag("MIFARE Plus S 2K/4K in SL3");
1566 printTag("MIFARE Plus X 2K/4K in SL3");
1567 printTag("MIFARE Plus SE 1K");
1568 type |= MTPLUS;
1572 printTag("NTAG 4xx");
1573 type |= MTDESFIRE;
1575 } else if ((sak & 0x04) == 0x04) {
1576 printTag("Any MIFARE CL1");
1577 type |= MTDESFIRE;
1578 } else {
1579 printTag("MIFARE Ultralight");
1580 printTag("MIFARE Ultralight C");
1581 printTag("MIFARE Ultralight EV1");
1582 printTag("MIFARE Ultralight Nano");
1583 printTag("MIFARE Hospitality");
1584 printTag("NTAG 2xx");
1585 type |= MTULTRALIGHT;
1589 if (type == MTNONE) {
1590 PrintAndLogEx(WARNING, " failed to fingerprint");
1592 return type;
1595 typedef struct {
1596 uint8_t uid0;
1597 uint8_t uid1;
1598 const char *desc;
1599 } uid_label_name;
1601 const uid_label_name uid_label_map[] = {
1602 // UID0, UID1, TEXT
1603 {0x02, 0x84, "M24SR64-Y"},
1604 {0x02, 0xA3, "25TA02KB-P"},
1605 {0x02, 0xC4, "25TA64K"},
1606 {0x02, 0xE3, "25TA02KB"},
1607 {0x02, 0xE4, "25TA512B"},
1608 {0x02, 0xF3, "25TA02KB-D"},
1609 {0x11, 0x22, "NTAG21x Modifiable"},
1610 {0x00, 0x00, "None"}
1613 static void getTagLabel(uint8_t uid0, uint8_t uid1) {
1614 int i = 0;
1615 while (uid_label_map[i].uid0 != 0x00) {
1616 if ((uid_label_map[i].uid0 == uid0) && (uid_label_map[i].uid1 == uid1)) {
1617 PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uid_label_map[i].desc);
1618 return;
1620 i += 1;
1624 int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) {
1625 clearCommandBuffer();
1626 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
1627 PacketResponseNG resp;
1628 if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
1629 if (verbose) PrintAndLogEx(WARNING, "iso14443a card select failed");
1630 DropField();
1631 return 0;
1634 iso14a_card_select_t card;
1635 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
1638 0: couldn't read
1639 1: OK, with ATS
1640 2: OK, no ATS
1641 3: proprietary Anticollision
1643 uint64_t select_status = resp.oldarg[0];
1645 if (select_status == 0) {
1646 if (verbose) PrintAndLogEx(WARNING, "iso14443a card select failed");
1647 DropField();
1648 return select_status;
1651 PrintAndLogEx(NORMAL, "");
1653 if (select_status == 3) {
1654 PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision");
1655 PrintAndLogEx(SUCCESS, "ATQA: %02x %02x", card.atqa[1], card.atqa[0]);
1656 DropField();
1657 return select_status;
1660 if (verbose) {
1661 PrintAndLogEx(INFO, "--- " _CYAN_("ISO14443-a Information") "---------------------");
1664 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
1665 PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]);
1666 PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
1668 bool isMifareClassic = true;
1669 bool isMifareDESFire = false;
1670 bool isMifarePlus = false;
1671 bool isMifareUltralight = false;
1672 bool isST = false;
1673 bool isEMV = false;
1674 int nxptype = MTNONE;
1676 if (card.uidlen <= 4) {
1677 nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
1679 isMifareClassic = ((nxptype & MTCLASSIC) == MTCLASSIC);
1680 isMifareDESFire = ((nxptype & MTDESFIRE) == MTDESFIRE);
1681 isMifarePlus = ((nxptype & MTPLUS) == MTPLUS);
1682 isMifareUltralight = ((nxptype & MTULTRALIGHT) == MTULTRALIGHT);
1684 if ((nxptype & MTOTHER) == MTOTHER)
1685 isMifareClassic = true;
1687 } else {
1689 // Double & triple sized UID, can be mapped to a manufacturer.
1690 PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0]));
1692 switch (card.uid[0]) {
1693 case 0x02: // ST
1694 isST = true;
1695 break;
1696 case 0x04: // NXP
1697 nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0]), select_status);
1699 isMifareClassic = ((nxptype & MTCLASSIC) == MTCLASSIC);
1700 isMifareDESFire = ((nxptype & MTDESFIRE) == MTDESFIRE);
1701 isMifarePlus = ((nxptype & MTPLUS) == MTPLUS);
1702 isMifareUltralight = ((nxptype & MTULTRALIGHT) == MTULTRALIGHT);
1704 if ((nxptype & MTOTHER) == MTOTHER)
1705 isMifareClassic = true;
1707 break;
1708 case 0x05: // Infineon
1709 if ((card.uid[1] & 0xF0) == 0x10) {
1710 printTag("my-d(tm) command set SLE 66R04/16/32P, SLE 66R04/16/32S");
1711 } else if ((card.uid[1] & 0xF0) == 0x20) {
1712 printTag("my-d(tm) command set SLE 66R01/16/32P (Type 2 Tag)");
1713 } else if ((card.uid[1] & 0xF0) == 0x30) {
1714 printTag("my-d(tm) move lean SLE 66R01P/66R01PN");
1715 } else if ((card.uid[1] & 0xF0) == 0x70) {
1716 printTag("my-d(tm) move lean SLE 66R01L");
1718 isMifareUltralight = true;
1719 isMifareClassic = false;
1721 if (card.sak == 0x88) {
1722 printTag("Infineon MIFARE CLASSIC 1K");
1723 isMifareUltralight = false;
1724 isMifareClassic = true;
1726 getTagLabel(card.uid[0], card.uid[1]);
1727 break;
1728 case 0x46:
1729 if (memcmp(card.uid, "FSTN10m", 7) == 0) {
1730 isMifareClassic = false;
1731 printTag("Waveshare NFC-Powered e-Paper 1.54\" (please disregard MANUFACTURER mapping above)");
1733 break;
1734 case 0x57:
1735 if (memcmp(card.uid, "WSDZ10m", 7) == 0) {
1736 isMifareClassic = false;
1737 printTag("Waveshare NFC-Powered e-Paper (please disregard MANUFACTURER mapping above)");
1739 break;
1740 default:
1741 getTagLabel(card.uid[0], card.uid[1]);
1742 switch (card.sak) {
1743 case 0x00: {
1744 isMifareClassic = false;
1746 // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc)
1747 DropField();
1749 uint32_t tagT = GetHF14AMfU_Type();
1750 if (tagT != UL_ERROR) {
1751 ul_print_type(tagT, 0);
1752 isMifareUltralight = true;
1753 printTag("MIFARE Ultralight/C/NTAG Compatible");
1754 } else {
1755 printTag("Possible AZTEK (iso14443a compliant)");
1758 // reconnect for further tests
1759 clearCommandBuffer();
1760 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
1761 WaitForResponse(CMD_ACK, &resp);
1763 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
1765 select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
1767 if (select_status == 0) {
1768 DropField();
1769 return select_status;
1771 break;
1773 case 0x0A: {
1774 printTag("FM11RF005SH (Shanghai Metro)");
1775 break;
1777 case 0x20: {
1778 printTag("JCOP 31/41");
1779 break;
1781 case 0x28: {
1782 printTag("JCOP31 or JCOP41 v2.3.1");
1783 break;
1785 case 0x38: {
1786 printTag("Nokia 6212 or 6131");
1787 break;
1789 case 0x98: {
1790 printTag("Gemplus MPCOS");
1791 break;
1793 default: {
1794 break;
1797 break;
1801 // try to request ATS even if tag claims not to support it
1802 if (select_status == 2) {
1803 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
1804 clearCommandBuffer();
1805 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, sizeof(rats));
1806 WaitForResponse(CMD_ACK, &resp);
1808 memcpy(card.ats, resp.data.asBytes, resp.oldarg[0]);
1809 card.ats_len = resp.oldarg[0]; // note: ats_len includes CRC Bytes
1810 if (card.ats_len > 3)
1811 select_status = 1;
1814 if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
1816 PrintAndLogEx(INFO, "-------------------------- " _CYAN_("ATS") " --------------------------");
1817 bool ta1 = 0, tb1 = 0, tc1 = 0;
1819 if (select_status == 2) {
1820 PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--");
1823 if (card.ats[0] != card.ats_len - 2) {
1824 PrintAndLogEx(WARNING, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len);
1827 PrintAndLogEx(SUCCESS, "ATS: " _YELLOW_("%s")"[ %02x %02x ]", sprint_hex(card.ats, card.ats_len - 2), card.ats[card.ats_len - 1], card.ats[card.ats_len]);
1828 PrintAndLogEx(INFO, " " _YELLOW_("%02x") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]);
1830 if (card.ats[0] > 1) { // there is a format byte (T0)
1831 ta1 = (card.ats[1] & 0x10) == 0x10;
1832 tb1 = (card.ats[1] & 0x20) == 0x20;
1833 tc1 = (card.ats[1] & 0x40) == 0x40;
1834 int16_t fsci = card.ats[1] & 0x0f;
1836 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, "
1837 "TC1 is%s present, FSCI is %d (FSC = %d)",
1838 card.ats[1],
1839 (ta1 ? "" : _RED_(" NOT")),
1840 (tb1 ? "" : _RED_(" NOT")),
1841 (tc1 ? "" : _RED_(" NOT")),
1842 fsci,
1843 fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1
1846 int pos = 2;
1847 if (ta1) {
1848 char dr[16], ds[16];
1849 dr[0] = ds[0] = '\0';
1850 if (card.ats[pos] & 0x10) strcat(ds, "2, ");
1851 if (card.ats[pos] & 0x20) strcat(ds, "4, ");
1852 if (card.ats[pos] & 0x40) strcat(ds, "8, ");
1853 if (card.ats[pos] & 0x01) strcat(dr, "2, ");
1854 if (card.ats[pos] & 0x02) strcat(dr, "4, ");
1855 if (card.ats[pos] & 0x04) strcat(dr, "8, ");
1856 if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
1857 if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
1858 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, "
1859 "DR: [%s], DS: [%s]",
1860 card.ats[pos],
1861 ((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""),
1866 pos++;
1869 if (tb1) {
1870 uint32_t sfgi = card.ats[pos] & 0x0F;
1871 uint32_t fwi = card.ats[pos] >> 4;
1873 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)",
1874 card.ats[pos],
1875 (sfgi),
1876 sfgi ? "" : "(not needed) ",
1877 sfgi ? (1 << 12) << sfgi : 0,
1878 fwi,
1879 (1 << 12) << fwi
1881 pos++;
1884 if (tc1) {
1885 PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported",
1886 card.ats[pos],
1887 (card.ats[pos] & 0x01) ? "" : _RED_(" NOT"),
1888 (card.ats[pos] & 0x02) ? "" : _RED_(" NOT")
1890 pos++;
1893 // ATS - Historial bytes and identify based on it
1894 if (card.ats[0] > pos && card.ats[0] <= card.ats_len - 2) {
1895 char tip[60];
1896 tip[0] = '\0';
1897 if (card.ats[0] - pos >= 7) {
1899 snprintf(tip, sizeof(tip), " ");
1901 if ((card.sak & 0x70) == 0x40) { // and no GetVersion()..
1903 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
1904 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)");
1906 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
1908 if ((card.atqa[0] & 0x02) == 0x02)
1909 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)");
1910 else if ((card.atqa[0] & 0x04) == 0x04)
1911 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)");
1913 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
1914 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
1916 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
1917 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
1920 } else { //SAK B4,5,6
1922 if ((card.sak & 0x20) == 0x20) { // and no GetVersion()..
1925 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
1926 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)");
1927 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
1928 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)");
1929 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) {
1930 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)");
1931 } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) {
1932 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)");
1934 } else {
1935 if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
1936 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)");
1937 } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
1938 snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)");
1944 uint8_t calen = card.ats[0] - pos;
1945 PrintAndLogEx(NORMAL, "");
1946 PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------");
1948 if (card.ats[pos] == 0xC1) {
1949 PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip);
1950 PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type");
1951 PrintAndLogEx(SUCCESS, " %02x.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]);
1952 switch (card.ats[pos + 2] & 0xf0) {
1953 case 0x10:
1954 PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire");
1955 isMifareDESFire = true;
1956 isMifareClassic = false;
1957 isMifarePlus = false;
1958 break;
1959 case 0x20:
1960 PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus");
1961 isMifarePlus = true;
1962 isMifareDESFire = false;
1963 isMifareClassic = false;
1964 break;
1966 switch (card.ats[pos + 2] & 0x0f) {
1967 case 0x00:
1968 PrintAndLogEx(SUCCESS, " x0............... < 1 kByte");
1969 break;
1970 case 0x01:
1971 PrintAndLogEx(SUCCESS, " x1............... 1 kByte");
1972 break;
1973 case 0x02:
1974 PrintAndLogEx(SUCCESS, " x2............... 2 kByte");
1975 break;
1976 case 0x03:
1977 PrintAndLogEx(SUCCESS, " x3............... 4 kByte");
1978 break;
1979 case 0x04:
1980 PrintAndLogEx(SUCCESS, " x4............... 8 kByte");
1981 break;
1983 switch (card.ats[pos + 3] & 0xf0) {
1984 case 0x00:
1985 PrintAndLogEx(SUCCESS, " 0x............ Engineering sample");
1986 break;
1987 case 0x20:
1988 PrintAndLogEx(SUCCESS, " 2x............ Released");
1989 break;
1991 switch (card.ats[pos + 3] & 0x0f) {
1992 case 0x00:
1993 PrintAndLogEx(SUCCESS, " x0............ Generation 1");
1994 break;
1995 case 0x01:
1996 PrintAndLogEx(SUCCESS, " x1............ Generation 2");
1997 break;
1998 case 0x02:
1999 PrintAndLogEx(SUCCESS, " x2............ Generation 3");
2000 break;
2002 switch (card.ats[pos + 4] & 0x0f) {
2003 case 0x00:
2004 PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported");
2005 break;
2006 case 0x01:
2007 PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported");
2008 break;
2009 case 0x0E:
2010 PrintAndLogEx(SUCCESS, " xE......... no VCS command supported");
2011 break;
2013 } else {
2014 PrintAndLogEx(SUCCESS, " %s", sprint_hex_inrow(card.ats + pos, calen));
2018 if (do_aid_search) {
2020 PrintAndLogEx(INFO, "-------------------- " _CYAN_("AID Search") " --------------------");
2022 json_t *root = AIDSearchInit(verbose);
2023 if (root != NULL) {
2024 bool found = false;
2025 bool ActivateField = true;
2026 for (size_t elmindx = 0; elmindx < json_array_size(root); elmindx++) {
2028 if (kbd_enter_pressed()) {
2029 break;
2032 json_t *data = AIDSearchGetElm(root, elmindx);
2033 uint8_t vaid[200] = {0};
2034 int vaidlen = 0;
2035 if (!AIDGetFromElm(data, vaid, sizeof(vaid), &vaidlen) || !vaidlen)
2036 continue;
2038 uint16_t sw = 0;
2039 uint8_t result[1024] = {0};
2040 size_t resultlen = 0;
2041 int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, vaid, vaidlen, result, sizeof(result), &resultlen, &sw);
2042 ActivateField = false;
2043 if (res)
2044 continue;
2046 uint8_t dfname[200] = {0};
2047 size_t dfnamelen = 0;
2048 if (resultlen > 3) {
2049 struct tlvdb *tlv = tlvdb_parse_multi(result, resultlen);
2050 if (tlv) {
2051 // 0x84 Dedicated File (DF) Name
2052 const struct tlv *dfnametlv = tlvdb_get_tlv(tlvdb_find_full(tlv, 0x84));
2053 if (dfnametlv) {
2054 dfnamelen = dfnametlv->len;
2055 memcpy(dfname, dfnametlv->value, dfnamelen);
2057 tlvdb_free(tlv);
2061 if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) {
2062 if (sw == 0x9000) {
2063 if (verbose) PrintAndLogEx(SUCCESS, "Application ( " _GREEN_("ok") " )");
2064 } else {
2065 if (verbose) PrintAndLogEx(WARNING, "Application ( " _RED_("blocked") " )");
2068 PrintAIDDescriptionBuf(root, vaid, vaidlen, verbose);
2070 if (dfnamelen) {
2071 if (dfnamelen == vaidlen) {
2072 if (memcmp(dfname, vaid, vaidlen) == 0) {
2073 if (verbose) PrintAndLogEx(INFO, "(DF) Name found and equal to AID");
2074 } else {
2075 PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
2076 PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
2078 } else {
2079 PrintAndLogEx(INFO, "(DF) Name not equal to AID: %s :", sprint_hex(dfname, dfnamelen));
2080 PrintAIDDescriptionBuf(root, dfname, dfnamelen, verbose);
2082 } else {
2083 if (verbose) PrintAndLogEx(INFO, "(DF) Name not found");
2086 if (verbose) PrintAndLogEx(SUCCESS, "----------------------------------------------------");
2087 found = true;
2088 isEMV = true;
2092 DropField();
2093 if (verbose == false && found)
2094 PrintAndLogEx(INFO, "----------------------------------------------------");
2097 } else {
2098 PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported");
2099 if ((card.sak & 0x20) == 0x20) {
2100 PrintAndLogEx(INFO, "--> SAK incorrectly claims that card supports RATS <--");
2102 if (select_status == 1)
2103 select_status = 2;
2106 int isMagic = 0;
2107 if (isMifareClassic) {
2108 isMagic = detect_mf_magic(true);
2110 if (isMifareUltralight) {
2111 isMagic = (detect_mf_magic(false) == MAGIC_NTAG21X);
2113 if (isMifareClassic) {
2114 int res = detect_classic_static_nonce();
2115 if (res == NONCE_STATIC)
2116 PrintAndLogEx(SUCCESS, "Static nonce: " _YELLOW_("yes"));
2118 if (res == NONCE_FAIL && verbose)
2119 PrintAndLogEx(SUCCESS, "Static nonce: " _RED_("read failed"));
2121 if (res == NONCE_NORMAL) {
2123 // not static
2124 res = detect_classic_prng();
2125 if (res == 1)
2126 PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_("weak"));
2127 else if (res == 0)
2128 PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_("hard"));
2129 else
2130 PrintAndLogEx(FAILED, "Prng detection: " _RED_("fail"));
2132 if (do_nack_test)
2133 detect_classic_nackbug(false);
2136 uint8_t signature[32] = {0};
2137 res = detect_mfc_ev1_signature(signature);
2138 if (res == PM3_SUCCESS) {
2139 mfc_ev1_print_signature(card.uid, card.uidlen, signature, sizeof(signature));
2142 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mf`") " commands");
2145 if (isMifareUltralight)
2146 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`"));
2148 if (isMifarePlus && isMagic == 0 && isEMV == false)
2149 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`"));
2151 if (isMifareDESFire && isMagic == 0 && isEMV == false)
2152 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`"));
2154 if (isST)
2155 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf st info`"));
2157 if (isEMV)
2158 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`emv search -s`"));
2160 PrintAndLogEx(NORMAL, "");
2161 DropField();
2162 return select_status;
2165 int infoHF14A4Applications(bool verbose) {
2166 bool cardFound[ARRAYLEN(hintAIDList)] = {0};
2167 bool ActivateField = true;
2168 int found = 0;
2169 for (int i = 0; i < ARRAYLEN(hintAIDList); i++) {
2170 uint16_t sw = 0;
2171 uint8_t result[1024] = {0};
2172 size_t resultlen = 0;
2173 int res = Iso7816Select(CC_CONTACTLESS, ActivateField, true, (uint8_t *)hintAIDList[i].aid, hintAIDList[i].aid_length, result, sizeof(result), &resultlen, &sw);
2174 ActivateField = false;
2175 if (res)
2176 break;
2178 if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) {
2179 if (!found) {
2180 if (verbose)
2181 PrintAndLogEx(INFO, "----------------- " _CYAN_("Short AID search") " -----------------");
2183 found++;
2185 if (sw == 0x9000) {
2186 if (verbose)
2187 PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " ( " _GREEN_("ok") " )", hintAIDList[i].desc);
2188 cardFound[i] = true;
2189 } else {
2190 if (verbose)
2191 PrintAndLogEx(WARNING, "Application " _CYAN_("%s") " ( " _RED_("blocked") " )", hintAIDList[i].desc);
2196 if (found) {
2197 if (verbose)
2198 PrintAndLogEx(INFO, "---------------------------------------------------");
2199 else
2200 PrintAndLogEx(INFO, "Short AID search:");
2202 if (found >= ARRAYLEN(hintAIDList) - 1) {
2203 PrintAndLogEx(HINT, "Hint: card answers to all AID. It maybe the latest revision of plus/desfire/ultralight card.");
2204 } else {
2205 for (int i = 0; i < ARRAYLEN(hintAIDList); i++) {
2206 if (cardFound[i] && strlen(hintAIDList[i].hint))
2207 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("%s") " commands", hintAIDList[i].hint);
2212 DropField();
2213 return found;
2216 static uint16_t get_sw(uint8_t *d, uint8_t n) {
2217 if (n < 2) {
2218 return 0;
2220 n -= 2;
2221 return d[n] * 0x0100 + d[n + 1];
2224 static uint64_t inc_sw_error_occurence(uint16_t sw, uint64_t all_sw[256][256]) {
2225 uint8_t sw1 = (uint8_t)(sw >> 8);
2226 uint8_t sw2 = (uint8_t)(0xff & sw);
2227 if (sw1 == 0x90 && sw2 == 0x00) {
2228 return 0; // Don't count successes.
2230 if (sw1 == 0x6d && sw2 == 0x00) {
2231 return 0xffffffffffffffffULL; // Always max "Instruction not supported".
2233 return ++all_sw[sw1][sw2];
2236 static int CmdHf14AFindapdu(const char *Cmd) {
2237 // TODO: Option to select AID/File (and skip INS 0xA4).
2238 // TODO: Check all instructions with extended APDUs if the card support it.
2239 // TODO: Option to reset tag before every command.
2240 CLIParserContext *ctx;
2241 CLIParserInit(&ctx, "hf 14a apdufind",
2242 "Enumerate APDU's of ISO7816 protocol to find valid CLS/INS/P1/P2 commands.\n"
2243 "It loops all 256 possible values for each byte.\n"
2244 "The loop oder is INS -> P1/P2 (alternating) -> CLA.\n"
2245 "Tag must be on antenna before running.",
2246 "hf 14a apdufind\n"
2247 "hf 14a apdufind --cla 80\n"
2248 "hf 14a apdufind --cla 80 --error-limit 20 --skip-ins a4 --skip-ins b0 --with-le\n"
2251 void *argtable[] = {
2252 arg_param_begin,
2253 arg_str0("c", "cla", "<hex>", "Start value of CLASS (1 hex byte)"),
2254 arg_str0("i", "ins", "<hex>", "Start value of INSTRUCTION (1 hex byte)"),
2255 arg_str0(NULL, "p1", "<hex>", "Start value of P1 (1 hex byte)"),
2256 arg_str0(NULL, "p2", "<hex>", "Start value of P2 (1 hex byte)"),
2257 arg_u64_0("r", "reset", "<number>", "Minimum secondes before resetting the tag (to prevent timeout issues). Default is 5 minutes"),
2258 arg_u64_0("e", "error-limit", "<number>", "Maximum times an status word other than 0x9000 or 0x6D00 is shown. Default is 512."),
2259 arg_strx0("s", "skip-ins", "<hex>", "Do not test an instructions (can be specifed multiple times)"),
2260 arg_lit0("l", "with-le", "Serach for APDUs with Le=0 (case 2S) as well"),
2261 arg_lit0("v", "verbose", "Verbose output"),
2262 arg_param_end
2264 CLIExecWithReturn(ctx, Cmd, argtable, true);
2266 int cla_len = 0;
2267 uint8_t cla_arg[1] = {0};
2268 CLIGetHexWithReturn(ctx, 1, cla_arg, &cla_len);
2269 int ins_len = 0;
2270 uint8_t ins_arg[1] = {0};
2271 CLIGetHexWithReturn(ctx, 2, ins_arg, &ins_len);
2272 int p1_len = 0;
2273 uint8_t p1_arg[1] = {0};
2274 CLIGetHexWithReturn(ctx, 3, p1_arg, &p1_len);
2275 int p2_len = 0;
2276 uint8_t p2_arg[1] = {0};
2277 CLIGetHexWithReturn(ctx, 4, p2_arg, &p2_len);
2278 uint64_t reset_time = arg_get_u64_def(ctx, 5, 5 * 60);
2279 uint64_t error_limit = arg_get_u64_def(ctx, 6, 512);
2280 int ignore_ins_len = 0;
2281 uint8_t ignore_ins_arg[250] = {0};
2282 CLIGetHexWithReturn(ctx, 7, ignore_ins_arg, &ignore_ins_len);
2283 bool with_le = arg_get_lit(ctx, 8);
2284 bool verbose = arg_get_lit(ctx, 9);
2286 CLIParserFree(ctx);
2288 bool activate_field = true;
2289 bool keep_field_on = true;
2290 uint8_t cla = cla_arg[0];
2291 uint8_t ins = ins_arg[0];
2292 uint8_t p1 = p1_arg[0];
2293 uint8_t p2 = p2_arg[0];
2294 uint8_t response[PM3_CMD_DATA_SIZE];
2295 int response_n = 0;
2296 uint8_t aSELECT_AID[80];
2297 int aSELECT_AID_n = 0;
2299 // Check if the tag reponds to APDUs.
2300 PrintAndLogEx(INFO, "Sending a test APDU (select file command) to check if the tag is responding to APDU");
2301 param_gethex_to_eol("00a404000aa000000440000101000100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
2302 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, true, false, response, sizeof(response), &response_n);
2303 if (res != PM3_SUCCESS) {
2304 PrintAndLogEx(FAILED, "Tag did not respond to a test APDU (select file command). Aborting");
2305 return res;
2307 PrintAndLogEx(SUCCESS, "Got response. Starting the APDU finder [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2308 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
2310 bool inc_p1 = true;
2311 bool skip_ins = false;
2312 uint64_t all_sw[256][256] = { { 0 } };
2313 uint64_t sw_occurences = 0;
2314 uint64_t t_start = msclock();
2315 uint64_t t_last_reset = msclock();
2317 // Enumerate APDUs.
2318 do {
2319 do {
2320 do {
2321 retry_ins:
2322 // Exit (was the Enter key pressed)?
2323 if (kbd_enter_pressed()) {
2324 PrintAndLogEx(INFO, "User interrupted detected. Aborting");
2325 goto out;
2328 // Skip/Ignore this instrctuion?
2329 for (int i = 0; i < ignore_ins_len; i++) {
2330 if (ins == ignore_ins_arg[i]) {
2331 skip_ins = true;
2332 break;
2335 if (skip_ins) {
2336 skip_ins = false;
2337 continue;
2340 if (verbose) {
2341 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2344 // Send APDU without Le (case 1) and with Le = 0 (case 2S), if "with-le" was set.
2345 uint8_t command[5] = {cla, ins, p1, p2, 0x00};
2346 int command_n = 4;
2347 for (int i = 0; i < 1 + with_le; i++) {
2348 // Send APDU.
2349 res = ExchangeAPDU14a(command, command_n + i, activate_field, keep_field_on, response, sizeof(response), &response_n);
2350 if (res != PM3_SUCCESS) {
2351 DropField();
2352 activate_field = true;
2353 goto retry_ins;
2355 uint16_t sw = get_sw(response, response_n);
2356 sw_occurences = inc_sw_error_occurence(sw, all_sw);
2358 // Show response.
2359 if (sw_occurences < error_limit) {
2360 logLevel_t log_level = INFO;
2361 if (sw == 0x9000) {
2362 log_level = SUCCESS;
2364 PrintAndLogEx(log_level, "Got response for APDU \"%s\": %04X (%s)", sprint_hex_inrow(command, command_n + i),
2365 sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2366 if (response_n > 2) {
2367 PrintAndLogEx(SUCCESS, "Response data is: %s | %s", sprint_hex_inrow(response, response_n - 2),
2368 sprint_ascii(response, response_n - 2));
2372 activate_field = false; // Do not reativate the filed until the next reset.
2373 } while (++ins != ins_arg[0]);
2374 // Increment P1/P2 in an alternating fashion.
2375 if (inc_p1) {
2376 p1++;
2377 } else {
2378 p2++;
2380 inc_p1 = !inc_p1;
2381 // Check if re-selecting the card is needed.
2382 uint64_t t_since_last_reset = ((msclock() - t_last_reset) / 1000);
2383 if (t_since_last_reset > reset_time) {
2384 DropField();
2385 activate_field = true;
2386 t_last_reset = msclock();
2387 PrintAndLogEx(INFO, "Last reset was %" PRIu64 " seconds ago. Reseting the tag to prevent timeout issues", t_since_last_reset);
2389 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2390 } while (p1 != p1_arg[0] || p2 != p2_arg[0]);
2391 cla++;
2392 PrintAndLogEx(INFO, "Status: [ CLA " _GREEN_("%02X") " INS " _GREEN_("%02X") " P1 " _GREEN_("%02X") " P2 " _GREEN_("%02X") " ]", cla, ins, p1, p2);
2393 } while (cla != cla_arg[0]);
2395 out:
2396 PrintAndLogEx(SUCCESS, "Runtime: %" PRIu64 " seconds\n", (msclock() - t_start) / 1000);
2397 DropField();
2398 return PM3_SUCCESS;
2401 int CmdHF14ANdefRead(const char *Cmd) {
2402 CLIParserContext *ctx;
2403 CLIParserInit(&ctx, "hf 14a ndefread",
2404 "Read NFC Data Exchange Format (NDEF) file on Type 4 NDEF tag",
2405 "hf 14a ndefread\n");
2407 void *argtable[] = {
2408 arg_param_begin,
2409 arg_param_end
2411 CLIExecWithReturn(ctx, Cmd, argtable, true);
2412 CLIParserFree(ctx);
2414 bool activate_field = true;
2415 bool keep_field_on = true;
2416 uint8_t response[PM3_CMD_DATA_SIZE];
2417 int resplen = 0;
2418 bool backward_compatibility_v1 = false;
2420 // --------------- Select NDEF Tag application ----------------
2421 uint8_t aSELECT_AID[80];
2422 int aSELECT_AID_n = 0;
2423 param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
2424 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
2425 if (res != PM3_SUCCESS) {
2426 DropField();
2427 return res;
2430 if (resplen < 2) {
2431 DropField();
2432 return PM3_ESOFT;
2435 uint16_t sw = get_sw(response, resplen);
2436 if (sw != 0x9000) {
2437 // Try NDEF Type 4 Tag v1.0
2438 param_gethex_to_eol("00a4040007d2760000850100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
2439 res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
2440 if (res != PM3_SUCCESS) {
2441 DropField();
2442 return res;
2444 if (resplen < 2) {
2445 DropField();
2446 return PM3_ESOFT;
2449 sw = get_sw(response, resplen);
2450 if (sw != 0x9000) {
2451 PrintAndLogEx(ERR, "Selecting NDEF aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2452 DropField();
2453 return PM3_ESOFT;
2455 backward_compatibility_v1 = true;
2458 activate_field = false;
2459 keep_field_on = true;
2461 // --------------- CC file reading ----------------
2463 uint8_t aSELECT_FILE_CC[30];
2464 int aSELECT_FILE_CC_n = 0;
2465 if (backward_compatibility_v1) {
2466 param_gethex_to_eol("00a4000002e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
2467 } else {
2468 param_gethex_to_eol("00a4000c02e103", 0, aSELECT_FILE_CC, sizeof(aSELECT_FILE_CC), &aSELECT_FILE_CC_n);
2470 res = ExchangeAPDU14a(aSELECT_FILE_CC, aSELECT_FILE_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
2471 if (res != PM3_SUCCESS) {
2472 DropField();
2473 return res;
2476 sw = get_sw(response, resplen);
2477 if (sw != 0x9000) {
2478 PrintAndLogEx(ERR, "Selecting CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2479 DropField();
2480 return PM3_ESOFT;
2483 uint8_t aREAD_CC[30];
2484 int aREAD_CC_n = 0;
2485 param_gethex_to_eol("00b000000f", 0, aREAD_CC, sizeof(aREAD_CC), &aREAD_CC_n);
2486 res = ExchangeAPDU14a(aREAD_CC, aREAD_CC_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
2487 if (res != PM3_SUCCESS) {
2488 DropField();
2489 return res;
2492 sw = get_sw(response, resplen);
2493 if (sw != 0x9000) {
2494 PrintAndLogEx(ERR, "reading CC file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2495 DropField();
2496 return PM3_ESOFT;
2499 // Parse CC data
2500 uint8_t cc_data[resplen - 2];
2501 memcpy(cc_data, response, sizeof(cc_data));
2502 uint8_t file_id[2] = {cc_data[9], cc_data[10]};
2504 print_type4_cc_info(cc_data, sizeof(cc_data));
2505 uint16_t max_rapdu_size = (cc_data[3] << 8 | cc_data[4]) - 2;
2506 max_rapdu_size = max_rapdu_size < sizeof(response) - 2 ? max_rapdu_size : sizeof(response) - 2;
2508 // --------------- NDEF file reading ----------------
2509 uint8_t aSELECT_FILE_NDEF[30];
2510 int aSELECT_FILE_NDEF_n = 0;
2511 if (backward_compatibility_v1) {
2512 param_gethex_to_eol("00a4000002", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
2513 } else {
2514 param_gethex_to_eol("00a4000c02", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n);
2516 memcpy(aSELECT_FILE_NDEF + aSELECT_FILE_NDEF_n, file_id, sizeof(file_id));
2517 res = ExchangeAPDU14a(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n + sizeof(file_id), activate_field, keep_field_on, response, sizeof(response), &resplen);
2518 if (res != PM3_SUCCESS) {
2519 DropField();
2520 return res;
2523 sw = get_sw(response, resplen);
2524 if (sw != 0x9000) {
2525 PrintAndLogEx(ERR, "Selecting NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2526 DropField();
2527 return PM3_ESOFT;
2530 // read first 2 bytes to get NDEF length
2532 uint8_t aREAD_NDEF[30];
2533 int aREAD_NDEF_n = 0;
2534 param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
2535 res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
2536 if (res != PM3_SUCCESS) {
2537 DropField();
2538 return res;
2541 sw = get_sw(response, resplen);
2542 if (sw != 0x9000) {
2543 PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2544 DropField();
2545 return PM3_ESOFT;
2547 uint16_t ndef_size = (response[0] << 8) + response[1];
2548 uint16_t offset = 2;
2549 uint8_t *ndef_file = calloc(ndef_size, sizeof(uint8_t));
2550 if (ndef_file == NULL) {
2551 PrintAndLogEx(ERR, "Out of memory error in CmdHF14ANdef(). Aborting...\n");
2552 DropField();
2553 return PM3_EMALLOC;
2555 for (uint16_t i = offset; i < ndef_size + offset; i += max_rapdu_size) {
2556 uint16_t segment_size = max_rapdu_size < ndef_size + offset - i ? max_rapdu_size : ndef_size + offset - i;
2557 keep_field_on = i < ndef_size + offset - max_rapdu_size;
2558 aREAD_NDEF_n = 0;
2559 param_gethex_to_eol("00b00000", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n);
2560 aREAD_NDEF[2] = i >> 8;
2561 aREAD_NDEF[3] = i & 0xFF;
2562 aREAD_NDEF[4] = segment_size;
2563 res = ExchangeAPDU14a(aREAD_NDEF, aREAD_NDEF_n + 1, activate_field, keep_field_on, response, sizeof(response), &resplen);
2564 if (res != PM3_SUCCESS) {
2565 DropField();
2566 free(ndef_file);
2567 return res;
2569 sw = get_sw(response, resplen);
2570 if (sw != 0x9000) {
2571 PrintAndLogEx(ERR, "reading NDEF file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
2572 DropField();
2573 free(ndef_file);
2574 return PM3_ESOFT;
2576 if (resplen != segment_size + 2) {
2577 PrintAndLogEx(ERR, "reading NDEF file failed, expected %i bytes, got %i bytes.", segment_size, resplen - 2);
2578 DropField();
2579 free(ndef_file);
2580 return PM3_ESOFT;
2582 memcpy(ndef_file + (i - offset), response, segment_size);
2584 NDEFRecordsDecodeAndPrint(ndef_file, ndef_size);
2585 free(ndef_file);
2586 return PM3_SUCCESS;
2589 static command_t CommandTable[] = {
2590 {"help", CmdHelp, AlwaysAvailable, "This help"},
2591 {"list", CmdHF14AList, AlwaysAvailable, "List ISO 14443-a history"},
2592 {"info", CmdHF14AInfo, IfPm3Iso14443a, "Tag information"},
2593 {"reader", CmdHF14AReader, IfPm3Iso14443a, "Act like an ISO14443-a reader"},
2594 {"ndefread", CmdHF14ANdefRead, IfPm3Iso14443a, "Read an NDEF file from ISO 14443-A Type 4 tag"},
2595 {"cuids", CmdHF14ACUIDs, IfPm3Iso14443a, "Collect n>0 ISO14443-a UIDs in one go"},
2596 {"sim", CmdHF14ASim, IfPm3Iso14443a, "Simulate ISO 14443-a tag"},
2597 {"sniff", CmdHF14ASniff, IfPm3Iso14443a, "sniff ISO 14443-a traffic"},
2598 {"apdu", CmdHF14AAPDU, IfPm3Iso14443a, "Send ISO 14443-4 APDU to tag"},
2599 {"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
2600 {"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
2601 {"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
2602 {"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
2603 {"apdufind", CmdHf14AFindapdu, IfPm3Iso14443a, "Enumerate APDUs - CLA/INS/P1P2"},
2604 {NULL, NULL, NULL, NULL}
2607 static int CmdHelp(const char *Cmd) {
2608 (void)Cmd; // Cmd is not used so far
2609 CmdsHelp(CommandTable);
2610 return PM3_SUCCESS;
2613 int CmdHF14A(const char *Cmd) {
2614 clearCommandBuffer();
2615 return CmdsParse(CommandTable, Cmd);