fix one too small
[RRG-proxmark3.git] / client / src / cmdhfmfu.c
blob10c478c25e22bf93cc87f5e47636d384a39ad03a
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 MIFARE ULTRALIGHT (C) commands
17 //-----------------------------------------------------------------------------
18 #include "cmdhfmfu.h"
19 #include <ctype.h>
20 #include "cmdparser.h"
21 #include "commonutil.h"
22 #include "crypto/libpcrypto.h"
23 #include "des.h"
24 #include "aes.h"
25 #include "cmdhfmf.h"
26 #include "cmdhf14a.h"
27 #include "comms.h"
28 #include "protocols.h"
29 #include "generator.h"
30 #include "nfc/ndef.h"
31 #include "cliparser.h"
32 #include "cmdmain.h"
33 #include "amiibo.h" // amiiboo fcts
34 #include "base64.h"
35 #include "fileutils.h" // saveFile
36 #include "cmdtrace.h" // trace list
37 #include "preferences.h" // setDeviceDebugLevel
39 #define MAX_UL_BLOCKS 0x0F
40 #define MAX_ULC_BLOCKS 0x2F
41 #define MAX_ULEV1a_BLOCKS 0x13
42 #define MAX_ULEV1b_BLOCKS 0x28
43 #define MAX_NTAG_203 0x29
44 #define MAX_NTAG_210 0x13
45 #define MAX_NTAG_212 0x28
46 #define MAX_NTAG_213 0x2C
47 #define MAX_NTAG_215 0x86
48 #define MAX_NTAG_216 0xE6
49 #define MAX_NTAG_I2C_1K 0xE9
50 #define MAX_NTAG_I2C_2K 0xE9
51 #define MAX_MY_D_NFC 0xFF
52 #define MAX_MY_D_MOVE 0x25
53 #define MAX_MY_D_MOVE_LEAN 0x0F
54 #define MAX_UL_NANO_40 0x0A
55 #define MAX_UL_AES 0x37
57 static int CmdHelp(const char *Cmd);
59 static uint8_t default_aes_keys[][16] = {
60 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
61 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
62 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
63 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
64 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
65 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
66 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33
67 { 0x47, 0x45, 0x4D, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x4F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45 }, // gemalto
68 { 0x56, 0x4c, 0x67, 0x56, 0x99, 0x69, 0x64, 0x9f, 0x17, 0xC6, 0xC6, 0x16, 0x01, 0x10, 0x4D, 0xCA } // Virtual Dorma Kaba
71 static uint8_t default_3des_keys[][16] = {
72 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
73 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
74 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
75 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
76 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
77 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
78 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33
79 { 0x47, 0x45, 0x4D, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x4F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45 } // gemalto
82 static uint8_t default_pwd_pack[][4] = {
83 {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default
84 {0x4E, 0x45, 0x78, 0x54}, // NExT
87 static uint64_t UL_TYPES_ARRAY[] = {
88 MFU_TT_UNKNOWN, MFU_TT_UL,
89 MFU_TT_UL_C, MFU_TT_UL_EV1_48,
90 MFU_TT_UL_EV1_128, MFU_TT_NTAG,
91 MFU_TT_NTAG_203, MFU_TT_NTAG_210,
92 MFU_TT_NTAG_212, MFU_TT_NTAG_213,
93 MFU_TT_NTAG_215, MFU_TT_NTAG_216,
94 MFU_TT_MY_D, MFU_TT_MY_D_NFC,
95 MFU_TT_MY_D_MOVE, MFU_TT_MY_D_MOVE_NFC,
96 MFU_TT_MY_D_MOVE_LEAN, MFU_TT_NTAG_I2C_1K,
97 MFU_TT_NTAG_I2C_2K, MFU_TT_NTAG_I2C_1K_PLUS,
98 MFU_TT_NTAG_I2C_2K_PLUS, MFU_TT_FUDAN_UL,
99 MFU_TT_NTAG_213_F, MFU_TT_NTAG_216_F,
100 MFU_TT_UL_EV1, MFU_TT_UL_NANO_40,
101 MFU_TT_NTAG_213_TT, MFU_TT_NTAG_213_C,
102 MFU_TT_MAGIC_1A, MFU_TT_MAGIC_1B,
103 MFU_TT_MAGIC_NTAG, MFU_TT_NTAG_210u,
104 MFU_TT_UL_MAGIC, MFU_TT_UL_C_MAGIC,
105 MFU_TT_UL_AES
108 static uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = {
109 // UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128,
110 MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS,
111 // NTAG, NTAG_203, NTAG_210, NTAG_212,
112 MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212,
113 // NTAG_213, NTAG_215, NTAG_216,
114 MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216,
115 // MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN,
116 MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN,
117 // NTAG_I2C_1K, NTAG_I2C_2K, NTAG_I2C_1K_PLUS, NTAG_I2C_2K_PLUS,
118 MAX_NTAG_I2C_1K, MAX_NTAG_I2C_2K, MAX_NTAG_I2C_1K, MAX_NTAG_I2C_2K,
119 // FUDAN_UL, NTAG_213_F, NTAG_216_F, UL_EV1, UL_NANO_40,
120 MAX_UL_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_ULEV1a_BLOCKS, MAX_UL_NANO_40,
121 // NTAG_213_TT, NTAG_213_C,
122 MAX_NTAG_213, MAX_NTAG_213,
123 // MAGIC_1A, MAGIC_1B, MAGIC_NTAG,
124 MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_NTAG_216,
125 // NTAG_210u, UL_MAGIC, UL_C_MAGIC
126 MAX_NTAG_210, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_UL_AES
129 static const ul_family_t ul_family[] = {
130 {"UL-C", "UL-C", "\x00\x00\x00\x00\x00\x00\x00\x00"},
131 {"UL", "MF0UL1001DUx", "\x00\x04\x03\x01\x00\x00\x0B\x03"},
132 {"UL EV1 48", "MF0UL1101DUx", "\x00\x04\x03\x01\x01\x00\x0B\x03"},
133 {"UL EV1 48", "MF0ULH1101DUx", "\x00\x04\x03\x02\x01\x00\x0B\x03"},
134 {"UL EV1 48", "MF0UL1141DUF", "\x00\x04\x03\x03\x01\x00\x0B\x03"},
135 {"UL EV1 128", "MF0UL2101Dxy", "\x00\x04\x03\x01\x01\x00\x0E\x03"},
136 {"UL EV1 128", "MF0UL2101DUx", "\x00\x04\x03\x02\x01\x00\x0E\x03"},
137 {"UL Ev1 n/a ", "MF0UL3101DUx", "\x00\x04\x03\x01\x01\x00\x11\x03"},
138 {"UL Ev1 n/a", "MF0ULH3101DUx", "\x00\x04\x03\x02\x01\x00\x11\x03"},
139 {"UL Ev1 n/a", "MF0UL5101DUx", "\x00\x04\x03\x01\x01\x00\x13\x03"},
140 {"NTAG 210", "NT2L1011F0DUx", "\x00\x04\x04\x01\x01\x00\x0B\x03"},
141 {"NTAG 210", "NT2H1011G0DUD", "\x00\x04\x04\x02\x01\x00\x0B\x03"},
142 {"NTAG 212", "NT2L1211F0DUx", "\x00\x04\x04\x01\x01\x00\x0E\x03"},
143 {"NTAG 213", "NT2H1311G0DUx", "\x00\x04\x04\x02\x01\x00\x0F\x03"},
144 {"NTAG", "NT2H1411G0DUx", "\x00\x04\x04\x02\x01\x01\x11\x03"},
145 {"NTAG 215", "NT2H1511G0DUx", "\x00\x04\x04\x02\x01\x00\x11\x03"},
146 {"NTAG 215", "NT2H1511F0Dxy", "\x00\x04\x04\x04\x01\x00\x11\x03"},
147 {"NTAG 216", "NT2H1611G0DUx", "\x00\x04\x04\x02\x01\x00\x13\x03"},
148 {"NTAG 213F", "NT2H1311F0Dxy", "\x00\x04\x04\x04\x01\x00\x0F\x03"},
149 {"NTAG 216F", "NT2H1611F0Dxy", "\x00\x04\x04\x04\x01\x00\x13\x03"},
150 {"NTAG 213C", "NT2H1311C1DTL", "\x00\x04\x04\x02\x01\x01\x0F\x03"},
151 {"NTAG 213TT", "NT2H1311TTDUx", "\x00\x04\x04\x02\x03\x00\x0F\x03"},
152 {"NTAG I2C 1k", "NT3H1101W0FHK", "\x00\x04\x04\x05\x02\x00\x13\x03"},
153 {"NTAG I2C 1k", "NT3H1101W0FHK_Variant", "\x00\x04\x04\x05\x02\x01\x13\x03"},
154 {"NTAG I2C 2k", "NT3H1201W0FHK", "\x00\x04\x04\x05\x02\x00\x15\x03"},
155 {"NTAG I2C 2k", "NT3H1201", "\x00\x04\x04\x05\x02\x01\x15\x03"},
156 {"NTAG I2C 1k Plus", "NT3H2111", "\x00\x04\x04\x05\x02\x02\x13\x03"},
157 {"NTAG I2C 2k Plus", "NT3H2211", "\x00\x04\x04\x05\x02\x02\x15\x03"},
158 {"NTAG unk", "nhs", "\x00\x04\x04\x06\x00\x00\x13\x03"},
159 {"UL NANO 40", "MF0UN0001DUx 17pF", "\x00\x04\x03\x01\x02\x00\x0B\x03"},
160 {"UL NANO", "MF0UN1001DUx 17pF", "\x00\x04\x03\x01\x03\x00\x0B\x03"},
161 {"UL NANO 40", "MF0UNH0001DUx 50pF", "\x00\x04\x03\x02\x02\x00\x0B\x03"},
162 {"UL NANO", "MF0UNH1001DUx 50pF", "\x00\x04\x03\x02\x03\x00\x0B\x03"},
163 {"NTAG 210u", "NT2L1001G0DUx", "\x00\x04\x04\x01\x02\x00\x0B\x03"},
164 {"NTAG 210u", "NT2H1001G0DUx", "\x00\x04\x04\x02\x02\x00\x0B\x03"},
165 {"UL EV1 128", "Mikron JSC Russia EV1", "\x00\x34\x21\x01\x01\x00\x0E\x03"},
166 {"NTAG 213", "Shanghai Feiju NTAG", "\x00\x53\x04\x02\x01\x00\x0F\x03"},
167 {"UL AES", "MF0AES2001DUD", "\x00\x04\x03\x01\x04\x00\x0F\x03"},
170 static bool compare_ul_family(uint8_t *d, uint8_t n) {
171 if (d == NULL) {
172 return false;
175 if (n > 8) {
176 n = 8;
179 for (int i = 0; i < ARRAYLEN(ul_family); ++i) {
180 if (memcmp(d, ul_family[i].version, n) == 0) {
181 return true;
184 return false;
187 //------------------------------------
188 // get version nxp product type
189 static const char *getProductTypeStr(uint8_t id) {
190 static char buf[20];
191 memset(buf, 0, sizeof(buf));
193 switch (id) {
194 case 3:
195 return "Ultralight";
196 case 4:
197 return "NTAG";
198 default:
199 snprintf(buf, sizeof(buf), "%02X, unknown", id);
200 return buf;
204 static int ul_print_nxp_silicon_info(uint8_t *card_uid) {
206 if (card_uid[0] != 0x04) {
207 return PM3_SUCCESS;
210 uint8_t uid[7];
211 memcpy(&uid, card_uid, 7);
213 uint16_t waferCoordX = ((uid[6] & 3) << 8) | uid[1];
214 uint16_t waferCoordY = ((uid[6] & 12) << 6) | uid[2];
215 uint32_t waferCounter = (
216 (uid[4] << 5) |
217 ((uid[6] & 0xF0) << 17) |
218 (uid[5] << 13) |
219 (uid[3] >> 3)
221 uint8_t testSite = uid[3] & 7;
223 PrintAndLogEx(NORMAL, "");
224 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Silicon Information"));
225 PrintAndLogEx(INFO, " Wafer Counter: %" PRId32 " ( 0x%02" PRIX32 " )", waferCounter, waferCounter);
226 PrintAndLogEx(INFO, " Wafer Coordinates: x %" PRId16 ", y %" PRId16 " (0x%02" PRIX16 ", 0x%02" PRIX16 ")"
227 , waferCoordX
228 , waferCoordY
229 , waferCoordX
230 , waferCoordY
232 PrintAndLogEx(INFO, " Test Site: %u", testSite);
233 return PM3_SUCCESS;
236 static int get_ulc_3des_key_magic(uint64_t magic_type, uint8_t *key) {
238 mf_readblock_ex_t payload = {
239 .read_cmd = ISO14443A_CMD_READBLOCK,
240 .block_no = 0x2C,
243 if ((magic_type & MFU_TT_MAGIC_1A) == MFU_TT_MAGIC_1A) {
244 payload.wakeup = MF_WAKE_GEN1A;
245 payload.auth_cmd = 0;
246 } else if ((magic_type & MFU_TT_MAGIC_1B) == MFU_TT_MAGIC_1B) {
247 payload.wakeup = MF_WAKE_GEN1B;
248 payload.auth_cmd = 0;
249 } else if ((magic_type & MFU_TT_MAGIC_4) == MFU_TT_MAGIC_4) {
250 payload.wakeup = MF_WAKE_GDM_ALT;
251 payload.auth_cmd = 0;
252 } else if ((magic_type & MFU_TT_MAGIC_NTAG21X) == MFU_TT_MAGIC_NTAG21X) {
253 payload.wakeup = MF_WAKE_WUPA;
254 payload.auth_cmd = 0;
255 } else {
256 payload.wakeup = MF_WAKE_WUPA;
257 payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
260 clearCommandBuffer();
261 SendCommandNG(CMD_HF_MIFARE_READBL_EX, (uint8_t *)&payload, sizeof(payload));
262 PacketResponseNG resp;
263 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL_EX, &resp, 1500) == false) {
264 PrintAndLogEx(WARNING, "command execute timeout");
265 return PM3_ETIMEOUT;
268 if (resp.status == PM3_SUCCESS && resp.length == MFBLOCK_SIZE) {
269 uint8_t *d = resp.data.asBytes;
270 reverse_array(d, 8);
271 reverse_array(d + 8, 8);
272 memcpy(key, d, MFBLOCK_SIZE);
275 return resp.status;
279 The 7 MSBits (=n) code the storage size itself based on 2^n,
280 the LSBit is set to '0' if the size is exactly 2^n
281 and set to '1' if the storage size is between 2^n and 2^(n+1).
283 static const char *getUlev1CardSizeStr(uint8_t fsize) {
285 static char buf[40];
286 memset(buf, 0, sizeof(buf));
288 uint16_t usize = 1 << ((fsize >> 1) + 1);
289 uint16_t lsize = 1 << (fsize >> 1);
291 // is LSB set?
292 if (fsize & 1)
293 snprintf(buf, sizeof(buf), "%02X, (%u <-> %u bytes)", fsize, usize, lsize);
294 else
295 snprintf(buf, sizeof(buf), "%02X, (%u bytes)", fsize, lsize);
296 return buf;
299 int ul_read_uid(uint8_t *uid) {
300 if (uid == NULL) {
301 PrintAndLogEx(WARNING, "NUll parameter UID");
302 return PM3_ESOFT;
304 // read uid from tag
305 clearCommandBuffer();
306 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
307 PacketResponseNG resp;
308 WaitForResponse(CMD_ACK, &resp);
309 iso14a_card_select_t card;
310 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
312 uint64_t select_status = resp.oldarg[0];
313 // 0: couldn't read
314 // 1: OK with ATS
315 // 2: OK, no ATS
316 // 3: proprietary Anticollision
317 if (select_status == 0) {
318 PrintAndLogEx(DEBUG, "iso14443a card select failed");
319 return PM3_ESOFT;
321 memcpy(uid, card.uid, 7);
323 if (card.uidlen != 7) {
324 PrintAndLogEx(WARNING, "Wrong sized UID, expected 7 bytes, got " _RED_("%d"), card.uidlen);
325 return PM3_ELENGTH;
327 return PM3_SUCCESS;
330 static void ul_switch_on_field(void) {
331 clearCommandBuffer();
332 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
335 static int ul_send_cmd_raw(uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength) {
336 clearCommandBuffer();
337 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC | ISO14A_NO_RATS, cmdlen, 0, cmd, cmdlen);
338 PacketResponseNG resp;
339 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
340 return PM3_ETIMEOUT;
343 if (!resp.oldarg[0] && responseLength) {
344 return PM3_EWRONGANSWER;
347 uint16_t resplen = (resp.oldarg[0] < responseLength) ? resp.oldarg[0] : responseLength;
348 memcpy(response, resp.data.asBytes, resplen);
349 return resplen;
352 static bool ul_select(iso14a_card_select_t *card) {
354 ul_switch_on_field();
356 PacketResponseNG resp;
357 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
358 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
359 DropField();
360 return false;
361 } else {
363 uint16_t len = (resp.oldarg[1] & 0xFFFF);
364 if (len == 0) {
365 PrintAndLogEx(DEBUG, "iso14443a card select failed");
366 DropField();
367 return false;
370 if (card) {
371 memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
374 return true;
377 static bool ul_select_rats(iso14a_card_select_t *card) {
379 ul_switch_on_field();
381 PacketResponseNG resp;
382 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
383 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
384 DropField();
385 return false;
386 } else {
388 uint16_t len = (resp.oldarg[1] & 0xFFFF);
389 if (len == 0) {
390 PrintAndLogEx(DEBUG, "iso14443a card select failed");
391 DropField();
392 return false;
395 if (card) {
396 memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
399 if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
400 // get ATS
401 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
402 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats));
403 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
404 PrintAndLogEx(WARNING, "Command execute timeout");
405 return PM3_ETIMEOUT;
409 if (card) {
410 card->ats_len = resp.oldarg[0];
411 memcpy(card->ats, resp.data.asBytes, card->ats_len);
415 return true;
418 // This read command will at least return 16bytes.
419 static int ul_read(uint8_t page, uint8_t *response, uint16_t responseLength) {
421 uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page};
422 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
425 static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) {
427 if (data == NULL) {
428 return PM3_EINVARG;
431 uint8_t cmd[18];
432 memset(cmd, 0x00, sizeof(cmd));
433 datalen = (datalen > 16) ? 16 : datalen;
435 cmd[0] = ISO14443A_CMD_WRITEBLOCK;
436 cmd[1] = page;
437 memcpy(cmd + 2, data, datalen);
439 uint8_t response[1] = {0xFF};
440 ul_send_cmd_raw(cmd, 2 + datalen, response, sizeof(response));
441 // ACK
442 if (response[0] == 0x0a) {
443 return PM3_SUCCESS;
445 // NACK
446 return PM3_EWRONGANSWER;
449 static int ulc_requestAuthentication(uint8_t *nonce, uint16_t nonceLength) {
451 uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00};
452 return ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength);
455 static int ulev1_requestAuthentication(uint8_t *pwd, uint8_t *pack, uint16_t packLength) {
457 uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
458 int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
459 // NACK tables different tags, but between 0-9 is a NEGATIVE response.
460 // ACK == 0xA
461 if (len == 1 && pack[0] <= 0x09) {
462 return PM3_EWRONGANSWER;
464 return len;
468 Default AES key is 00-00h. Both the data and UID one.
469 Data key is 00, UID is 01. Authenticity is 02h
470 Auth is 1A[Key ID][CRC] - AF[RndB] - AF[RndA][RndB'] - 00[RndA']
472 static int ulaes_requestAuthentication(uint8_t *key, uint8_t keyno, bool switch_off_field) {
473 struct p {
474 bool turn_off_field;
475 uint8_t keyno;
476 uint8_t key[16];
477 } PACKED payload;
479 payload.turn_off_field = switch_off_field;
480 payload.keyno = keyno;
481 memcpy(payload.key, key, sizeof(payload.key));
483 clearCommandBuffer();
484 SendCommandNG(CMD_HF_MIFAREULAES_AUTH, (uint8_t *)&payload, sizeof(payload));
485 PacketResponseNG resp;
486 if (WaitForResponseTimeout(CMD_HF_MIFAREULAES_AUTH, &resp, 1500) == false) {
487 return PM3_ETIMEOUT;
489 if (resp.status != PM3_SUCCESS) {
490 return resp.status;
492 return PM3_SUCCESS;
495 static int ulc_authentication(uint8_t *key, bool switch_off_field) {
497 clearCommandBuffer();
498 SendCommandMIX(CMD_HF_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16);
499 PacketResponseNG resp;
500 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
501 return PM3_ETIMEOUT;
503 if (resp.oldarg[0] == 1) {
504 return PM3_SUCCESS;
506 return PM3_ESOFT;
509 static int trace_mfuc_try_key(uint8_t *key, int state, uint8_t (*authdata)[16]) {
510 uint8_t iv[8] = {0};
511 uint8_t RndB[8] = {0};
512 uint8_t RndARndB[16] = {0};
513 uint8_t RndA[8] = {0};
514 mbedtls_des3_context ctx_des3;
515 switch (state) {
516 case 2:
517 mbedtls_des3_set2key_dec(&ctx_des3, key);
518 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
519 8, iv, authdata[0], RndB);
520 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
521 16, iv, authdata[1], RndARndB);
522 if ((memcmp(&RndB[1], &RndARndB[8], 7) == 0) &&
523 (RndB[0] == RndARndB[15])) {
524 return PM3_SUCCESS;
526 break;
527 case 3:
528 if (key == NULL) {// if no key was found
529 return PM3_ESOFT;
531 memcpy(iv, authdata[0], 8);
532 mbedtls_des3_set2key_dec(&ctx_des3, key);
533 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
534 16, iv, authdata[1], RndARndB);
535 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
536 8, iv, authdata[2], RndA);
537 if ((memcmp(&RndARndB[1], RndA, 7) == 0) &&
538 (RndARndB[0] == RndA[7])) {
539 return PM3_SUCCESS;
541 break;
542 default:
543 return PM3_EINVARG;
545 return PM3_ESOFT;
548 int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (*authdata)[16]) {
549 switch (state) {
550 case 2:
551 for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
552 uint8_t *key = default_3des_keys[i];
553 if (trace_mfuc_try_key(key, state, authdata) == PM3_SUCCESS) {
554 *correct_key = key;
555 return PM3_SUCCESS;
558 break;
559 case 3:
560 return trace_mfuc_try_key(*correct_key, state, authdata);
561 break;
562 default:
563 return PM3_EINVARG;
565 return PM3_ESOFT;
568 // param override, means we override hw debug levels.
569 static int try_default_3des_keys(bool override, uint8_t **correct_key) {
571 uint8_t dbg_curr = DBG_NONE;
572 if (override) {
573 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
574 return PM3_ESOFT;
577 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
578 return PM3_ESOFT;
582 int res = PM3_ESOFT;
584 PrintAndLogEx(INFO, "");
585 PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known UL-C 3DES keys"));
587 for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
588 uint8_t *key = default_3des_keys[i];
589 if (ulc_authentication(key, true) == PM3_SUCCESS) {
590 *correct_key = key;
591 res = PM3_SUCCESS;
592 break;
596 if (override) {
597 setDeviceDebugLevel(dbg_curr, false);
599 return res;
602 // param override, means we override hw debug levels.
603 static int try_default_aes_keys(bool override) {
605 uint8_t dbg_curr = DBG_NONE;
606 if (override) {
607 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
608 return PM3_ESOFT;
611 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
612 return PM3_ESOFT;
616 int res = PM3_ESOFT;
618 PrintAndLogEx(NORMAL, "");
619 PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known UL-AES keys"));
621 for (uint8_t i = 0; i < ARRAYLEN(default_aes_keys); ++i) {
622 uint8_t *key = default_aes_keys[i];
624 for (uint8_t keyno = 0; keyno < 3; keyno++) {
626 if (ulaes_requestAuthentication(key, keyno, true) == PM3_SUCCESS) {
628 char keystr[20] = {0};
629 switch (keyno) {
630 case 0:
631 sprintf(keystr, "Data key");
632 break;
633 case 1:
634 sprintf(keystr, "UID key");
635 break;
636 case 2:
637 sprintf(keystr, "Authenticity key");
638 break;
639 default:
640 break;
642 PrintAndLogEx(SUCCESS, "%02X " _YELLOW_("%s") " - %s ( "_GREEN_("ok") " )"
643 , keyno
644 , keystr
645 , sprint_hex_inrow(key, 16)
648 res = PM3_SUCCESS;
653 if (override) {
654 setDeviceDebugLevel(dbg_curr, false);
656 return res;
659 static int ul_auth_select(iso14a_card_select_t *card, uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, uint8_t *pack, uint8_t packSize) {
661 if (hasAuthKey && (tagtype & MFU_TT_UL_C)) {
662 //will select card automatically and close connection on error
663 if (ulc_authentication(authkey, false) != PM3_SUCCESS) {
664 PrintAndLogEx(WARNING, "Authentication Failed UL-C");
665 return PM3_ESOFT;
668 } else {
669 if (ul_select(card) == false) {
670 return PM3_ESOFT;
673 if (hasAuthKey) {
674 if (ulev1_requestAuthentication(authkey, pack, packSize) == PM3_EWRONGANSWER) {
675 DropField();
676 PrintAndLogEx(WARNING, "Authentication Failed UL-EV1/NTAG");
677 return PM3_ESOFT;
681 return PM3_SUCCESS;
684 static int ntagtt_getTamperStatus(uint8_t *response, uint16_t responseLength) {
685 uint8_t cmd[] = {NTAGTT_CMD_READ_TT, 0x00};
686 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
689 static int ulev1_getVersion(uint8_t *response, uint16_t responseLength) {
690 uint8_t cmd[] = {MIFARE_ULEV1_VERSION};
691 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
694 static int ulev1_readCounter(uint8_t counter, uint8_t *response, uint16_t responseLength) {
695 uint8_t cmd[] = {MIFARE_ULEV1_READ_CNT, counter};
696 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
699 static int ulev1_readTearing(uint8_t counter, uint8_t *response, uint16_t responseLength) {
700 uint8_t cmd[] = {MIFARE_ULEV1_CHECKTEAR, counter};
701 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
704 static int ulev1_readSignature(uint8_t *response, uint16_t responseLength) {
705 uint8_t cmd[] = {MIFARE_ULEV1_READSIG, 0x00};
706 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
709 // Fudan check checks for which error is given for a command with incorrect crc
710 // NXP UL chip responds with 01, fudan 00.
711 // other possible checks:
712 // send a0 + crc
713 // UL responds with 00, fudan doesn't respond
714 // or
715 // send a200 + crc
716 // UL doesn't respond, fudan responds with 00
717 // or
718 // send 300000 + crc (read with extra byte(s))
719 // UL responds with read of page 0, fudan doesn't respond.
721 // make sure field is off before calling this function
722 static int ul_fudan_check(void) {
723 iso14a_card_select_t card;
724 if (ul_select(&card) == false) {
725 return MFU_TT_UL_ERROR;
728 uint8_t cmd[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa7}; // wrong crc on purpose, should be 0xa8
729 clearCommandBuffer();
730 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd));
731 PacketResponseNG resp;
732 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
733 return MFU_TT_UL_ERROR;
735 if (resp.oldarg[0] != 1) {
736 return MFU_TT_UL_ERROR;
739 return (resp.data.asBytes[0] == 0)
740 ? MFU_TT_FUDAN_UL : MFU_TT_UL; //if response == 0x00 then Fudan, else Genuine NXP
743 static int ul_print_default(uint8_t *data, uint8_t *real_uid) {
745 uint8_t uid[7];
746 uid[0] = data[0];
747 uid[1] = data[1];
748 uid[2] = data[2];
749 uid[3] = data[4];
750 uid[4] = data[5];
751 uid[5] = data[6];
752 uid[6] = data[7];
753 bool mful_uid_layout = true;
755 if (memcmp(uid, real_uid, 7) != 0) {
756 mful_uid_layout = false;
758 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(real_uid, 7));
759 PrintAndLogEx(SUCCESS, " UID[0]: %02X, %s", real_uid[0], getTagInfo(real_uid[0]));
760 if (real_uid[0] == 0x05 && ((real_uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP
761 uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU
762 switch (chip) {
763 case 0xC2:
764 PrintAndLogEx(SUCCESS, " IC type: SLE 66R04P 770 Bytes");
765 break; //77 pages
766 case 0xC4:
767 PrintAndLogEx(SUCCESS, " IC type: SLE 66R16P 2560 Bytes");
768 break; //256 pages
769 case 0xC6:
770 PrintAndLogEx(SUCCESS, " IC type: SLE 66R32P 5120 Bytes");
771 break; //512 pages /2 sectors
774 if (mful_uid_layout) {
775 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
776 int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
777 if (data[3] == crc0)
778 PrintAndLogEx(SUCCESS, " BCC0: %02X ( " _GREEN_("ok") " )", data[3]);
779 else
780 PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0);
782 int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
783 if (data[8] == crc1)
784 PrintAndLogEx(SUCCESS, " BCC1: %02X ( " _GREEN_("ok") " )", data[8]);
785 else
786 PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1);
787 PrintAndLogEx(SUCCESS, " Internal: %02X ( %s )", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
788 } else {
789 PrintAndLogEx(SUCCESS, "Blocks 0-2: %s", sprint_hex(data + 0, 12));
792 PrintAndLogEx(SUCCESS, " Lock: %s - %s",
793 sprint_hex(data + 10, 2),
794 sprint_bin(data + 10, 2)
797 PrintAndLogEx(SUCCESS, " OTP: " _YELLOW_("%s") " - %s",
798 sprint_hex(data + 12, 4),
799 sprint_bin(data + 12, 4)
801 return PM3_SUCCESS;
804 static int ndef_get_maxsize(const uint8_t *data) {
805 // no NDEF message
806 if (data[0] != 0xE1)
807 return 0;
809 if (data[2] == 0x06)
810 return 48;
811 else if (data[2] == 0x12)
812 return 144;
813 else if (data[2] == 0x3E)
814 return 496;
815 else if (data[2] == 0x6D)
816 return 872;
817 return 0;
820 static int ndef_print_CC(uint8_t *data) {
822 // no NDEF message
823 if (data[0] != 0xE1 && data[0] != 0xF1) {
824 return PM3_ESOFT;
827 //NFC Forum Type 1,2,3,4
829 // 4 has 1.1 (11)
831 // b7, b6 major version
832 // b5, b4 minor version
833 // b3, b2 read
834 // 00 always, 01 rfu, 10 proprietary, 11 rfu
835 // b1, b0 write
836 // 00 always, 01 rfo, 10 proprietary, 11 never
837 uint8_t cc_write = data[1] & 0x03;
838 uint8_t cc_read = (data[1] & 0x0C) >> 2;
839 uint8_t cc_minor = (data[1] & 0x30) >> 4;
840 uint8_t cc_major = (data[1] & 0xC0) >> 6;
842 const char *wStr;
843 switch (cc_write) {
844 case 0:
845 wStr = "Write access granted without any security";
846 break;
847 case 1:
848 wStr = "RFU";
849 break;
850 case 2:
851 wStr = "Proprietary";
852 break;
853 case 3:
854 wStr = "No write access";
855 break;
856 default:
857 wStr = "Unknown";
858 break;
860 const char *rStr;
861 switch (cc_read) {
862 case 0:
863 rStr = "Read access granted without any security";
864 break;
865 case 1:
866 case 3:
867 rStr = "RFU";
868 break;
869 case 2:
870 rStr = "Proprietary";
871 break;
872 default:
873 rStr = "Unknown";
874 break;
878 PrintAndLogEx(NORMAL, "");
879 PrintAndLogEx(INFO, "--- " _CYAN_("NDEF Message"));
880 PrintAndLogEx(SUCCESS, "Capability Container: %s", sprint_hex(data, 4));
881 PrintAndLogEx(SUCCESS, " %02X: NDEF Magic Number", data[0]);
883 // PrintAndLogEx(SUCCESS, " %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0F);
884 PrintAndLogEx(SUCCESS, " %02X: version %d.%d supported by tag", data[1], cc_major, cc_minor);
885 PrintAndLogEx(SUCCESS, " : %s / %s", rStr, wStr);
887 PrintAndLogEx(SUCCESS, " %02X: Physical Memory Size: %d bytes", data[2], data[2] * 8);
888 if (data[2] == 0x06)
889 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 48);
890 else if (data[2] == 0x12)
891 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 144);
892 else if (data[2] == 0x3E)
893 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 496);
894 else if (data[2] == 0x6D)
895 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 872);
897 uint8_t msb3 = (data[3] & 0xE0) >> 5;
898 uint8_t sf = (data[3] & 0x10) >> 4;
899 uint8_t lb = (data[3] & 0x08) >> 3;
900 uint8_t mlrule = (data[3] & 0x06) >> 1;
901 uint8_t mbread = (data[3] & 0x01);
903 PrintAndLogEx(SUCCESS, " %02X: Additional feature information", data[3]);
905 uint8_t bits[8 + 1] = {0};
906 num_to_bytebits(data[3], 8, bits);
907 const char *bs = sprint_bytebits_bin(bits, 8);
909 PrintAndLogEx(SUCCESS, " %s", bs);
910 if (msb3 == 0) {
911 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 0, 3, "RFU"));
912 } else {
913 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_RED, bs, 8, 0, 3, "RFU"));
916 if (sf) {
917 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 3, 1, "Support special frame"));
918 } else {
919 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 3, 1, "Don\'t support special frame"));
922 if (lb) {
923 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 4, 1, "Support lock block"));
924 } else {
925 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 4, 1, "Don\'t support lock block"));
928 if (mlrule == 0) {
929 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "RFU"));
930 } else {
931 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_RED, bs, 8, 5, 2, "RFU"));
934 if (mbread) {
935 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "IC support multiple block reads"));
936 } else {
937 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "IC don\'t support multiple block reads"));
939 return PM3_SUCCESS;
942 int ul_print_type(uint64_t tagtype, uint8_t spaces) {
944 if (spaces > 10) {
945 spaces = 10;
948 char typestr[140];
949 memset(typestr, 0x00, sizeof(typestr));
951 if (tagtype & MFU_TT_UL)
952 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)"), spaces, "");
953 else if (tagtype & MFU_TT_UL_C)
954 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, "");
955 else if (tagtype & MFU_TT_UL_NANO_40)
956 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces, "");
957 else if (tagtype & MFU_TT_UL_EV1_48)
958 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces, "");
959 else if (tagtype & MFU_TT_UL_EV1_128)
960 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces, "");
961 else if (tagtype & MFU_TT_UL_EV1)
962 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces, "");
963 else if (tagtype & MFU_TT_UL_AES)
964 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight AES"), spaces, "");
965 else if (tagtype & MFU_TT_NTAG)
966 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces, "");
967 else if (tagtype & MFU_TT_NTAG_203)
968 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces, "");
969 else if (tagtype & MFU_TT_NTAG_210u)
970 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 210u (micro) 48bytes (NT2L1001G0DU)"), spaces, "");
971 else if (tagtype & MFU_TT_NTAG_210)
972 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces, "");
973 else if (tagtype & MFU_TT_NTAG_212)
974 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces, "");
975 else if (tagtype & MFU_TT_NTAG_213)
976 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, "");
977 else if (tagtype & MFU_TT_NTAG_213_F)
978 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, "");
979 else if (tagtype & MFU_TT_NTAG_213_C)
980 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces, "");
981 else if (tagtype & MFU_TT_NTAG_213_TT)
982 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, "");
983 else if (tagtype & MFU_TT_NTAG_215)
984 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, "");
985 else if (tagtype & MFU_TT_NTAG_216)
986 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces, "");
987 else if (tagtype & MFU_TT_NTAG_216_F)
988 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces, "");
989 else if (tagtype & MFU_TT_NTAG_I2C_1K)
990 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces, "");
991 else if (tagtype & MFU_TT_NTAG_I2C_2K)
992 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces, "");
993 else if (tagtype & MFU_TT_NTAG_I2C_1K_PLUS)
994 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces, "");
995 else if (tagtype & MFU_TT_NTAG_I2C_2K_PLUS)
996 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces, "");
997 else if (tagtype & MFU_TT_MY_D)
998 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces, "");
999 else if (tagtype & MFU_TT_MY_D_NFC)
1000 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces, "");
1001 else if (tagtype & MFU_TT_MY_D_MOVE)
1002 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces, "");
1003 else if (tagtype & MFU_TT_MY_D_MOVE_NFC)
1004 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces, "");
1005 else if (tagtype & MFU_TT_MY_D_MOVE_LEAN)
1006 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, "");
1007 else if (tagtype & MFU_TT_FUDAN_UL)
1008 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces, "");
1009 else
1010 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("Unknown %06" PRIx64), spaces, "", tagtype);
1014 bool ismagic = ((tagtype & MFU_TT_MAGIC) == MFU_TT_MAGIC);
1015 // clear magic flag
1016 tagtype &= ~(MFU_TT_MAGIC);
1018 if (ismagic) {
1019 snprintf(typestr + strlen(typestr), 4, " (");
1022 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_1A) == MFU_TT_MAGIC_1A) ? _GREEN_("Gen 1a") : "");
1023 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_1B) == MFU_TT_MAGIC_1B) ? _GREEN_("Gen 1b") : "");
1024 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_2) == MFU_TT_MAGIC_2) ? _GREEN_("Gen 2 / CUID") : "");
1025 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_4) == MFU_TT_MAGIC_4) ? _GREEN_("USCUID-UL") : "");
1026 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_NTAG) == MFU_TT_MAGIC_NTAG) ? _GREEN_("NTAG CUID") : "");
1027 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_NTAG21X) == MFU_TT_MAGIC_NTAG21X) ? _GREEN_("NTAG21x") : "");
1030 if (ismagic) {
1031 snprintf(typestr + strlen(typestr), 4, " )");
1034 PrintAndLogEx(SUCCESS, "%s", typestr);
1035 return PM3_SUCCESS;
1038 static int ulc_print_3deskey(uint8_t *data) {
1039 PrintAndLogEx(INFO, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data, 4), sprint_ascii(data, 4));
1040 PrintAndLogEx(INFO, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data + 4, 4), sprint_ascii(data + 4, 4));
1041 PrintAndLogEx(INFO, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4));
1042 PrintAndLogEx(INFO, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4));
1043 PrintAndLogEx(INFO, "3des key: " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(data, 16, 8), 16));
1044 return PM3_SUCCESS;
1047 // Only takes 16 bytes of data. Now key data available here
1048 static int ulc_print_configuration(uint8_t *data) {
1050 PrintAndLogEx(NORMAL, "");
1051 PrintAndLogEx(INFO, "--- " _CYAN_("UL-C Configuration") " --------------------------");
1052 PrintAndLogEx(INFO, "Total memory....... " _YELLOW_("%u") " bytes", MAX_ULC_BLOCKS * 4);
1053 PrintAndLogEx(INFO, "Available memory... " _YELLOW_("%u") " bytes", (MAX_ULC_BLOCKS - 4) * 4);
1054 PrintAndLogEx(INFO, "40 / 0x28 | %s - %s Higher lockbits", sprint_hex(data, 4), sprint_bin(data, 2));
1055 PrintAndLogEx(INFO, "41 / 0x29 | %s - %s Counter", sprint_hex(data + 4, 4), sprint_bin(data + 4, 2));
1057 bool validAuth = (data[8] >= 0x03 && data[8] < 0x30);
1058 if (validAuth) {
1059 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 Page " _YELLOW_("%d") "/" _YELLOW_("0x%02X") " and above need authentication"
1060 , sprint_hex(data + 8, 4)
1061 , data[8]
1062 , data[8]
1064 } else {
1065 if (data[8] == 0) {
1066 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 default", sprint_hex(data + 8, 4));
1067 } else if (data[8] == 0x30) {
1068 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 " _GREEN_("unlocked"), sprint_hex(data + 8, 4));
1069 } else {
1070 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 " _RED_("byte is out-of-range"), sprint_hex(data + 8, 4));
1074 PrintAndLogEx(INFO, "43 / 0x2B | %s Auth1 %s",
1075 sprint_hex(data + 12, 4),
1076 (data[12] & 1) ? "write access restricted" : _RED_("R/W access restricted")
1079 return PM3_SUCCESS;
1082 static int ulaes_print_configuration(uint8_t *data, uint8_t start_page) {
1084 PrintAndLogEx(NORMAL, "");
1085 PrintAndLogEx(INFO, "--- " _CYAN_("UL-AES Configuration") " --------------------------");
1087 bool rid_act = (data[0] & 1);
1088 bool sec_msg_act = (data[0] & 2);
1089 bool prot = (data[4] & 0x80);
1090 bool cfglck = (data[4] & 0x40);
1091 bool cnt_inc_en = (data[4] & 8);
1092 bool cnt_rd_en = (data[4] & 4);
1093 uint16_t authlim = (data[6]) | ((data[7] & 0x3) << 8);
1095 PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: %s", start_page, start_page, sprint_hex(data, 4));
1097 PrintAndLogEx(INFO, " - Random ID is %s", (rid_act) ? "enabled" : "disabled");
1098 PrintAndLogEx(INFO, " - Secure messaging is %s", (sec_msg_act) ? "enabled" : "disabled");
1099 if (data[3] < 0x3c) {
1100 PrintAndLogEx(INFO, " - page %d and above need authentication", data[3]);
1101 } else {
1102 PrintAndLogEx(INFO, " - pages don't need authentication");
1104 PrintAndLogEx(INFO, " cfg1 [%u/0x%02X]: %s", start_page + 1, start_page + 1, sprint_hex(data + 4, 4));
1106 if (authlim == 0) {
1107 PrintAndLogEx(INFO, " - " _GREEN_("Unlimited authentication attempts"));
1108 } else {
1109 PrintAndLogEx(INFO, " - Max number of authentication attempts is " _YELLOW_("%d"), authlim);
1111 PrintAndLogEx(INFO, " - %s access requires authentication", prot ? "Read and write" : "Write");
1112 PrintAndLogEx(INFO, " - User configuration is %s", cfglck ? _RED_("locked") : "unlocked");
1113 PrintAndLogEx(INFO, " - Counter 2 increment access %s authentication", cnt_inc_en ? "does not require" : "requires");
1114 PrintAndLogEx(INFO, " - Counter 2 read access %s authentication", cnt_rd_en ? "does not require" : "requires");
1115 return PM3_SUCCESS;
1118 static int ulev1_print_configuration(uint64_t tagtype, uint8_t *data, uint8_t startPage) {
1120 PrintAndLogEx(NORMAL, "");
1121 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Configuration"));
1123 bool strg_mod_en = (data[0] & 2);
1125 uint8_t authlim = (data[4] & 0x07);
1126 bool nfc_cnf_prot_pwd = ((data[4] & 0x08) == 0x08);
1127 bool nfc_cnf_en = ((data[4] & 0x10) == 0x10);
1128 bool cfglck = ((data[4] & 0x40) == 0x40);
1129 bool prot = ((data[4] & 0x80) == 0x80);
1131 uint8_t vctid = data[5];
1133 PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: %s", startPage, startPage, sprint_hex(data, 4));
1135 //NTAG213TT has different ASCII mirroring options and config bytes interpretation from other ulev1 class tags
1136 if (tagtype & MFU_TT_NTAG_213_TT) {
1137 uint8_t mirror_conf = ((data[0] & 0xE0) >> 5);
1138 uint8_t mirror_byte = ((data[0] & 0x18) >> 3);
1139 uint8_t mirror_page = data[2];
1141 switch (mirror_conf) {
1142 case 0:
1143 PrintAndLogEx(INFO, " - no ASCII mirror");
1144 break;
1145 case 1:
1146 PrintAndLogEx(INFO, " - UID ASCII mirror");
1147 break;
1148 case 2:
1149 PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
1150 break;
1151 case 3:
1152 PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
1153 break;
1154 case 4:
1155 PrintAndLogEx(INFO, " - tag tamper ASCII mirror");
1156 break;
1157 case 5:
1158 PrintAndLogEx(INFO, " - UID and tag tamper ASCII mirror");
1159 break;
1160 case 6:
1161 PrintAndLogEx(INFO, " - NFC counter and tag tamper ASCII mirror");
1162 break;
1163 case 7:
1164 PrintAndLogEx(INFO, " - UID, NFC counter, and tag tamper ASCII mirror");
1165 break;
1166 default:
1167 break;
1170 if (mirror_conf) {
1171 uint8_t mirror_user_mem_start_byte = (4 * (mirror_page - 4)) + mirror_byte;
1172 uint8_t bytes_required_for_mirror_data = 0;
1174 switch (mirror_conf) {
1175 case 1:
1176 bytes_required_for_mirror_data = 14;
1177 break;
1178 case 2:
1179 bytes_required_for_mirror_data = 6;
1180 break;
1181 case 3:
1182 bytes_required_for_mirror_data = 8;
1183 break;
1184 case 4:
1185 bytes_required_for_mirror_data = 21;
1186 break;
1187 case 5:
1188 bytes_required_for_mirror_data = 23;
1189 break;
1190 case 6:
1191 bytes_required_for_mirror_data = 15;
1192 break;
1193 case 7:
1194 bytes_required_for_mirror_data = 30;
1195 break;
1196 default:
1197 break;
1199 PrintAndLogEx(INFO, " mirror start page %02X | byte pos %02X - %s"
1200 , mirror_page, mirror_byte
1201 , (mirror_page >= 0x4 && ((mirror_user_mem_start_byte + bytes_required_for_mirror_data) <= 144)) ? _GREEN_("ok") : _YELLOW_("Invalid value")
1205 } else if (tagtype & (MFU_TT_NTAG_213_F | MFU_TT_NTAG_216_F)) {
1206 uint8_t mirror_conf = ((data[0] & 0xC0) >> 6);
1207 uint8_t mirror_byte = (data[0] & 0x30);
1208 bool sleep_en = (data[0] & 0x08);
1209 strg_mod_en = (data[0] & 0x04);
1210 uint8_t fdp_conf = (data[0] & 0x03);
1212 switch (mirror_conf) {
1213 case 0:
1214 PrintAndLogEx(INFO, " - no ASCII mirror");
1215 break;
1216 case 1:
1217 PrintAndLogEx(INFO, " - UID ASCII mirror");
1218 break;
1219 case 2:
1220 PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
1221 break;
1222 case 3:
1223 PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
1224 break;
1225 default:
1226 break;
1229 PrintAndLogEx(INFO, " - SLEEP mode %s", (sleep_en) ? "enabled" : "disabled");
1231 switch (fdp_conf) {
1232 case 0:
1233 PrintAndLogEx(INFO, " - no field detect");
1234 break;
1235 case 1:
1236 PrintAndLogEx(INFO, " - enabled by first State-of-Frame (start of communication)");
1237 break;
1238 case 2:
1239 PrintAndLogEx(INFO, " - enabled by selection of the tag");
1240 break;
1241 case 3:
1242 PrintAndLogEx(INFO, " - enabled by field presence");
1243 break;
1244 default:
1245 break;
1247 // valid mirror start page and byte position within start page.
1248 if (tagtype & MFU_TT_NTAG_213_F) {
1249 switch (mirror_conf) {
1250 case 1:
1251 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x24) ? "OK" : "Invalid value"); break;}
1252 case 2:
1253 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x26) ? "OK" : "Invalid value"); break;}
1254 case 3:
1255 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x22) ? "OK" : "Invalid value"); break;}
1256 default:
1257 break;
1259 } else if (tagtype & MFU_TT_NTAG_216_F) {
1260 switch (mirror_conf) {
1261 case 1:
1262 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0xDE) ? "OK" : "Invalid value"); break;}
1263 case 2:
1264 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0xE0) ? "OK" : "Invalid value"); break;}
1265 case 3:
1266 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0xDC) ? "OK" : "Invalid value"); break;}
1267 default:
1268 break;
1272 PrintAndLogEx(INFO, " - strong modulation mode %s", (strg_mod_en) ? "enabled" : "disabled");
1274 if (data[3] < 0xff)
1275 PrintAndLogEx(INFO, " - page %d and above need authentication", data[3]);
1276 else
1277 PrintAndLogEx(INFO, " - pages don't need authentication");
1279 uint8_t tt_enabled = 0;
1280 uint8_t tt_message[4] = {0x00};
1281 uint8_t tt_msg_resp_len = 0;
1282 uint8_t tt_status_resp[5] = {0x00};
1284 if (tagtype & MFU_TT_NTAG_213_TT) {
1285 tt_enabled = (data[1] & 0x02);
1286 tt_msg_resp_len = ul_read(45, tt_message, 4);
1288 PrintAndLogEx(INFO, " - tamper detection feature is %s"
1289 , (tt_enabled) ? _GREEN_("ENABLED") : "disabled"
1292 switch (data[1] & 0x06) {
1293 case 0x00:
1294 PrintAndLogEx(INFO, " - tamper message is unlocked and read/write enabled");
1295 break;
1296 case 0x02:
1297 PrintAndLogEx(INFO, " - tamper message is reversibly read/write locked in memory while the tamper feature is enabled");
1298 break;
1299 case 0x04:
1300 case 0x06:
1301 PrintAndLogEx(INFO, " - tamper message is permanently read/write locked in memory");
1302 break;
1303 default:
1304 break;
1308 PrintAndLogEx(INFO, " cfg1 [%u/0x%02X]: %s", startPage + 1, startPage + 1, sprint_hex(data + 4, 4));
1309 if (authlim == 0)
1310 PrintAndLogEx(INFO, " - " _GREEN_("Unlimited password attempts"));
1311 else
1312 PrintAndLogEx(INFO, " - Max number of password attempts is " _YELLOW_("%d"), authlim);
1314 PrintAndLogEx(INFO, " - NFC counter %s", (nfc_cnf_en) ? "enabled" : "disabled");
1315 PrintAndLogEx(INFO, " - NFC counter %s", (nfc_cnf_prot_pwd) ? "password protection enabled" : "not protected");
1317 PrintAndLogEx(INFO, " - user configuration %s", cfglck ? "permanently locked" : "writeable");
1318 PrintAndLogEx(INFO, " - %s access is protected with password", prot ? "read and write" : "write");
1319 PrintAndLogEx(INFO, " - %02X, Virtual Card Type Identifier is %sdefault", vctid, (vctid == 0x05) ? "" : "not ");
1320 PrintAndLogEx(INFO, " PWD [%u/0x%02X]: %s- ( cannot be read )", startPage + 2, startPage + 2, sprint_hex(data + 8, 4));
1321 PrintAndLogEx(INFO, " PACK [%u/0x%02X]: %s - ( cannot be read )", startPage + 3, startPage + 3, sprint_hex(data + 12, 2));
1322 PrintAndLogEx(INFO, " RFU [%u/0x%02X]: %s- ( cannot be read )", startPage + 3, startPage + 3, sprint_hex(data + 14, 2));
1324 if (tagtype & MFU_TT_NTAG_213_TT) {
1325 if (data[1] & 0x06) {
1326 PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s- (cannot be read)", sprint_hex(tt_message, tt_msg_resp_len));
1327 PrintAndLogEx(INFO, " - tamper message is masked in memory");
1328 } else {
1329 PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s", sprint_hex(tt_message, tt_msg_resp_len));
1330 PrintAndLogEx(INFO, " - tamper message is %s and is readable/writablbe in memory", sprint_hex(tt_message, tt_msg_resp_len));
1334 //The NTAG213TT only returns meaningful information for the fields below if the tamper feature is enabled
1335 if ((tagtype & MFU_TT_NTAG_213_TT) && tt_enabled) {
1337 int tt_status_len = ntagtt_getTamperStatus(tt_status_resp, 5);
1338 if (tt_status_len != 5) {
1339 PrintAndLogEx(WARNING, "Error sending the READ_TT_STATUS command to tag\n");
1340 return PM3_ESOFT;
1343 PrintAndLogEx(NORMAL, "");
1344 PrintAndLogEx(INFO, "--- " _CYAN_("Tamper Status"));
1345 PrintAndLogEx(INFO, " READ_TT_STATUS: %s", sprint_hex(tt_status_resp, 5));
1347 PrintAndLogEx(INFO, " Tamper status result from this power-up:");
1348 switch (tt_status_resp[4]) {
1349 case 0x43:
1350 PrintAndLogEx(INFO, " - Tamper loop was detcted as closed during this power-up");
1351 break;
1352 case 0x4F:
1353 PrintAndLogEx(INFO, " - Tamper loop was detected as open during this power-up");
1354 break;
1355 case 0x49:
1356 PrintAndLogEx(INFO, " - Tamper loop measurement was not enabled or not valid during this power-up");
1357 break;
1358 default:
1359 break;
1362 PrintAndLogEx(INFO, " Tamper detection permanent memory:");
1363 if ((tt_status_resp[0] | tt_status_resp [1] | tt_status_resp[2] | tt_status_resp[3]) == 0x00)
1365 PrintAndLogEx(INFO, " - Tamper loop has never been detected as open during power-up");
1366 else {
1367 PrintAndLogEx(INFO, " - Tamper loop was detected as open during power-up at least once");
1368 PrintAndLogEx(INFO, " - Tamper message returned by READ_TT_STATUS command: %s", sprint_hex(tt_status_resp, 4));
1371 return PM3_SUCCESS;
1374 static int ulev1_print_counters(void) {
1375 PrintAndLogEx(NORMAL, "");
1376 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counters"));
1377 uint8_t tear[1] = {0};
1378 uint8_t counter[3] = {0, 0, 0};
1379 int len = 0;
1380 for (uint8_t i = 0; i < 3; ++i) {
1381 ulev1_readTearing(i, tear, sizeof(tear));
1382 len = ulev1_readCounter(i, counter, sizeof(counter));
1383 if (len == 3) {
1384 PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
1385 PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
1386 , tear[0]
1387 , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
1391 return len;
1394 static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) {
1396 #define PUBLIC_ECDA_KEYLEN 33
1397 #define PUBLIC_ECDA_192_KEYLEN 49
1398 // known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier)
1399 // ref: AN11350 NTAG 21x Originality Signature Validation
1400 // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
1401 const ecdsa_publickey_t nxp_mfu_public_keys[] = {
1402 {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
1403 {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
1404 {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
1405 {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
1406 {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
1407 {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
1408 {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
1409 {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
1410 {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
1411 {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
1414 // https://www.nxp.com/docs/en/application-note/AN13452.pdf
1415 const ecdsa_publickey_t nxp_mfu_192_public_keys[] = {
1416 {"NXP Ultralight AES", "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"},
1420 uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = {
1421 // UL, NTAG21x and NDEF
1423 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c,
1424 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49,
1425 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39,
1426 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61
1428 // UL EV1
1430 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b,
1431 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8,
1432 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72,
1433 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8
1435 // unknown. Needs identification
1437 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57,
1438 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35,
1439 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2,
1440 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF
1442 // unknown. Needs identification
1444 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE,
1445 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1,
1446 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA,
1447 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC
1449 // manufacturer public key
1451 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61,
1452 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C,
1453 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07,
1454 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2
1456 // MIKRON public key.
1458 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8,
1459 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07,
1460 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7,
1461 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
1465 uint8_t i;
1466 bool is_valid = false;
1467 if (signature_len == 32) {
1468 for (i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) {
1470 int dl = 0;
1471 uint8_t key[PUBLIC_ECDA_KEYLEN] = {0};
1472 param_gethex_to_eol(nxp_mfu_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl);
1474 int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, signature_len, false);
1476 is_valid = (res == 0);
1477 if (is_valid)
1478 break;
1482 bool is_192_valid = false;
1483 if (signature_len == 48) {
1484 for (i = 0; i < ARRAYLEN(nxp_mfu_192_public_keys); i++) {
1485 int dl = 0;
1486 uint8_t key[PUBLIC_ECDA_192_KEYLEN] = {0};
1487 param_gethex_to_eol(nxp_mfu_192_public_keys[i].value, 0, key, PUBLIC_ECDA_192_KEYLEN, &dl);
1489 int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP192R1, key, uid, 7, signature, signature_len, false);
1491 is_192_valid = (res == 0);
1492 if (is_192_valid)
1493 break;
1497 PrintAndLogEx(NORMAL, "");
1498 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
1499 if (is_192_valid) {
1500 PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_192_public_keys[i].desc);
1501 PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_192_public_keys[i].value);
1502 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp192r1");
1503 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
1504 PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )");
1505 return PM3_SUCCESS;
1508 if (is_valid) {
1509 PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_public_keys[i].desc);
1510 PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value);
1511 PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1");
1512 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
1513 PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )");
1514 return PM3_SUCCESS;
1517 PrintAndLogEx(INFO, " Elliptic curve parameters: %s", (signature_len == 48) ? "NID_secp192r1" : "NID_secp128r1");
1518 PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len));
1519 PrintAndLogEx(SUCCESS, " Signature verification ( " _RED_("fail") " )");
1520 return PM3_ESOFT;
1523 static int ulev1_print_version(uint8_t *data) {
1524 PrintAndLogEx(NORMAL, "");
1525 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Version"));
1526 PrintAndLogEx(INFO, " Raw bytes: %s", sprint_hex(data, 8));
1527 PrintAndLogEx(INFO, " Vendor ID: %02X, %s", data[1], getTagInfo(data[1]));
1528 PrintAndLogEx(INFO, " Product type: %s", getProductTypeStr(data[2]));
1529 PrintAndLogEx(INFO, " Product subtype: %02X, %s", data[3], (data[3] == 1) ? "17 pF" : "50pF");
1530 PrintAndLogEx(INFO, " Major version: %02X", data[4]);
1531 PrintAndLogEx(INFO, " Minor version: %02X", data[5]);
1532 PrintAndLogEx(INFO, " Size: %s", getUlev1CardSizeStr(data[6]));
1533 PrintAndLogEx(INFO, " Protocol type: %02X%s", data[7], (data[7] == 0x3) ? ", ISO14443-3 Compliant" : "");
1534 return PM3_SUCCESS;
1537 static int ntag_print_counter(void) {
1538 // NTAG has one counter/tearing. At address 0x02.
1539 PrintAndLogEx(NORMAL, "");
1540 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counter"));
1541 uint8_t tear[1] = {0};
1542 uint8_t counter[3] = {0, 0, 0};
1543 uint16_t len;
1544 len = ulev1_readTearing(0x02, tear, sizeof(tear));
1545 (void)len;
1546 len = ulev1_readCounter(0x02, counter, sizeof(counter));
1547 (void)len;
1548 PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3));
1549 PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
1550 , tear[0]
1551 , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
1553 return len;
1557 static int ulc_magic_test(){
1558 // Magic Ultralight test
1559 // Magic UL-C, by observation,
1560 // 1) it seems to have a static nonce response to 0x1A command.
1561 // 2) the deskey bytes is not-zero:d out on as datasheet states.
1562 // 3) UID - changeable, not only, but pages 0-1-2-3.
1563 // 4) use the ul_magic_test ! magic tags answers specially!
1564 int returnValue = UL_ERROR;
1565 iso14a_card_select_t card;
1566 uint8_t nonce1[11] = {0x00};
1567 uint8_t nonce2[11] = {0x00};
1568 if ( !ul_select(&card) ){
1569 return MFU_TT_UL_ERROR;
1571 int status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
1572 if ( status <= 0 ) {
1573 status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
1574 returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? MFU_TT_UL_C_MAGIC : MFU_TT_UL_C;
1575 } else {
1576 returnValue = MFU_TT_UL;
1578 DropField();
1579 return returnValue;
1582 static uint64_t ul_magic_test(void) {
1583 // Magic Ultralight tests
1584 // 1) take present UID, and try to write it back. OBSOLETE
1585 // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
1587 DropField();
1589 iso14a_card_select_t card;
1590 if (ul_select_rats(&card) == false) {
1591 return MFU_TT_UL_ERROR;
1595 // iceman: how to proper identify RU based UID cards
1596 if (
1597 (memcmp(card.uid, "\xAA\x55\x39", 3) == 0) ||
1598 (memcmp(card.uid, "\xAA\x55\xC3", 3) == 0)
1600 // Ul-5 MFU Ev1 FUID,
1601 return MFU_TT_UL_EV1_MAGIC;
1604 PrintAndLogEx(DEBUG, "%u - %s", card.ats_len, sprint_hex_inrow(card.ats, card.ats_len));
1606 // USCUID-UL cards
1607 if (card.ats_len == 18) {
1609 // USCUID-UL configuration
1610 // https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md#uscuid-ul-configuration-guide
1611 // identify: ATS len 18,
1612 // First 8 bytes can vary depending on setup. next 8 bytes is GET VERSION data and finally 2 byte crc
1614 // \x85\x00\x00\xA0\x0A\x00\x0A\xC3 \x00\x04\x03\x01\x01\x00\x0B\x03 \xZZ\xZZ
1616 // 7AFF - back door enabled
1617 // 8500 -
1618 // if we ignore first 8 bytes we can identify regardless how card is configured
1620 if (compare_ul_family(card.ats + 8, 8)) {
1621 return MFU_TT_MAGIC_4 | MFU_TT_MAGIC;
1625 // Direct write alternative cards
1626 if (card.ats_len == 14) {
1628 // UL-C Direct write
1629 if (memcmp(card.ats, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
1630 return MFU_TT_MAGIC_2 | MFU_TT_UL_C_MAGIC;
1633 // NTAG 213 Direct write
1634 if (memcmp(card.ats, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
1636 // iceman: should this be the same as NTAg21x?!?
1637 return MFU_TT_MAGIC_2 | MFU_TT_MAGIC_NTAG;
1642 int status = ul_comp_write(0, NULL, 0);
1643 DropField();
1644 if (status == PM3_SUCCESS) {
1645 PrintAndLogEx(INFO, "comp write pass");
1646 return MFU_TT_MAGIC_2 | MFU_TT_MAGIC;
1649 // check for GEN1A, GEN1B and NTAG21x
1650 PacketResponseNG resp;
1651 clearCommandBuffer();
1652 uint8_t payload[] = { 0 };
1653 SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload));
1655 uint16_t is_generation = MAGIC_FLAG_NONE;
1656 if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) {
1657 if ((resp.status == PM3_SUCCESS) && resp.length == sizeof(uint16_t)) {
1658 is_generation = resp.data.asDwords[0] & 0xFFFF;
1662 if ((is_generation & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) {
1663 return MFU_TT_MAGIC_1A | MFU_TT_MAGIC;
1666 if ((is_generation & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B) {
1667 return MFU_TT_MAGIC_1B | MFU_TT_MAGIC;
1669 if ((is_generation & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
1670 return MFU_TT_MAGIC_NTAG21X | MFU_TT_MAGIC;
1673 return MFU_TT_UNKNOWN;
1676 static char *mfu_generate_filename(const char *prefix, const char *suffix) {
1677 iso14a_card_select_t card;
1678 if (ul_select(&card) == false) {
1679 PrintAndLogEx(WARNING, "No tag found.");
1680 return NULL;
1683 char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(card.uid) * 2 + 1, sizeof(uint8_t));
1684 strcpy(fptr, prefix);
1685 FillFileNameByUID(fptr, card.uid, suffix, card.uidlen);
1686 return fptr;
1689 // used with the Amiibo dumps loading...
1690 // Not related to 'hf mfu dump'
1691 static int mfu_dump_tag(uint16_t pages, void **pdata, uint16_t *len) {
1693 // read uid
1694 iso14a_card_select_t card;
1695 if (ul_select(&card) == false) {
1696 return PM3_ECARDEXCHANGE;
1699 int res = PM3_SUCCESS;
1700 uint16_t maxbytes = (pages * MFU_BLOCK_SIZE);
1702 *pdata = calloc(maxbytes, sizeof(uint8_t));
1703 if (*pdata == NULL) {
1704 PrintAndLogEx(FAILED, "error, cannot allocate memory");
1705 res = PM3_EMALLOC;
1706 goto out;
1709 // UL_EV1/NTAG auth
1710 uint8_t keytype = 2;
1711 // generate PWD
1712 uint8_t key[4] = {0};
1713 num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
1715 clearCommandBuffer();
1716 SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, key, 4);
1717 PacketResponseNG resp;
1718 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
1719 PrintAndLogEx(WARNING, "Command execute timeout");
1720 free(*pdata);
1721 res = PM3_ETIMEOUT;
1722 goto out;
1725 if (resp.oldarg[0] != 1) {
1726 PrintAndLogEx(WARNING, "Failed reading card");
1727 free(*pdata);
1728 res = PM3_ESOFT;
1729 goto out;
1732 // read all memory
1733 uint32_t startindex = resp.oldarg[2];
1734 uint32_t buffer_size = resp.oldarg[1];
1735 if (buffer_size > maxbytes) {
1736 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
1737 buffer_size = maxbytes;
1740 if (GetFromDevice(BIG_BUF, *pdata, buffer_size, startindex, NULL, 0, NULL, 2500, false) == false) {
1741 PrintAndLogEx(WARNING, "command execution time out");
1742 free(*pdata);
1743 res = PM3_ETIMEOUT;
1744 goto out;
1747 if (len) {
1748 *len = buffer_size;
1751 out:
1752 return res;
1756 Lego Dimensions,
1757 Version: 00 04 04 02 01 00 0F 03
1759 matching bytes:
1760 index 12 ( 3 * 4 )
1761 E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E
1764 typedef struct {
1765 const char *desc;
1766 uint8_t mpos;
1767 uint8_t mlen;
1768 const char *match;
1769 uint32_t (*otp)(const uint8_t *uid);
1770 const char *hint;
1771 } mfu_otp_identify_t;
1773 static mfu_otp_identify_t mfu_otp_ident_table[] = {
1774 { "SALTO Systems card", 12, 4, "534C544F", ul_c_otpgenA, NULL },
1775 { NULL, 0, 0, NULL, NULL, NULL }
1778 static mfu_otp_identify_t *mfu_match_otp_fingerprint(uint8_t *uid, uint8_t *data) {
1779 uint8_t i = 0;
1780 do {
1781 int ml = 0;
1782 uint8_t mtmp[40] = {0};
1784 // static or dynamic created OTP to fingerprint.
1785 if (mfu_otp_ident_table[i].match) {
1786 param_gethex_to_eol(mfu_otp_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml);
1787 } else {
1788 uint32_t otp = mfu_otp_ident_table[i].otp(uid);
1789 num_to_bytes(otp, 4, mtmp);
1792 int min = MIN(mfu_otp_ident_table[i].mlen, 4);
1794 PrintAndLogEx(DEBUG, "uid.... %s", sprint_hex_inrow(uid, 7));
1795 PrintAndLogEx(DEBUG, "calc... %s", sprint_hex_inrow(mtmp, 4));
1796 PrintAndLogEx(DEBUG, "dump... %s", sprint_hex_inrow(data + mfu_otp_ident_table[i].mpos, min));
1798 bool m2 = (memcmp(mtmp, data + mfu_otp_ident_table[i].mpos, min) == 0);
1799 if (m2) {
1800 PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_otp_ident_table[i].desc);
1801 return &mfu_otp_ident_table[i];
1803 } while (mfu_otp_ident_table[++i].desc);
1804 return NULL;
1807 typedef struct {
1808 const char *desc;
1809 const char *version;
1810 uint8_t mpos;
1811 uint8_t mlen;
1812 const char *match;
1813 uint32_t (*Pwd)(const uint8_t *uid);
1814 uint16_t (*Pack)(const uint8_t *uid);
1815 const char *hint;
1816 } mfu_identify_t;
1818 static mfu_identify_t mfu_ident_table[] = {
1820 "Jooki", "0004040201000F03",
1821 12, 32, "E11012000103A00C340329D101255504732E6A6F6F6B692E726F636B732F732F",
1822 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1823 "hf mfu ndefread"
1826 "Lego Dimensions", "0004040201000F03",
1827 12, 18, "E11012000103A00C340313D1010F5402656E",
1828 ul_ev1_pwdgenC, ul_ev1_packgenC,
1829 "hf mfu dump -k %08x"
1832 "Hotwheels", "0004040201000F03",
1833 9, 9, "E110120F",
1834 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1835 "hf mfu dump -k %08x"
1838 "Minecraft Earth", "0004040201000F03",
1839 9, 26, "48F6FFE1101200037C91012C55027069642E6D617474656C2F4167",
1840 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1841 "hf mfu dump -k %08x"
1844 "Snackworld", "0004040101000B03",
1845 9, 7, "483000E1100600",
1846 NULL, NULL,
1847 "hf mfu dump -k"
1850 "Amiibo", "0004040201001103",
1851 9, 9, "480FE0F110FFEEA500",
1852 ul_ev1_pwdgenB, ul_ev1_packgenB,
1853 "hf mfu dump -k %08x"
1856 "Amiibo - Power Up band", "0004040502021303",
1857 8, 10, "44000FE0F110FFEEA500",
1858 ul_ev1_pwdgenB, ul_ev1_packgenB,
1859 "hf mfu dump -k %08x"
1863 "Xiaomi AIR Purifier", "0004040201000F03",
1864 0, 0, "",
1865 ul_ev1_pwdgenE, ul_ev1_packgenE,
1866 "hf mfu dump -k %08x"
1870 "Philips Toothbrush", "0004040201010F03",
1871 16, 20, "0310D1010C55027068696C6970732E636F6DFE00",
1872 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1873 "hf mfu pwdgen -r"
1876 "Philips Toothbrush", "0004040201010F03",
1877 16, 36, "0320D1011C55027068696C6970732E636F6D2F6E6663627275736868656164746170FE00",
1878 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1879 "hf mfu pwdgen -r"
1882 "Bank Of Archie brothers", "0004030101000B03",
1883 9, 11, "48F6FF0000000036343533",
1884 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1885 NULL
1888 "Art-Dass NFT card", "0004040201000F03",
1889 16, 16, "033ED1013A5504617274646173732E6E",
1890 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1891 NULL
1894 "Bonverde Coffe card", "0004030101000B03",
1895 18, 4, "644B05AA",
1896 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1897 NULL
1899 {NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
1902 static mfu_identify_t *mfu_match_fingerprint(uint8_t *version, uint8_t *data) {
1903 uint8_t i = 0;
1904 do {
1906 int vl = 0;
1907 uint8_t vtmp[10] = {0};
1908 param_gethex_to_eol(mfu_ident_table[i].version, 0, vtmp, sizeof(vtmp), &vl);
1910 bool m1 = (memcmp(vtmp, version, vl) == 0);
1911 if (m1 == false) {
1912 PrintAndLogEx(DEBUG, "(fingerprint) wrong version");
1913 continue;
1916 int ml = 0;
1917 uint8_t mtmp[40] = {0};
1918 param_gethex_to_eol(mfu_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml);
1920 bool m2 = (memcmp(mtmp, data + mfu_ident_table[i].mpos, mfu_ident_table[i].mlen) == 0);
1921 if (m2) {
1922 PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_ident_table[i].desc);
1923 return &mfu_ident_table[i];
1925 } while (mfu_ident_table[++i].desc);
1926 return NULL;
1929 static uint8_t mfu_max_len(void) {
1930 uint8_t n = 0, i = 0;
1931 do {
1932 uint8_t tmp = mfu_ident_table[i].mpos + mfu_ident_table[i].mlen;
1933 if (tmp > n) {
1934 n = tmp;
1936 } while (mfu_ident_table[++i].desc);
1937 return n;
1940 static int mfu_get_version_uid(uint8_t *version, uint8_t *uid) {
1941 iso14a_card_select_t card;
1942 if (ul_select(&card) == false) {
1943 return PM3_ESOFT;
1945 memcpy(uid, card.uid, card.uidlen);
1947 uint8_t v[10] = {0x00};
1948 int len = ulev1_getVersion(v, sizeof(v));
1949 DropField();
1950 if (len != sizeof(v)) {
1951 return PM3_ESOFT;
1954 memcpy(version, v, 8);
1955 return PM3_SUCCESS;
1958 static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, int ak_len) {
1960 uint8_t dbg_curr = DBG_NONE;
1961 uint8_t *data = NULL;
1962 int res = PM3_ESOFT;
1963 PrintAndLogEx(INFO, "");
1964 PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
1965 uint8_t maxbytes = mfu_max_len();
1966 if (maxbytes == 0) {
1967 PrintAndLogEx(ERR, "fingerprint table wrong");
1968 res = PM3_ESOFT;
1969 goto out;
1972 maxbytes = ((maxbytes / MFU_BLOCK_SIZE) + 1) * MFU_BLOCK_SIZE;
1973 data = calloc(maxbytes, sizeof(uint8_t));
1974 if (data == NULL) {
1975 PrintAndLogEx(ERR, "failed to allocate memory");
1976 res = PM3_EMALLOC;
1977 goto out;
1980 uint8_t pages = (maxbytes / MFU_BLOCK_SIZE);
1981 uint8_t keytype = 0;
1983 if (hasAuthKey) {
1984 if (tagtype & MFU_TT_UL_C)
1985 keytype = 1; // UL_C auth
1986 else
1987 keytype = 2; // UL_EV1/NTAG auth
1990 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
1991 res = PM3_ESOFT;
1992 goto out;
1995 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
1996 res = PM3_ESOFT;
1997 goto out;
2000 clearCommandBuffer();
2001 SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, authkey, ak_len);
2002 PacketResponseNG resp;
2003 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
2004 PrintAndLogEx(WARNING, "Command execute timeout");
2005 res = PM3_ETIMEOUT;
2006 goto out;
2009 if (resp.oldarg[0] != 1) {
2010 PrintAndLogEx(WARNING, "Failed reading card");
2011 res = PM3_ESOFT;
2012 goto out;
2015 // read all memory
2016 uint32_t startindex = resp.oldarg[2];
2017 uint32_t buffer_size = resp.oldarg[1];
2019 if (buffer_size > maxbytes) {
2020 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
2021 buffer_size = maxbytes;
2024 if (GetFromDevice(BIG_BUF, data, buffer_size, startindex, NULL, 0, NULL, 2500, false) == false) {
2025 PrintAndLogEx(WARNING, "command execution time out");
2026 res = PM3_ETIMEOUT;
2027 goto out;
2030 uint8_t version[8] = {0};
2031 uint8_t uid[7] = {0};
2032 if (mfu_get_version_uid(version, uid) == PM3_SUCCESS) {
2033 mfu_identify_t *item = mfu_match_fingerprint(version, data);
2034 if (item) {
2035 PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc);
2036 res = PM3_SUCCESS;
2038 if (item->hint) {
2039 if (item->Pwd) {
2040 char s[40] = {0};
2041 snprintf(s, sizeof(s), item->hint, item->Pwd(uid));
2042 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", s);
2043 } else {
2044 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", item->hint);
2050 // OTP checks
2051 mfu_otp_identify_t *item = mfu_match_otp_fingerprint(uid, data);
2052 if (item) {
2053 PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc);
2054 res = PM3_SUCCESS;
2056 if (item->hint) {
2057 if (item->otp) {
2058 char s[40] = {0};
2059 snprintf(s, sizeof(s), item->hint, item->otp(uid));
2060 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", s);
2061 } else {
2062 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", item->hint);
2067 out:
2069 if (res != PM3_SUCCESS) {
2070 PrintAndLogEx(INFO, "n/a");
2073 setDeviceDebugLevel(dbg_curr, false);
2074 free(data);
2075 return res;
2078 static int mfu_write_block(uint8_t *data, uint8_t datalen, bool has_auth_key, bool has_pwd, uint8_t *auth_key_ptr, uint8_t blockno) {
2080 // 4 or 16.
2081 uint8_t cmd[32];
2082 memcpy(cmd, data, datalen);
2084 // 0 - no pwd/key, no authentication
2085 // 1 - 3des key (16 bytes)
2086 // 2 - pwd (4 bytes)
2087 uint8_t keytype = 0;
2088 size_t cmdlen = datalen;
2089 if (has_auth_key) {
2090 keytype = 1;
2091 memcpy(cmd + datalen, auth_key_ptr, 16);
2092 cmdlen += 16;
2093 } else if (has_pwd) {
2094 keytype = 2;
2095 memcpy(cmd + datalen, auth_key_ptr, 4);
2096 cmdlen += 4;
2099 clearCommandBuffer();
2100 if (datalen == 16) {
2101 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockno, keytype, 0, cmd, cmdlen);
2102 } else {
2103 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, keytype, 0, cmd, cmdlen);
2105 PacketResponseNG resp;
2106 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
2107 return PM3_ETIMEOUT;
2110 uint8_t isOK = resp.oldarg[0] & 0xFF;
2111 if (isOK) {
2112 return PM3_SUCCESS;
2114 return PM3_ESOFT;
2117 uint64_t GetHF14AMfU_Type(void) {
2119 uint64_t tagtype = MFU_TT_UNKNOWN;
2120 iso14a_card_select_t card;
2122 if (ul_select(&card) == false)
2123 return MFU_TT_UL_ERROR;
2125 // Ultralight - ATQA / SAK
2126 if (card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00) {
2127 //PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
2128 DropField();
2129 return MFU_TT_UL_ERROR;
2132 if (card.uid[0] != 0x05) {
2134 uint8_t version[10] = {0x00};
2135 int len = ulev1_getVersion(version, sizeof(version));
2136 DropField();
2138 switch (len) {
2139 case 0x0A: {
2141 MF0UL1001DUx 0004030100000B03
2142 MF0UL1101DUx 0004030101000B03
2143 MF0ULH1101DUx 0004030201000B03
2144 MF0UL1141DUF 0004030301000B03
2145 MF0UL2101Dxy 0004030101000E03
2146 MF0UL2101DUx 0004030201000E03
2147 MF0UL3101DUx 0004030101001103
2148 MF0ULH3101DUx 0004030201001103
2149 MF0UL5101DUx 0004030101001303
2150 NT2L1011F0DUx 0004040101000B03
2151 NT2H1011G0DUD 0004040201000B03
2152 NT2L1211F0DUx 0004040101000E03
2153 NT2H1311G0DUx 0004040201000F03
2154 NT2H1311F0Dxy 0004040401000F03
2155 NT2H1411G0DUx 0004040201011103
2156 NT2H1511G0DUx 0004040201001103
2157 NT2H1511F0Dxy 0004040401001103
2158 NT2H1611G0DUx 0004040201001303
2159 NT2H1611F0Dxy 0004040401001303
2160 NT2H1311C1DTL 0004040201010F03
2161 NT2H1311TTDUx 0004040203000F03
2162 NT3H1101W0FHK 0004040502001303
2163 NT3H1201W0FHK 0004040502001503
2164 NT3H1101W0FHK_Variant 0004040502011303
2165 NT3H1201 0004040502011503
2166 NT3H2111 0004040502021303
2167 NT3H2211 0004040502021503
2168 nhs 0004040600001303
2169 MF0UN0001DUx 0004030102000B03
2170 MF0UNH0001DUx 0004030202000B03
2171 MF0UN1001DUx 0004030103000B03
2172 MF0UNH1001DUx 0004030203000B03
2173 NT2L1001G0DUx 0004040102000B03
2174 NT2H1001G0DUx 0004040202000B03
2175 NT2H1311TTDUx 0004040203000F03
2176 Micron UL 0034210101000E03
2177 Feiju NTAG 0053040201000F03
2178 MF0AES2001DUD 0004030104000F03
2181 if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { tagtype = MFU_TT_UL_EV1_48; break; }
2182 else if (memcmp(version, "\x00\x04\x03\x01\x02\x00\x0B", 7) == 0) { tagtype = MFU_TT_UL_NANO_40; break; }
2183 else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { tagtype = MFU_TT_UL_EV1_48; break; }
2184 else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_UL_EV1_128; break; }
2185 else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_UL_EV1_128; break; }
2186 else if (memcmp(version, "\x00\x04\x03\x01\x04\x00\x0F\x03", 8) == 0) { tagtype = MFU_TT_UL_AES; break; }
2187 else if (memcmp(version, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_UL_EV1_128; break; } // Mikron JSC Russia EV1 41 pages tag
2188 else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype = MFU_TT_NTAG_210; break; }
2189 else if (memcmp(version, "\x00\x04\x04\x01\x02\x00\x0B", 7) == 0) { tagtype = MFU_TT_NTAG_210u; break; }
2190 else if (memcmp(version, "\x00\x04\x04\x02\x02\x00\x0B", 7) == 0) { tagtype = MFU_TT_NTAG_210u; break; }
2191 else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_NTAG_212; break; }
2192 else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213; break; }
2193 else if (memcmp(version, "\x00\x53\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213; break; } // Shanghai Feiju Microelectronics Co. Ltd. China (Xiaomi Air Purifier filter)
2194 else if (memcmp(version, "\x00\x04\x04\x02\x01\x01\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213_C; break; }
2195 else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x11", 7) == 0) { tagtype = MFU_TT_NTAG_215; break; }
2196 else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x13", 7) == 0) { tagtype = MFU_TT_NTAG_216; break; }
2197 else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213_F; break; }
2198 else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x13", 7) == 0) { tagtype = MFU_TT_NTAG_216_F; break; }
2199 else if (memcmp(version, "\x00\x04\x04\x02\x03\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213_TT; break; }
2200 else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x13", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_1K; break; }
2201 else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_2K; break; }
2202 else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_1K_PLUS; break; }
2203 else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x15", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_2K_PLUS; break; }
2204 else if (version[2] == 0x04) { tagtype = MFU_TT_NTAG; break; }
2205 else if (version[2] == 0x03) { tagtype = MFU_TT_UL_EV1; }
2206 break;
2208 case 0x01:
2209 tagtype = MFU_TT_UL_C;
2210 break;
2211 case 0x00:
2212 tagtype = MFU_TT_UL;
2213 break;
2214 case PM3_ETIMEOUT:
2215 case PM3_EWRONGANSWER:
2216 tagtype = (MFU_TT_UL | MFU_TT_UL_C | MFU_TT_NTAG_203);
2217 break; // could be UL | UL_C magic tags
2218 default :
2219 tagtype = MFU_TT_UNKNOWN;
2220 break;
2223 // UL vs UL-C vs ntag203 test
2224 if (tagtype & (MFU_TT_UL | MFU_TT_UL_C | MFU_TT_NTAG_203)) {
2225 if (ul_select(&card) == false) {
2226 return MFU_TT_UL_ERROR;
2229 // do UL_C check first...
2230 uint8_t nonce[11] = {0x00};
2231 int status = ulc_requestAuthentication(nonce, sizeof(nonce));
2232 DropField();
2233 if (status > 1) {
2234 tagtype = MFU_TT_UL_C;
2235 } else {
2236 // need to re-select after authentication error
2237 if (ul_select(&card) == false) {
2238 return MFU_TT_UL_ERROR;
2241 uint8_t data[16] = {0x00};
2242 // read page 0x26-0x29 (last valid ntag203 page)
2243 status = ul_read(0x26, data, sizeof(data));
2244 if (status <= 1) {
2245 tagtype = MFU_TT_UL;
2246 } else {
2247 // read page 0x30 (should error if it is a ntag203)
2248 status = ul_read(0x30, data, sizeof(data));
2249 if (status <= 1) {
2250 tagtype = MFU_TT_NTAG_203;
2251 } else {
2252 tagtype = MFU_TT_UNKNOWN;
2255 DropField();
2258 if (tagtype & MFU_TT_UL) {
2259 tagtype = ul_fudan_check();
2260 DropField();
2262 } else {
2263 DropField();
2264 // Infinition MY-D tests Exam high nibble
2265 uint8_t nib = (card.uid[1] & 0xf0) >> 4;
2266 switch (nib) {
2267 // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
2268 case 1:
2269 tagtype = MFU_TT_MY_D;
2270 break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
2271 case 2:
2272 tagtype = MFU_TT_MY_D_NFC;
2273 break; // or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
2274 case 3:
2275 tagtype = (MFU_TT_MY_D_MOVE | MFU_TT_MY_D_MOVE_NFC);
2276 break; // or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
2277 case 7:
2278 tagtype = MFU_TT_MY_D_MOVE_LEAN;
2279 break; // or SLE 66R01L // 16 pages of 4 bytes
2283 tagtype |= ul_magic_test();
2284 if (tagtype == (MFU_TT_UNKNOWN | MFU_TT_MAGIC)) {
2285 tagtype = (MFU_TT_UL_MAGIC);
2288 return tagtype;
2291 // extended tag information
2293 static int CmdHF14AMfUInfo(const char *Cmd) {
2295 CLIParserContext *ctx;
2296 CLIParserInit(&ctx, "hf mfu info",
2297 "Get info about MIFARE Ultralight Family styled tag.\n"
2298 "Sometimes the tags are locked down, and you may need a key to be able to read the information",
2299 "hf mfu info\n"
2300 "hf mfu info -k AABBCCDD\n"
2301 "hf mfu info --key 00112233445566778899AABBCCDDEEFF"
2304 void *argtable[] = {
2305 arg_param_begin,
2306 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2307 arg_lit0("l", NULL, "Swap entered key's endianness"),
2308 // arg_lit0("v", "verbose", "verbose output"),
2309 arg_lit0(NULL, "force", "override `hw dbg` settings"),
2310 arg_param_end
2312 CLIExecWithReturn(ctx, Cmd, argtable, true);
2314 int ak_len = 0;
2315 uint8_t authenticationkey[16] = {0x00};
2316 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
2317 bool swap_endian = arg_get_lit(ctx, 2);
2318 // bool verbose = arg_get_lit(ctx, 3);
2319 bool override = (arg_get_lit(ctx, 3) == false);
2320 CLIParserFree(ctx);
2322 if (ak_len) {
2323 if (ak_len != 16 && ak_len != 4) {
2324 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2325 return PM3_EINVARG;
2329 bool has_auth_key = false;
2330 if (ak_len > 0)
2331 has_auth_key = true;
2333 uint8_t authlim = 0xff;
2334 uint8_t data[16] = {0x00};
2335 iso14a_card_select_t card;
2336 int status;
2337 uint8_t *authkeyptr = authenticationkey;
2338 uint8_t pwd[4] = {0, 0, 0, 0};
2339 uint8_t *key = pwd;
2340 uint8_t pack[4] = {0, 0, 0, 0};
2341 int len;
2343 uint64_t tagtype = GetHF14AMfU_Type();
2344 if (tagtype == MFU_TT_UL_ERROR) {
2345 return PM3_ESOFT;
2348 PrintAndLogEx(NORMAL, "");
2349 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
2350 ul_print_type(tagtype, 6);
2352 // Swap endianness
2353 if (swap_endian && has_auth_key) {
2354 authkeyptr = SwapEndian64(authenticationkey, ak_len, (ak_len == 16) ? 8 : 4);
2357 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2358 return PM3_ESOFT;
2361 bool locked = false;
2362 // read pages 0,1,2,3 (should read 4 pages)
2363 status = ul_read(0, data, sizeof(data));
2364 if (status <= 0) {
2365 DropField();
2366 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
2367 return PM3_ESOFT;
2368 } else if (status == 16) {
2369 ul_print_default(data, card.uid);
2370 ndef_print_CC(data + 12);
2371 } else {
2372 locked = true;
2375 // UL_C Specific
2376 if ((tagtype & MFU_TT_UL_C)) {
2378 // read pages 0x28, 0x29, 0x2A, 0x2B
2379 uint8_t ulc_conf[16] = {0x00};
2380 status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
2381 if (status <= 0) {
2382 PrintAndLogEx(ERR, "Error: tag didn't answer to READ UL-C");
2383 DropField();
2384 return PM3_ESOFT;
2387 if (status == 16) {
2388 ulc_print_configuration(ulc_conf);
2389 } else {
2390 locked = true;
2393 mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
2395 DropField();
2397 if ((tagtype & MFU_TT_MAGIC) == MFU_TT_MAGIC) {
2398 //just read key
2399 uint8_t ulc_deskey[16] = {0x00};
2400 status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
2401 if (status <= 0) {
2402 DropField();
2403 PrintAndLogEx(ERR, "Error: tag didn't answer to READ magic");
2404 return PM3_ESOFT;
2407 if (status == 16) {
2408 ulc_print_3deskey(ulc_deskey);
2411 PrintAndLogEx(NORMAL, "");
2412 return PM3_SUCCESS;
2414 } else {
2415 // if we called info with key, just return
2416 if (has_auth_key) {
2417 PrintAndLogEx(NORMAL, "");
2418 return PM3_SUCCESS;
2421 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
2422 if (try_default_3des_keys(override, &key) == PM3_SUCCESS) {
2423 PrintAndLogEx(SUCCESS, "Found default 3des key: ");
2424 uint8_t keySwap[16];
2425 memcpy(keySwap, SwapEndian64(key, 16, 8), 16);
2426 ulc_print_3deskey(keySwap);
2427 } else {
2428 PrintAndLogEx(INFO, "n/a");
2431 PrintAndLogEx(NORMAL, "");
2432 return PM3_SUCCESS;
2436 // Specific UL-AES
2437 if (tagtype & MFU_TT_UL_AES) {
2439 // read pages 0x28, 0x29, 0x2A, 0x2B
2440 uint8_t ulaes_conf[16] = {0x00};
2441 status = ul_read(0x29, ulaes_conf, sizeof(ulaes_conf));
2442 if (status <= 0) {
2443 PrintAndLogEx(ERR, "Error: tag didn't answer to READ UL-AES");
2444 DropField();
2445 return PM3_ESOFT;
2448 if (status == 16) {
2449 ulaes_print_configuration(ulaes_conf, 0x29);
2450 } else {
2451 locked = true;
2454 DropField();
2456 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
2457 if (try_default_aes_keys(override) != PM3_SUCCESS) {
2458 PrintAndLogEx(INFO, "n/a");
2460 DropField();
2462 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2463 return PM3_ESOFT;
2467 // do counters and signature first (don't neet auth)
2469 // ul counters are different than ntag counters
2470 if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1))) {
2471 if (ulev1_print_counters() != 3) {
2472 // failed - re-select
2473 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2474 return PM3_ESOFT;
2479 // NTAG counters?
2480 if ((tagtype & (MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C | MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216))) {
2481 if (ntag_print_counter()) {
2482 // failed - re-select
2483 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2484 return PM3_ESOFT;
2489 // Read signature
2490 if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
2491 MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
2492 MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216 | MFU_TT_NTAG_216_F |
2493 MFU_TT_NTAG_I2C_1K | MFU_TT_NTAG_I2C_2K | MFU_TT_NTAG_I2C_1K_PLUS | MFU_TT_NTAG_I2C_2K_PLUS |
2494 MFU_TT_UL_AES))) {
2495 uint8_t ulev1_signature[48] = {0x00};
2496 status = ulev1_readSignature(ulev1_signature, sizeof(ulev1_signature));
2497 if (status < 0) {
2498 PrintAndLogEx(ERR, "Error: tag didn't answer to READ SIGNATURE");
2499 DropField();
2500 return PM3_ESOFT;
2502 if (status == 32 || status == 34) {
2503 ulev1_print_signature(tagtype, card.uid, ulev1_signature, 32);
2504 } else if (status == 48) {
2505 ulev1_print_signature(tagtype, card.uid, ulev1_signature, 48);
2506 } else {
2507 // re-select
2508 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2509 return PM3_ESOFT;
2513 // print silicon info
2514 ul_print_nxp_silicon_info(card.uid);
2516 // Get Version
2517 uint8_t version[10] = {0x00};
2518 status = ulev1_getVersion(version, sizeof(version));
2519 if (status < 0) {
2520 PrintAndLogEx(ERR, "Error: tag didn't answer to GETVERSION");
2521 DropField();
2522 return PM3_ESOFT;
2523 } else if (status == 10) {
2524 ulev1_print_version(version);
2525 } else {
2526 locked = true;
2527 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2528 return PM3_ESOFT;
2532 // Don't check config / passwords for Ul AES :)
2533 if (tagtype == MFU_TT_UL_AES) {
2534 goto out;
2537 uint8_t startconfigblock = 0;
2538 uint8_t ulev1_conf[16] = {0x00};
2540 for (uint8_t i = 1; i < ARRAYLEN(UL_TYPES_ARRAY); i++) {
2541 if ((tagtype & UL_TYPES_ARRAY[i]) == UL_TYPES_ARRAY[i]) {
2542 startconfigblock = UL_MEMORY_ARRAY[i] - 3;
2543 break;
2547 if (startconfigblock) { // if we know where the config block is...
2548 status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
2549 if (status <= 0) {
2550 PrintAndLogEx(ERR, "Error: tag didn't answer to READ EV1");
2551 DropField();
2552 return PM3_ESOFT;
2553 } else if (status == 16) {
2554 // save AUTHENTICATION LIMITS for later:
2555 authlim = (ulev1_conf[4] & 0x07);
2556 // add pwd / pack if used from cli
2557 if (has_auth_key) {
2558 memcpy(ulev1_conf + 8, authkeyptr, 4);
2559 memcpy(ulev1_conf + 12, pack, 2);
2561 ulev1_print_configuration(tagtype, ulev1_conf, startconfigblock);
2565 // AUTHLIMIT, (number of failed authentications)
2566 // 0 = limitless.
2567 // 1-7 = limit. No automatic tries then.
2568 // hasAuthKey, if we was called with key, skip test.
2569 if (!authlim && (has_auth_key == false)) {
2570 PrintAndLogEx(NORMAL, "");
2571 PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known EV1/NTAG passwords"));
2573 // test pwd gen A
2574 num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key);
2575 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2576 if (len > -1) {
2577 has_auth_key = true;
2578 ak_len = 4;
2579 memcpy(authenticationkey, key, 4);
2580 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2581 goto out;
2584 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2585 return PM3_ESOFT;
2588 // test pwd gen B
2589 num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
2590 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2591 if (len > -1) {
2592 has_auth_key = true;
2593 ak_len = 4;
2594 memcpy(authenticationkey, key, 4);
2595 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2596 goto out;
2599 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2600 return PM3_ESOFT;
2603 // test pwd gen C
2604 num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key);
2605 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2606 if (len > -1) {
2607 has_auth_key = true;
2608 ak_len = 4;
2609 memcpy(authenticationkey, key, 4);
2610 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2611 goto out;
2614 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2615 return PM3_ESOFT;
2618 // test pwd gen D
2619 num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key);
2620 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2621 if (len > -1) {
2622 has_auth_key = true;
2623 ak_len = 4;
2624 memcpy(authenticationkey, key, 4);
2625 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2626 goto out;
2629 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2630 return PM3_ESOFT;
2633 for (uint8_t i = 0; i < ARRAYLEN(default_pwd_pack); ++i) {
2634 key = default_pwd_pack[i];
2635 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2636 if (len > -1) {
2637 has_auth_key = true;
2638 ak_len = 4;
2639 memcpy(authenticationkey, key, 4);
2640 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2641 break;
2642 } else {
2643 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2644 return PM3_ESOFT;
2648 if (len < 1) {
2649 PrintAndLogEx(WARNING, _YELLOW_("password not known"));
2650 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2652 } else {
2653 if (locked) {
2654 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2659 out:
2660 DropField();
2662 mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
2664 if (locked) {
2665 PrintAndLogEx(INFO, "\nTag appears to be locked, try using a key to get more info");
2666 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2668 PrintAndLogEx(NORMAL, "");
2669 return PM3_SUCCESS;
2673 // Write Single Block
2675 static int CmdHF14AMfUWrBl(const char *Cmd) {
2677 CLIParserContext *ctx;
2678 CLIParserInit(&ctx, "hf mfu wrbl",
2679 "Write a block. It autodetects card type.",
2680 "hf mfu wrbl -b 0 -d 01234567\n"
2681 "hf mfu wrbl -b 0 -d 01234567 -k AABBCCDD\n"
2682 "hf mfu wrbl -b 0 -d 01234567 -k 00112233445566778899AABBCCDDEEFF"
2685 void *argtable[] = {
2686 arg_param_begin,
2687 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2688 arg_lit0("l", NULL, "Swap entered key's endianness"),
2689 arg_int1("b", "block", "<dec>", "Block number to write"),
2690 arg_str1("d", "data", "<hex>", "Block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"),
2691 arg_lit0(NULL, "force", "Force operation even if address is out of range"),
2692 arg_param_end
2694 CLIExecWithReturn(ctx, Cmd, argtable, false);
2696 int ak_len = 0;
2697 uint8_t authenticationkey[16] = {0x00};
2698 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
2699 bool swap_endian = arg_get_lit(ctx, 2);
2701 int blockno = arg_get_int_def(ctx, 3, -1);
2703 int datalen = 0;
2704 uint8_t data[16] = {0x00};
2705 CLIGetHexWithReturn(ctx, 4, data, &datalen);
2706 bool force = arg_get_lit(ctx, 5);
2707 CLIParserFree(ctx);
2709 bool has_auth_key = false;
2710 bool has_pwd = false;
2711 if (ak_len == 16) {
2712 has_auth_key = true;
2713 } else if (ak_len == 4) {
2714 has_pwd = true;
2715 } else if (ak_len != 0) {
2716 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2717 return PM3_EINVARG;
2720 if (blockno < 0) {
2721 PrintAndLogEx(WARNING, "Wrong block number");
2722 return PM3_EINVARG;
2725 if (datalen != 16 && datalen != 4) {
2726 PrintAndLogEx(WARNING, "Wrong data length. Expect 16 or 4, got %d", datalen);
2727 return PM3_EINVARG;
2730 uint8_t *auth_key_ptr = authenticationkey;
2732 // starting with getting tagtype
2733 uint64_t tagtype = GetHF14AMfU_Type();
2734 if (tagtype == MFU_TT_UL_ERROR)
2735 return PM3_ESOFT;
2737 uint8_t maxblockno = 0;
2738 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
2739 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
2740 maxblockno = UL_MEMORY_ARRAY[idx];
2741 break;
2744 if ((blockno > maxblockno) && (!force)) {
2745 PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
2746 return PM3_EINVARG;
2749 // Swap endianness
2750 if (swap_endian) {
2751 if (has_auth_key)
2752 auth_key_ptr = SwapEndian64(authenticationkey, 16, 8);
2754 if (has_pwd)
2755 auth_key_ptr = SwapEndian64(authenticationkey, 4, 4);
2758 if (blockno <= 3)
2759 PrintAndLogEx(INFO, "Special block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen));
2760 else
2761 PrintAndLogEx(INFO, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen));
2763 if (ak_len) {
2764 PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
2768 // Send write Block.
2769 uint8_t *d = data;
2770 int res = 0;
2771 if (datalen == 16) {
2772 // Comp write may take 16bytes, but only write 4bytes. See UL-C datasheet
2773 for (uint8_t i = 0; i < 4; i++) {
2775 res = mfu_write_block(d, 4, has_auth_key, has_pwd, auth_key_ptr, blockno + i);
2776 if (res == PM3_SUCCESS) {
2777 d += 4;
2778 } else {
2779 PrintAndLogEx(INFO, "Write ( %s )", _RED_("fail"));
2780 return PM3_ESOFT;
2784 if (res == PM3_SUCCESS) {
2785 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
2786 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno);
2789 } else {
2790 res = mfu_write_block(data, datalen, has_auth_key, has_pwd, auth_key_ptr, blockno);
2791 switch (res) {
2792 case PM3_SUCCESS: {
2793 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
2794 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno);
2795 break;
2797 case PM3_ESOFT: {
2798 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
2799 PrintAndLogEx(HINT, "Check password / key!");
2800 break;
2802 case PM3_ETIMEOUT:
2803 default: {
2804 PrintAndLogEx(WARNING, "Command execute timeout");
2805 break;
2810 return res;
2813 // Read Single Block
2815 static int CmdHF14AMfURdBl(const char *Cmd) {
2817 CLIParserContext *ctx;
2818 CLIParserInit(&ctx, "hf mfu rdbl",
2819 "Read a block and print. It autodetects card type.",
2820 "hf mfu rdbl -b 0\n"
2821 "hf mfu rdbl -b 0 -k AABBCCDD\n"
2822 "hf mfu rdbl -b 0 --key 00112233445566778899AABBCCDDEEFF"
2825 void *argtable[] = {
2826 arg_param_begin,
2827 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2828 arg_lit0("l", NULL, "Swap entered key's endianness"),
2829 arg_int1("b", "block", "<dec>", "Block number to read"),
2830 arg_lit0(NULL, "force", "Force operation even if address is out of range"),
2831 arg_param_end
2833 CLIExecWithReturn(ctx, Cmd, argtable, false);
2835 int ak_len = 0;
2836 uint8_t authenticationkey[16] = {0x00};
2837 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
2838 bool swap_endian = arg_get_lit(ctx, 2);
2839 int blockno = arg_get_int_def(ctx, 3, -1);
2840 bool force = arg_get_lit(ctx, 4);
2841 CLIParserFree(ctx);
2843 bool has_auth_key = false;
2844 bool has_pwd = false;
2845 if (ak_len == 16) {
2846 has_auth_key = true;
2847 } else if (ak_len == 4) {
2848 has_pwd = true;
2849 } else if (ak_len != 0) {
2850 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2851 return PM3_EINVARG;
2854 if (blockno < 0) {
2855 PrintAndLogEx(WARNING, "Wrong block number");
2856 return PM3_EINVARG;
2859 uint8_t *authKeyPtr = authenticationkey;
2861 // start with getting tagtype
2862 uint64_t tagtype = GetHF14AMfU_Type();
2863 if (tagtype == MFU_TT_UL_ERROR)
2864 return PM3_ESOFT;
2866 uint8_t maxblockno = 0;
2867 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
2868 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
2869 maxblockno = UL_MEMORY_ARRAY[idx];
2870 break;
2873 if ((blockno > maxblockno) && (!force)) {
2874 PrintAndLogEx(WARNING, "block number to large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
2875 return PM3_EINVARG;
2878 // Swap endianness
2879 if (swap_endian) {
2880 if (has_auth_key)
2881 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
2883 if (has_pwd)
2884 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
2887 if (ak_len) {
2888 PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
2891 //Read Block
2892 uint8_t keytype = 0;
2893 uint8_t datalen = 0;
2894 if (has_auth_key) {
2895 keytype = 1;
2896 datalen = 16;
2897 } else if (has_pwd) {
2898 keytype = 2;
2899 datalen = 4;
2902 clearCommandBuffer();
2903 SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, keytype, 0, authKeyPtr, datalen);
2904 PacketResponseNG resp;
2905 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
2906 uint8_t isOK = resp.oldarg[0] & 0xff;
2907 if (isOK) {
2908 uint8_t *d = resp.data.asBytes;
2909 PrintAndLogEx(NORMAL, "");
2910 PrintAndLogEx(INFO, "Block# | Data | Ascii");
2911 PrintAndLogEx(INFO, "-----------------------------");
2912 PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s\n", blockno, blockno, sprint_hex(d, 4), sprint_ascii(d, 4));
2913 } else {
2914 PrintAndLogEx(WARNING, "Failed reading block: ( %02x )", isOK);
2916 } else {
2917 PrintAndLogEx(WARNING, "Command execute timeout");
2919 return PM3_SUCCESS;
2922 void mfu_print_dump(mfu_dump_t *card, uint16_t pages, uint8_t startpage, bool dense_output) {
2924 PrintAndLogEx(NORMAL, "");
2925 PrintAndLogEx(INFO, _CYAN_("MFU dump file information"));
2926 PrintAndLogEx(INFO, "-------------------------------------------------------------");
2927 PrintAndLogEx(INFO, "Version..... " _YELLOW_("%s"), sprint_hex(card->version, sizeof(card->version)));
2928 PrintAndLogEx(INFO, "TBD 0....... %s", sprint_hex(card->tbo, sizeof(card->tbo)));
2929 PrintAndLogEx(INFO, "TBD 1....... %s", sprint_hex(card->tbo1, sizeof(card->tbo1)));
2930 PrintAndLogEx(INFO, "Signature... %s", sprint_hex(card->signature, 16));
2931 PrintAndLogEx(INFO, " %s", sprint_hex(card->signature + 16, sizeof(card->signature) - 16));
2932 for (uint8_t i = 0; i < 3; i ++) {
2933 PrintAndLogEx(INFO, "Counter %d... %s", i, sprint_hex(card->counter_tearing[i], 3));
2934 PrintAndLogEx(INFO, "Tearing %d... %s", i, sprint_hex(card->counter_tearing[i] + 3, 1));
2937 // 0-bases index, to get total bytes, its +1 page.
2938 // UL-C,
2939 // Max index page is 47.
2940 // total pages is 48
2941 // total bytes is 192
2942 PrintAndLogEx(INFO, "Max data page... " _YELLOW_("%d") " ( " _YELLOW_("%d") " bytes )", card->pages, (card->pages + 1) * MFU_BLOCK_SIZE);
2943 PrintAndLogEx(INFO, "Header size..... %d bytes", MFU_DUMP_PREFIX_LENGTH);
2945 uint8_t j = 0;
2946 bool lckbit = false;
2947 uint8_t *data = card->data;
2949 uint8_t lockbytes_sta[] = {0, 0};
2950 uint8_t lockbytes_dyn[] = {0, 0, 0};
2951 bool bit_stat[16] = {0};
2952 bool bit_dyn[16] = {0};
2954 // Load static lock bytes.
2955 memcpy(lockbytes_sta, data + 10, sizeof(lockbytes_sta));
2956 for (j = 0; j < 16; j++) {
2957 bit_stat[j] = lockbytes_sta[j / 8] & (1 << (7 - j % 8));
2960 // Load dynamic lockbytes if available
2961 // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG
2962 if (pages == 44) {
2964 memcpy(lockbytes_dyn, data + (40 * 4), sizeof(lockbytes_dyn));
2966 for (j = 0; j < 16; j++) {
2967 bit_dyn[j] = lockbytes_dyn[j / 8] & (1 << (7 - j % 8));
2969 PrintAndLogEx(INFO, "Dynamic lock.... %s", sprint_hex(lockbytes_dyn, 3));
2972 PrintAndLogEx(NORMAL, "");
2973 PrintAndLogEx(INFO, "-------------------------------------------------------------");
2974 PrintAndLogEx(INFO, "block# | data |lck| ascii");
2975 PrintAndLogEx(INFO, "---------+-------------+---+------");
2977 bool in_repeated_block = false;
2979 for (uint16_t i = 0; i < pages; ++i) {
2980 if (i < 3) {
2981 PrintAndLogEx(INFO, "%3d/0x%02X | " _RED_("%s")"| | %s",
2982 i + startpage,
2983 i + startpage,
2984 sprint_hex(data + i * 4, 4),
2985 sprint_ascii(data + i * 4, 4)
2987 continue;
2989 switch (i) {
2990 case 3:
2991 lckbit = bit_stat[4];
2992 break;
2993 case 4:
2994 lckbit = bit_stat[3];
2995 break;
2996 case 5:
2997 lckbit = bit_stat[2];
2998 break;
2999 case 6:
3000 lckbit = bit_stat[1];
3001 break;
3002 case 7:
3003 lckbit = bit_stat[0];
3004 break;
3005 case 8:
3006 lckbit = bit_stat[15];
3007 break;
3008 case 9:
3009 lckbit = bit_stat[14];
3010 break;
3011 case 10:
3012 lckbit = bit_stat[13];
3013 break;
3014 case 11:
3015 lckbit = bit_stat[12];
3016 break;
3017 case 12:
3018 lckbit = bit_stat[11];
3019 break;
3020 case 13:
3021 lckbit = bit_stat[10];
3022 break;
3023 case 14:
3024 lckbit = bit_stat[9];
3025 break;
3026 case 15:
3027 lckbit = bit_stat[8];
3028 break;
3029 case 16:
3030 case 17:
3031 case 18:
3032 case 19:
3033 lckbit = bit_dyn[6];
3034 break;
3035 case 20:
3036 case 21:
3037 case 22:
3038 case 23:
3039 lckbit = bit_dyn[5];
3040 break;
3041 case 24:
3042 case 25:
3043 case 26:
3044 case 27:
3045 lckbit = bit_dyn[4];
3046 break;
3047 case 28:
3048 case 29:
3049 case 30:
3050 case 31:
3051 lckbit = bit_dyn[2];
3052 break;
3053 case 32:
3054 case 33:
3055 case 34:
3056 case 35:
3057 lckbit = bit_dyn[1];
3058 break;
3059 case 36:
3060 case 37:
3061 case 38:
3062 case 39:
3063 lckbit = bit_dyn[0];
3064 break;
3065 case 40:
3066 lckbit = bit_dyn[12];
3067 break;
3068 case 41:
3069 lckbit = bit_dyn[11];
3070 break;
3071 case 42:
3072 lckbit = bit_dyn[10];
3073 break; //auth0
3074 case 43:
3075 lckbit = bit_dyn[9];
3076 break; //auth1
3077 default:
3078 break;
3082 // suppress repeating blocks, truncate as such that the first and last block with the same data is shown
3083 // but the blocks in between are replaced with a single line of "......" if dense_output is enabled
3084 uint8_t *blk = data + (i * MFU_BLOCK_SIZE);
3085 if (dense_output &&
3086 (i > 3) &&
3087 (i < pages) &&
3088 (in_repeated_block == false) &&
3089 (memcmp(blk, blk - MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) == 0) &&
3090 (memcmp(blk, blk + MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) == 0) &&
3091 (memcmp(blk, blk + (MFU_BLOCK_SIZE * 2), MFU_BLOCK_SIZE) == 0)
3093 // we're in a user block that isn't the first user block nor last two user blocks,
3094 // and the current block data is the same as the previous and next two block
3095 in_repeated_block = true;
3096 PrintAndLogEx(INFO, " ......");
3097 } else if (in_repeated_block &&
3098 (memcmp(blk, blk + MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) || i == pages)
3100 // in a repeating block, but the next block doesn't match anymore, or we're at the end block
3101 in_repeated_block = false;
3105 if (in_repeated_block == false) {
3106 PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s"
3107 , i + startpage
3108 , i + startpage
3109 , sprint_hex(data + i * 4, 4)
3110 , (lckbit) ? _RED_("1") : "0"
3111 , sprint_ascii(data + i * 4, 4)
3115 PrintAndLogEx(INFO, "---------------------------------");
3119 // Mifare Ultralight / Ultralight-C / Ultralight-EV1
3120 // Read and Dump Card Contents, using auto detection of tag size.
3121 static int CmdHF14AMfUDump(const char *Cmd) {
3123 CLIParserContext *ctx;
3124 CLIParserInit(&ctx, "hf mfu dump",
3125 "Dump MIFARE Ultralight/NTAG tag to files (bin/json)\n"
3126 "It autodetects card type."
3127 "Supports:\n"
3128 "Ultralight, Ultralight-C, Ultralight EV1\n"
3129 "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216\n",
3130 "hf mfu dump -f myfile\n"
3131 "hf mfu dump -k AABBCCDD -> dump whole tag using pwd AABBCCDD\n"
3132 "hf mfu dump -p 10 -> start at page 10 and dump rest of blocks\n"
3133 "hf mfu dump -p 10 -q 2 -> start at page 10 and dump two blocks\n"
3134 "hf mfu dump --key 00112233445566778899AABBCCDDEEFF"
3137 void *argtable[] = {
3138 arg_param_begin,
3139 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
3140 arg_str0("k", "key", "<hex>", "Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
3141 arg_lit0("l", NULL, "Swap entered key's endianness"),
3142 arg_int0("p", "page", "<dec>", "Manually set start page number to start from"),
3143 arg_int0("q", "qty", "<dec>", "Manually set number of pages to dump"),
3144 arg_lit0(NULL, "ns", "no save to file"),
3145 arg_lit0("z", "dense", "dense dump output style"),
3146 arg_param_end
3148 CLIExecWithReturn(ctx, Cmd, argtable, true);
3150 int fnlen = 0;
3151 char filename[FILE_PATH_SIZE] = {0};
3152 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3154 int ak_len = 0;
3155 uint8_t authenticationkey[16] = {0x00};
3156 uint8_t *authKeyPtr = authenticationkey;
3157 CLIGetHexWithReturn(ctx, 2, authenticationkey, &ak_len);
3158 bool swap_endian = arg_get_lit(ctx, 3);
3159 int start_page = arg_get_int_def(ctx, 4, 0);
3160 int pages = arg_get_int_def(ctx, 5, 16);
3161 bool nosave = arg_get_lit(ctx, 6);
3162 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 7));
3163 CLIParserFree(ctx);
3165 bool has_auth_key = false;
3166 bool has_pwd = false;
3167 if (ak_len == 16) {
3168 has_auth_key = true;
3169 } else if (ak_len == 4) {
3170 has_pwd = true;
3171 } else if (ak_len != 0) {
3172 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
3173 return PM3_EINVARG;
3176 bool manual_pages = false;
3177 if (start_page > 0) {
3178 manual_pages = true;
3181 if (pages != 16) {
3182 manual_pages = true;
3185 uint8_t card_mem_size = 0;
3187 // Swap endianness
3188 if (swap_endian) {
3189 if (has_auth_key) {
3190 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
3193 if (has_pwd) {
3194 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
3198 uint64_t tagtype = GetHF14AMfU_Type();
3199 if (tagtype == MFU_TT_UL_ERROR) {
3200 return PM3_ESOFT;
3203 //get number of pages to read
3204 if (manual_pages == false) {
3205 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
3206 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
3207 //add one as maxblks starts at 0
3208 card_mem_size = pages = UL_MEMORY_ARRAY[idx] + 1;
3209 break;
3214 ul_print_type(tagtype, 0);
3215 PrintAndLogEx(SUCCESS, "Reading tag memory...");
3216 uint8_t keytype = 0;
3217 if (has_auth_key || has_pwd) {
3218 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C)
3219 keytype = 1; // UL_C auth
3220 else
3221 keytype = 2; // UL_EV1/NTAG auth
3224 uint8_t dbg_curr = DBG_NONE;
3225 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
3226 return PM3_ESOFT;
3229 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
3230 return PM3_ESOFT;
3233 clearCommandBuffer();
3234 SendCommandMIX(CMD_HF_MIFAREU_READCARD, start_page, pages, keytype, authKeyPtr, ak_len);
3235 PacketResponseNG resp;
3236 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
3237 PrintAndLogEx(WARNING, "Command execute timeout");
3238 return PM3_ETIMEOUT;
3241 if (resp.oldarg[0] != 1) {
3242 PrintAndLogEx(WARNING, "Failed dumping card");
3243 return PM3_ESOFT;
3246 setDeviceDebugLevel(dbg_curr, false);
3248 // read all memory
3249 uint8_t data[1024] = {0x00};
3250 memset(data, 0x00, sizeof(data));
3252 uint32_t startindex = resp.oldarg[2];
3253 uint32_t buffer_size = resp.oldarg[1];
3254 if (buffer_size > sizeof(data)) {
3255 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
3256 buffer_size = sizeof(data);
3259 if (GetFromDevice(BIG_BUF, data, buffer_size, startindex, NULL, 0, NULL, 2500, false) == false) {
3260 PrintAndLogEx(WARNING, "command execute timeout");
3261 return PM3_ETIMEOUT;
3264 bool is_partial = (pages != buffer_size / MFU_BLOCK_SIZE);
3266 pages = buffer_size / MFU_BLOCK_SIZE;
3268 if (is_partial) {
3270 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
3271 if (card_mem_size != (pages + 4)) {
3272 PrintAndLogEx(INFO, "Partial dump, got " _RED_("%d") " bytes - card mem size is %u bytes", pages * MFU_BLOCK_SIZE, card_mem_size * MFU_BLOCK_SIZE);
3273 PrintAndLogEx(HINT, "Try using a key");
3275 } else {
3276 PrintAndLogEx(HINT, "Try using a pwd");
3280 iso14a_card_select_t card;
3281 mfu_dump_t dump_file_data;
3282 memset(&dump_file_data, 0, sizeof(dump_file_data));
3283 uint8_t get_version[] = {0, 0, 0, 0, 0, 0, 0, 0};
3284 uint8_t get_counter_tearing[][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
3285 uint8_t get_signature[32];
3286 memset(get_signature, 0, sizeof(get_signature));
3288 // not ul_c and not std ul then attempt to collect info like
3289 // VERSION, SIGNATURE, COUNTERS, TEARING, PACK,
3290 if (!(tagtype & MFU_TT_UL_C || tagtype & MFU_TT_UL || tagtype & MFU_TT_MY_D_MOVE || tagtype & MFU_TT_MY_D_MOVE_LEAN)) {
3291 // attempt to read pack
3292 bool has_key = (has_auth_key || has_pwd);
3293 uint8_t get_pack[] = {0, 0};
3294 if (ul_auth_select(&card, tagtype, has_key, authKeyPtr, get_pack, sizeof(get_pack)) != PM3_SUCCESS) {
3295 //reset pack
3296 get_pack[0] = 0;
3297 get_pack[1] = 0;
3299 DropField();
3301 // only add pack if not partial read, and complete pages read.
3302 if (!is_partial && pages == card_mem_size) {
3304 // add pack to block read
3305 memcpy(data + (pages * 4) - 4, get_pack, sizeof(get_pack));
3308 if (has_auth_key) {
3309 uint8_t dummy_pack[] = {0, 0};
3310 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3311 } else {
3312 ul_select(&card);
3315 ulev1_getVersion(get_version, sizeof(get_version));
3317 // ULEV-1 has 3 counters
3318 uint8_t n = 0;
3320 // NTAG has 1 counter, at 0x02
3321 if ((tagtype & (MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C | MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216))) {
3322 n = 2;
3325 // NTAG can have nfc counter pwd protection enabled
3326 for (; n < 3; n++) {
3328 if (has_auth_key) {
3329 uint8_t dummy_pack[] = {0, 0};
3330 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3331 } else {
3332 ul_select(&card);
3334 ulev1_readCounter(n, &get_counter_tearing[n][0], 3);
3336 if (has_auth_key) {
3337 uint8_t dummy_pack[] = {0, 0};
3338 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3339 } else {
3340 ul_select(&card);
3342 ulev1_readTearing(n, &get_counter_tearing[n][3], 1);
3345 DropField();
3347 if (has_auth_key) {
3348 uint8_t dummy_pack[] = {0, 0};
3349 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3350 } else {
3351 ul_select(&card);
3354 ulev1_readSignature(get_signature, sizeof(get_signature));
3355 DropField();
3359 // format and add keys to block dump output
3360 // only add keys if not partial read, and complete pages read
3362 // UL-C add a working known key
3363 if (has_auth_key && (tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) { // add 4 pages of key
3365 // if we didn't swapendian before - do it now for the sprint_hex call
3366 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
3367 // need to swap to keep it the same
3368 if (swap_endian == false) {
3369 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
3370 } else {
3371 authKeyPtr = authenticationkey;
3374 memcpy(data + pages * MFU_BLOCK_SIZE, authKeyPtr, ak_len);
3375 pages += ak_len / MFU_BLOCK_SIZE;
3377 // fix
3378 if (is_partial && pages == card_mem_size) {
3379 is_partial = false;
3383 if (!is_partial && pages == card_mem_size && has_pwd) {
3384 // if we didn't swapendian before - do it now for the sprint_hex call
3385 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
3386 // need to swap to keep it the same
3387 if (swap_endian == false) {
3388 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
3389 } else {
3390 authKeyPtr = authenticationkey;
3393 memcpy(data + (pages * MFU_BLOCK_SIZE) - 8, authenticationkey, ak_len);
3396 //add *special* blocks to dump
3397 // pack and pwd saved into last pages of dump, if was not partial read
3398 dump_file_data.pages = pages - 1;
3399 memcpy(dump_file_data.version, get_version, sizeof(dump_file_data.version));
3400 memcpy(dump_file_data.signature, get_signature, sizeof(dump_file_data.signature));
3401 memcpy(dump_file_data.counter_tearing, get_counter_tearing, sizeof(dump_file_data.counter_tearing));
3402 memcpy(dump_file_data.data, data, pages * MFU_BLOCK_SIZE);
3404 mfu_print_dump(&dump_file_data, pages, start_page, dense_output);
3406 if (nosave) {
3407 PrintAndLogEx(INFO, "Called with no save option");
3408 PrintAndLogEx(NORMAL, "");
3409 return PM3_SUCCESS;
3412 // user supplied filename?
3413 if (fnlen < 1) {
3414 PrintAndLogEx(INFO, "Using UID as filename");
3415 uint8_t uid[7] = {0};
3416 memcpy(uid, (uint8_t *)&dump_file_data.data, 3);
3417 memcpy(uid + 3, (uint8_t *)&dump_file_data.data + 4, 4);
3418 strcat(filename, "hf-mfu-");
3419 FillFileNameByUID(filename, uid, "-dump", sizeof(uid));
3422 uint16_t datalen = MFU_DUMP_PREFIX_LENGTH + (pages * MFU_BLOCK_SIZE);
3423 pm3_save_dump(filename, (uint8_t *)&dump_file_data, datalen, jsfMfuMemory);
3425 if (is_partial) {
3426 PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
3428 return PM3_SUCCESS;
3431 static void wait4response(uint8_t b) {
3432 PacketResponseNG resp;
3433 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
3434 uint8_t isOK = resp.oldarg[0] & 0xff;
3435 if (isOK == 0) {
3436 PrintAndLogEx(WARNING, "failed to write block %d", b);
3438 } else {
3439 PrintAndLogEx(WARNING, "Command execute timeout");
3444 //Configure tamper feature of NTAG 213TT
3446 int CmdHF14MfUTamper(const char *Cmd) {
3447 CLIParserContext *ctx;
3448 CLIParserInit(&ctx, "hf mfu tamper",
3449 "Set the configuration of the NTAG 213TT tamper feature\n"
3450 "Supports:\n"
3451 "NTAG 213TT\n",
3452 "hf mfu tamper -e -> enable tamper feature\n"
3453 "hf mfu tamper -d -> disable tamper feature\n"
3454 "hf mfu tamper -m 0A0A0A0A -> set the tamper message to 0A0A0A0A\n"
3455 "hf mfu tamper --lockmessage -> permanently lock the tamper message and mask it from memory\n"
3458 void *argtable[] = {
3459 arg_param_begin,
3460 arg_lit0("e", "enable", "Enable the tamper feature"),
3461 arg_lit0("d", "disable", "Disable the tamper feature"),
3462 arg_str0("m", "message", "<hex>", "Set the tamper message (4 bytes)"),
3463 arg_lit0(NULL, "lockmessage", "Permanently lock the tamper message and mask it from memory (does not lock tamper feature itself)"),
3464 arg_param_end
3466 CLIExecWithReturn(ctx, Cmd, argtable, false);
3468 int tt_cfg_page = 41;
3469 int tt_msg_page = 45;
3470 int msg_len = 0;
3471 uint8_t msg_data[4] = {0x00};
3472 CLIGetHexWithReturn(ctx, 3, msg_data, &msg_len);
3473 bool use_msg = (msg_len > 0);
3475 if (use_msg && msg_len != 4) {
3476 PrintAndLogEx(WARNING, "The tamper message must be 4 hex bytes if provided");
3477 DropField();
3478 CLIParserFree(ctx);
3479 return PM3_ESOFT;
3482 bool lock_msg = arg_get_lit(ctx, 4);
3483 bool enable = arg_get_lit(ctx, 1);
3484 bool disable = arg_get_lit(ctx, 2);
3485 CLIParserFree(ctx);
3487 uint64_t tagtype = GetHF14AMfU_Type();
3488 if (tagtype == MFU_TT_UL_ERROR) {
3489 PrintAndLogEx(WARNING, "Tag type not detected");
3490 DropField();
3491 return PM3_ESOFT;
3493 if (tagtype != MFU_TT_NTAG_213_TT) {
3494 PrintAndLogEx(WARNING, "Tag type not NTAG 213TT");
3495 DropField();
3496 return PM3_ESOFT;
3499 DropField();
3500 iso14a_card_select_t card;
3502 if (enable && disable) {
3503 PrintAndLogEx(WARNING, "You can only select one of the options enable/disable tamper feature");
3504 DropField();
3505 return PM3_ESOFT;
3508 if (use_msg) {
3509 if (ul_select(&card) == false) {
3510 DropField();
3511 return MFU_TT_UL_ERROR;
3513 PrintAndLogEx(INFO, "Trying to write tamper message");
3514 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_msg_page, 0, 0, msg_data, 4);
3516 PacketResponseNG resp;
3518 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
3519 uint8_t isOK = resp.oldarg[0] & 0xff;
3520 if (!isOK)
3521 PrintAndLogEx(WARNING, "Failed to write tamper message");
3522 else
3523 PrintAndLogEx(SUCCESS, "Tamper message written successfully");
3524 } else {
3525 PrintAndLogEx(WARNING, "Command execute timeout");
3529 if (enable || disable || lock_msg) {
3531 if (ul_select(&card) == false) {
3532 PrintAndLogEx(ERR, "Unable to select tag");
3533 DropField();
3534 return MFU_TT_UL_ERROR;
3537 uint8_t cfg_page[4] = {0x00};
3538 uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, tt_cfg_page};
3539 int status = ul_send_cmd_raw(cmd, sizeof(cmd), cfg_page, 4);
3540 DropField();
3542 if (status <= 0) {
3543 PrintAndLogEx(WARNING, "Problem reading current config from tag");
3544 DropField();
3545 return PM3_ESOFT;
3548 if (enable) {
3549 cfg_page[1] = cfg_page[1] | 0x02;
3550 PrintAndLogEx(INFO, "Enabling tamper feature");
3552 if (disable) {
3553 cfg_page[1] = cfg_page[1] & 0xFD;
3554 PrintAndLogEx(INFO, "Disabling tamper feature");
3556 if (lock_msg) {
3557 cfg_page[1] = cfg_page[1] | 0x04;
3558 PrintAndLogEx(INFO, "Locking tamper message");
3561 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_cfg_page, 0, 0, cfg_page, 4);
3562 PacketResponseNG resp;
3564 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
3565 uint8_t isOK = resp.oldarg[0] & 0xff;
3566 if (!isOK)
3567 PrintAndLogEx(WARNING, "Failed to write tamper configuration");
3568 else
3569 PrintAndLogEx(SUCCESS, "Tamper configuration written successfully");
3570 } else {
3571 PrintAndLogEx(WARNING, "Command execute timeout");
3575 DropField();
3576 return PM3_SUCCESS;
3580 // Restore dump file onto tag
3582 static int CmdHF14AMfURestore(const char *Cmd) {
3583 CLIParserContext *ctx;
3584 CLIParserInit(&ctx, "hf mfu restore",
3585 "Restore MIFARE Ultralight/NTAG dump file (bin/eml/json) to tag.\n",
3586 "hf mfu restore -f myfile -s -> special write\n"
3587 "hf mfu restore -f myfile -k AABBCCDD -s -> special write, use key\n"
3588 "hf mfu restore -f myfile -k AABBCCDD -ser -> special write, use key, write dump pwd, ..."
3591 void *argtable[] = {
3592 arg_param_begin,
3593 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
3594 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
3595 arg_lit0("l", NULL, "swap entered key's endianness"),
3596 arg_lit0("s", NULL, "enable special write UID -MAGIC TAG ONLY-"),
3597 arg_lit0("e", NULL, "enable special write version/signature -MAGIC NTAG 21* ONLY-"),
3598 arg_lit0("r", NULL, "use password found in dumpfile to configure tag. Requires " _YELLOW_("'-e'") " parameter to work"),
3599 arg_lit0("v", "verbose", "verbose output"),
3600 arg_lit0("z", "dense", "dense dump output style"),
3601 arg_param_end
3603 CLIExecWithReturn(ctx, Cmd, argtable, false);
3605 int fnlen = 0;
3606 char filename[FILE_PATH_SIZE] = {0};
3607 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3609 int ak_len = 0;
3610 uint8_t authkey[16] = {0x00};
3611 uint8_t *p_authkey = authkey;
3612 CLIGetHexWithReturn(ctx, 2, authkey, &ak_len);
3614 bool swap_endian = arg_get_lit(ctx, 3);
3615 bool write_special = arg_get_lit(ctx, 4);
3616 bool write_extra = arg_get_lit(ctx, 5);
3617 bool read_key = arg_get_lit(ctx, 6);
3618 bool verbose = arg_get_lit(ctx, 7);
3619 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 8));
3620 CLIParserFree(ctx);
3622 bool has_key = false;
3623 if (ak_len > 0) {
3624 if (ak_len != 4 && ak_len != 16) {
3625 PrintAndLogEx(ERR, "Wrong key length. expected 4 or 16, got %d", ak_len);
3626 return PM3_EINVARG;
3627 } else {
3628 has_key = true;
3632 if (fnlen == 0) {
3633 char *fptr = mfu_generate_filename("hf-mfu-", "-dump.bin");
3634 if (fptr != NULL) {
3635 strncpy(filename, fptr, sizeof(filename) - 1);
3636 } else {
3637 snprintf(filename, sizeof(filename), "dumpdata.bin");
3639 free(fptr);
3642 // read dump file
3643 uint8_t *dump = NULL;
3644 size_t bytes_read = 0;
3645 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (MFU_MAX_BYTES + MFU_DUMP_PREFIX_LENGTH));
3646 if (res != PM3_SUCCESS) {
3647 return res;
3650 if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
3651 PrintAndLogEx(ERR, "Error, dump file is too small");
3652 free(dump);
3653 return PM3_ESOFT;
3656 res = convert_mfu_dump_format(&dump, &bytes_read, verbose);
3657 if (res != PM3_SUCCESS) {
3658 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
3659 free(dump);
3660 return res;
3663 mfu_dump_t *mem = (mfu_dump_t *)dump;
3664 uint8_t pages = (bytes_read - MFU_DUMP_PREFIX_LENGTH) / MFU_BLOCK_SIZE;
3666 if (pages - 1 != mem->pages) {
3667 PrintAndLogEx(ERR, "Error, invalid dump, wrong page count");
3668 PrintAndLogEx(INFO, " %u vs mempg %u", pages - 1, mem->pages);
3669 free(dump);
3670 return PM3_ESOFT;
3673 PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", filename);
3675 mfu_print_dump(mem, pages, 0, dense_output);
3677 // Swap endianness
3678 if (swap_endian && has_key) {
3679 if (ak_len == 16)
3680 p_authkey = SwapEndian64(authkey, ak_len, 8);
3681 else
3682 p_authkey = SwapEndian64(authkey, ak_len, 4);
3685 uint8_t data[20] = {0};
3686 uint8_t keytype = 0;
3687 // set key - only once
3688 if (has_key) {
3689 keytype = (ak_len == 16) ? 1 : 2;
3690 memcpy(data + 4, p_authkey, ak_len);
3693 // write version, signature, pack
3694 // only magic NTAG cards
3695 if (write_extra) {
3697 #define MFU_NTAG_SPECIAL_PWD 0xF0
3698 #define MFU_NTAG_SPECIAL_PACK 0xF1
3699 #define MFU_NTAG_SPECIAL_VERSION 0xFA
3700 #define MFU_NTAG_SPECIAL_SIGNATURE 0xF2
3701 // pwd
3702 if (has_key || read_key) {
3704 memcpy(data, p_authkey, 4);
3705 if (read_key) {
3706 // try reading key from dump and use.
3707 memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 8), 4);
3710 PrintAndLogEx(INFO, "special PWD block written 0x%X - %s", MFU_NTAG_SPECIAL_PWD, sprint_hex(data, 4));
3711 clearCommandBuffer();
3712 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data));
3714 wait4response(MFU_NTAG_SPECIAL_PWD);
3716 // copy the new key
3717 keytype = 2;
3718 memcpy(authkey, data, 4);
3719 memcpy(data + 4, authkey, 4);
3722 // pack
3723 memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2);
3724 data[2] = 0;
3725 data[3] = 0;
3726 PrintAndLogEx(INFO, "special PACK block written 0x%X - %s", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4));
3727 clearCommandBuffer();
3728 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data));
3729 wait4response(MFU_NTAG_SPECIAL_PACK);
3731 // Signature
3732 for (uint8_t s = MFU_NTAG_SPECIAL_SIGNATURE, i = 0; s < MFU_NTAG_SPECIAL_SIGNATURE + 8; s++, i += 4) {
3733 memcpy(data, mem->signature + i, 4);
3734 PrintAndLogEx(INFO, "special SIG block written 0x%X - %s", s, sprint_hex(data, 4));
3735 clearCommandBuffer();
3736 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data));
3737 wait4response(s);
3740 // Version
3741 for (uint8_t s = MFU_NTAG_SPECIAL_VERSION, i = 0; s < MFU_NTAG_SPECIAL_VERSION + 2; s++, i += 4) {
3742 memcpy(data, mem->version + i, 4);
3743 PrintAndLogEx(INFO, "special VERSION block written 0x%X - %s", s, sprint_hex(data, 4));
3744 clearCommandBuffer();
3745 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data));
3746 wait4response(s);
3750 PrintAndLogEx(INFO, "Restoring data blocks.");
3751 PrintAndLogEx(INFO, "." NOLF);
3752 // write all other data
3753 // Skip block 0,1,2,3 (only magic tags can write to them)
3754 // Skip last 5 blocks usually is configuration
3755 for (uint8_t b = 4; b < pages - 5; b++) {
3757 //Send write Block
3758 memcpy(data, mem->data + (b * 4), 4);
3759 clearCommandBuffer();
3760 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
3761 wait4response(b);
3762 PrintAndLogEx(NORMAL, "." NOLF);
3763 fflush(stdout);
3765 PrintAndLogEx(NORMAL, "");
3767 // write special data last
3768 if (write_special) {
3770 PrintAndLogEx(INFO, "Restoring configuration blocks");
3772 PrintAndLogEx(INFO, "Authentication with keytype[%x] %s\n", (uint8_t)(keytype & 0xff), sprint_hex(p_authkey, 4));
3774 #if defined ICOPYX
3775 // otp, uid, lock, dynlockbits, cfg0, cfg1, pwd, pack
3776 uint8_t blocks[] = {3, 0, 1, 2, pages - 5, pages - 4, pages - 3, pages - 2, pages - 1};
3777 #else
3778 // otp, uid, lock, dynlockbits, cfg0, cfg1
3779 uint8_t blocks[] = {3, 0, 1, 2, pages - 5, pages - 4, pages - 3};
3780 #endif
3781 for (uint8_t i = 0; i < ARRAYLEN(blocks); i++) {
3782 uint8_t b = blocks[i];
3783 memcpy(data, mem->data + (b * 4), 4);
3784 clearCommandBuffer();
3785 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
3786 wait4response(b);
3787 PrintAndLogEx(INFO, "special block written " _YELLOW_("%u") " - %s", b, sprint_hex(data, 4));
3791 DropField();
3792 free(dump);
3793 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mfu dump --ns") "` to verify");
3794 PrintAndLogEx(INFO, "Done!");
3795 return PM3_SUCCESS;
3798 // Load emulator with dump file
3800 static int CmdHF14AMfUeLoad(const char *Cmd) {
3802 CLIParserContext *ctx;
3803 CLIParserInit(&ctx, "hf mfu eload",
3804 "Load emulator memory with data from (bin/eml/json) dump file\n",
3805 "hf mfu eload -f hf-mfu-04010203040506.bin\n"
3806 "hf mfu eload -f hf-mfu-04010203040506.bin -q 57 -> load 57 blocks from myfile"
3809 void *argtable[] = {
3810 arg_param_begin,
3811 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
3812 arg_int0("q", "qty", "<dec>", "Number of blocks to load from eml file"),
3813 arg_lit0("v", "verbose", "verbose output"),
3814 arg_param_end
3816 CLIExecWithReturn(ctx, Cmd, argtable, false);
3817 CLIParserFree(ctx);
3819 size_t nc_len = strlen(Cmd) + 6;
3820 char *nc = calloc(nc_len, 1);
3821 if (nc == NULL) {
3822 return CmdHF14AMfELoad(Cmd);
3825 snprintf(nc, nc_len, "%s --ul", Cmd);
3826 int res = CmdHF14AMfELoad(nc);
3827 free(nc);
3829 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfu sim -t 7`") " to simulate an Amiibo.");
3830 PrintAndLogEx(INFO, "Done!");
3831 return res;
3835 // Simulate tag
3837 static int CmdHF14AMfUSim(const char *Cmd) {
3838 CLIParserContext *ctx;
3839 CLIParserInit(&ctx, "hf mfu sim",
3840 "Simulate MIFARE Ultralight family type based upon\n"
3841 "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
3842 "from emulator memory. See `hf mfu eload` first. \n"
3843 "The UID from emulator memory will be used if not specified.\n"
3844 "See `hf 14a sim -h` to see available types. You want 2 or 7 usually.",
3845 "hf mfu sim -t 2 --uid 11223344556677 -> MIFARE Ultralight\n"
3846 "hf mfu sim -t 7 --uid 11223344556677 -n 5 -> MFU EV1 / NTAG 215 Amiibo\n"
3847 "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo"
3850 void *argtable[] = {
3851 arg_param_begin,
3852 arg_int1("t", "type", "<1..12> ", "Simulation type to use"),
3853 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
3854 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks. 0 = infinite"),
3855 arg_lit0("v", "verbose", "Verbose output"),
3856 arg_param_end
3858 CLIExecWithReturn(ctx, Cmd, argtable, false);
3859 CLIParserFree(ctx);
3860 return CmdHF14ASim(Cmd);
3863 //-------------------------------------------------------------------------------
3864 // Ultralight C Methods
3865 //-------------------------------------------------------------------------------
3867 // Ultralight C Authentication
3869 static int CmdHF14AMfUCAuth(const char *Cmd) {
3870 CLIParserContext *ctx;
3871 CLIParserInit(&ctx, "hf mfu cauth",
3872 "Tests 3DES password on Mifare Ultralight-C tag.\n"
3873 "If password is not specified, a set of known defaults will be tested.",
3874 "hf mfu cauth\n"
3875 "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f"
3878 void *argtable[] = {
3879 arg_param_begin,
3880 arg_str0(NULL, "key", "<hex>", "Authentication key (UL-C 16 hex bytes)"),
3881 arg_lit0("l", NULL, "Swap entered key's endianness"),
3882 arg_lit0("k", NULL, "Keep field on (only if a password is provided)"),
3883 arg_param_end
3885 CLIExecWithReturn(ctx, Cmd, argtable, true);
3887 int ak_len = 0;
3888 uint8_t authenticationkey[16] = {0x00};
3889 uint8_t *authKeyPtr = authenticationkey;
3890 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
3891 bool swap_endian = arg_get_lit(ctx, 2);
3892 bool keep_field_on = arg_get_lit(ctx, 3);
3893 CLIParserFree(ctx);
3895 if (ak_len != 16 && ak_len != 0) {
3896 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length");
3897 return PM3_EINVARG;
3900 // Swap endianness
3901 if (swap_endian && ak_len) {
3902 authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
3905 int isok;
3907 // If no hex key is specified, try default keys
3908 if (ak_len == 0) {
3909 isok = try_default_3des_keys(false, &authKeyPtr);
3910 } else {
3911 // try user-supplied
3912 isok = ulc_authentication(authKeyPtr, !keep_field_on);
3915 if (isok == PM3_SUCCESS) {
3916 PrintAndLogEx(SUCCESS, "Authentication 3DES key... " _GREEN_("%s") " ( " _GREEN_("ok")" )", sprint_hex_inrow(authKeyPtr, 16));
3917 } else {
3918 PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " )");
3920 return PM3_SUCCESS;
3924 A test function to validate that the polarssl-function works the same
3925 was as the openssl-implementation.
3926 Commented out, since it requires openssl
3928 static int CmdTestDES(const char * cmd)
3930 uint8_t key[16] = {0x00};
3932 memcpy(key,key3_3des_data,16);
3933 DES_cblock RndA, RndB;
3935 PrintAndLogEx(NORMAL, "----------OpenSSL DES implementation----------");
3937 uint8_t e_RndB[8] = {0x00};
3938 unsigned char RndARndB[16] = {0x00};
3940 DES_cblock iv = { 0 };
3941 DES_key_schedule ks1,ks2;
3942 DES_cblock key1,key2;
3944 memcpy(key,key3_3des_data,16);
3945 memcpy(key1,key,8);
3946 memcpy(key2,key+8,8);
3949 DES_set_key((DES_cblock *)key1,&ks1);
3950 DES_set_key((DES_cblock *)key2,&ks2);
3952 DES_random_key(&RndA);
3953 PrintAndLogEx(NORMAL, " RndA:%s",sprint_hex(RndA, 8));
3954 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(e_RndB, 8));
3955 //void DES_ede2_cbc_encrypt(const unsigned char *input,
3956 // unsigned char *output, long length, DES_key_schedule *ks1,
3957 // DES_key_schedule *ks2, DES_cblock *ivec, int enc);
3958 DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
3960 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(RndB, 8));
3961 rol(RndB,8);
3962 memcpy(RndARndB,RndA,8);
3963 memcpy(RndARndB+8,RndB,8);
3964 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(RndARndB, 16));
3965 DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
3966 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(RndARndB, 16));
3969 PrintAndLogEx(NORMAL, "----------PolarSSL implementation----------");
3971 uint8_t random_a[8] = { 0 };
3972 uint8_t enc_random_a[8] = { 0 };
3973 uint8_t random_b[8] = { 0 };
3974 uint8_t enc_random_b[8] = { 0 };
3975 uint8_t random_a_and_b[16] = { 0 };
3976 des3_context ctx = { 0 };
3978 memcpy(random_a, RndA,8);
3980 uint8_t output[8] = { 0 };
3981 uint8_t iv[8] = { 0 };
3983 PrintAndLogEx(NORMAL, " RndA :%s",sprint_hex(random_a, 8));
3984 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(enc_random_b, 8));
3986 des3_set2key_dec(&ctx, key);
3988 des3_crypt_cbc(&ctx // des3_context *ctx
3989 , DES_DECRYPT // int mode
3990 , sizeof(random_b) // size_t length
3991 , iv // unsigned char iv[8]
3992 , enc_random_b // const unsigned char *input
3993 , random_b // unsigned char *output
3996 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(random_b, 8));
3998 rol(random_b,8);
3999 memcpy(random_a_and_b ,random_a,8);
4000 memcpy(random_a_and_b+8,random_b,8);
4002 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(random_a_and_b, 16));
4004 des3_set2key_enc(&ctx, key);
4006 des3_crypt_cbc(&ctx // des3_context *ctx
4007 , DES_ENCRYPT // int mode
4008 , sizeof(random_a_and_b) // size_t length
4009 , enc_random_b // unsigned char iv[8]
4010 , random_a_and_b // const unsigned char *input
4011 , random_a_and_b // unsigned char *output
4014 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
4016 return 0;
4021 // Mifare Ultralight C - Set password
4023 static int CmdHF14AMfUCSetPwd(const char *Cmd) {
4024 CLIParserContext *ctx;
4025 CLIParserInit(&ctx, "hf mfu setpwd",
4026 "Set the 3DES key on MIFARE Ultralight-C tag. ",
4027 "hf mfu setpwd --key 000102030405060708090a0b0c0d0e0f"
4030 void *argtable[] = {
4031 arg_param_begin,
4032 arg_str0("k", "key", "<hex>", "New key (16 hex bytes)"),
4033 arg_param_end
4035 CLIExecWithReturn(ctx, Cmd, argtable, true);
4037 int k_len = 0;
4038 uint8_t key[16] = {0x00};
4039 CLIGetHexWithReturn(ctx, 1, key, &k_len);
4040 CLIParserFree(ctx);
4042 if (k_len != 16) {
4043 PrintAndLogEx(WARNING, "Key must be 16 hex bytes");
4044 return PM3_EINVARG;
4047 clearCommandBuffer();
4048 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, key, sizeof(key));
4050 PacketResponseNG resp;
4051 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4052 if ((resp.oldarg[0] & 0xff) == 1) {
4053 PrintAndLogEx(INFO, "Ultralight-C new key... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key)));
4054 } else {
4055 PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
4056 return PM3_ESOFT;
4058 } else {
4059 PrintAndLogEx(WARNING, "command execute timeout");
4060 return PM3_ETIMEOUT;
4062 return PM3_SUCCESS;
4066 // Magic UL / UL-C tags - Set UID
4068 static int CmdHF14AMfUCSetUid(const char *Cmd) {
4070 CLIParserContext *ctx;
4071 CLIParserInit(&ctx, "hf mfu setuid",
4072 "Set UID on MIFARE Ultralight tag.\n"
4073 "This only works for `magic Ultralight` tags.",
4074 "hf mfu setuid --uid 11223344556677"
4077 void *argtable[] = {
4078 arg_param_begin,
4079 arg_str0("u", "uid", "<hex>", "New UID (7 hex bytes)"),
4080 arg_param_end
4082 CLIExecWithReturn(ctx, Cmd, argtable, true);
4084 int u_len = 0;
4085 uint8_t uid[7] = {0x00};
4086 CLIGetHexWithReturn(ctx, 1, uid, &u_len);
4087 CLIParserFree(ctx);
4089 if (u_len != 7) {
4090 PrintAndLogEx(WARNING, "UID must be 7 hex bytes");
4091 return PM3_EINVARG;
4094 PrintAndLogEx(INFO, "Please ignore possible transient BCC warnings");
4096 // read block2.
4097 PacketResponseNG resp;
4098 clearCommandBuffer();
4099 SendCommandMIX(CMD_HF_MIFAREU_READBL, 2, 0, 0, NULL, 0);
4100 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4101 PrintAndLogEx(WARNING, "Command execute timeout");
4102 return PM3_ETIMEOUT;
4105 // save old block2.
4106 uint8_t oldblock2[4] = {0x00};
4107 memcpy(resp.data.asBytes, oldblock2, 4);
4109 // Enforce bad BCC handling temporarily as BCC will be wrong between
4110 // block 1 write and block2 write
4111 hf14a_config config;
4112 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG, NULL, 0);
4113 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG, &resp, 2000)) {
4114 PrintAndLogEx(WARNING, "command execute timeout");
4115 return PM3_ETIMEOUT;
4117 memcpy(&config, resp.data.asBytes, sizeof(hf14a_config));
4118 int8_t oldconfig_bcc = config.forcebcc;
4119 if (oldconfig_bcc != 2) {
4120 config.forcebcc = 2;
4121 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)&config, sizeof(hf14a_config));
4124 // block 0.
4125 uint8_t data[4];
4126 data[0] = uid[0];
4127 data[1] = uid[1];
4128 data[2] = uid[2];
4129 data[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
4130 clearCommandBuffer();
4131 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 0, 0, 0, data, sizeof(data));
4132 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4133 PrintAndLogEx(WARNING, "Command execute timeout");
4134 return PM3_ETIMEOUT;
4137 // block 1.
4138 data[0] = uid[3];
4139 data[1] = uid[4];
4140 data[2] = uid[5];
4141 data[3] = uid[6];
4142 clearCommandBuffer();
4143 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 1, 0, 0, data, sizeof(data));
4144 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4145 PrintAndLogEx(WARNING, "Command execute timeout");
4146 return PM3_ETIMEOUT;
4149 // block 2.
4150 data[0] = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
4151 data[1] = oldblock2[1];
4152 data[2] = oldblock2[2];
4153 data[3] = oldblock2[3];
4154 clearCommandBuffer();
4155 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 2, 0, 0, data, sizeof(data));
4156 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4157 PrintAndLogEx(WARNING, "Command execute timeout");
4158 return PM3_ETIMEOUT;
4161 // restore BCC config
4162 if (oldconfig_bcc != 2) {
4163 config.forcebcc = oldconfig_bcc;
4164 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)&config, sizeof(hf14a_config));
4166 return PM3_SUCCESS;
4169 static int CmdHF14AMfUKeyGen(const char *Cmd) {
4170 CLIParserContext *ctx;
4171 CLIParserInit(&ctx, "hf mfu keygen",
4172 "Calculate MFC keys based ",
4173 "hf mfu keygen -r\n"
4174 "hf mfu keygen --uid 11223344556677"
4177 void *argtable[] = {
4178 arg_param_begin,
4179 arg_str0("u", "uid", "<hex>", "<4|7> hex byte UID"),
4180 arg_lit0("r", NULL, "Read UID from tag"),
4181 arg_u64_0("b", "blk", "<dec>", "Block number"),
4182 arg_param_end
4184 CLIExecWithReturn(ctx, Cmd, argtable, true);
4186 int ulen = 0;
4187 uint8_t uid[7];
4188 CLIGetHexWithReturn(ctx, 1, uid, &ulen);
4189 bool read_tag = arg_get_lit(ctx, 2);
4190 uint8_t block = arg_get_u64_def(ctx, 3, 1) & 0xFF;
4191 CLIParserFree(ctx);
4193 if (read_tag) {
4194 // read uid from tag
4195 clearCommandBuffer();
4196 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
4197 PacketResponseNG resp;
4198 WaitForResponse(CMD_ACK, &resp);
4199 iso14a_card_select_t card;
4200 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
4202 uint64_t select_status = resp.oldarg[0];
4203 // 0: couldn't read,
4204 // 1: OK, with ATS
4205 // 2: OK, no ATS
4206 // 3: proprietary Anticollision
4208 if (select_status == 0) {
4209 PrintAndLogEx(WARNING, "iso14443a card select failed");
4210 return PM3_ESOFT;
4213 if (card.uidlen != 4 && card.uidlen != 7) {
4214 PrintAndLogEx(WARNING, "Wrong sized UID, expected 4|7 bytes got %d", card.uidlen);
4215 return PM3_ESOFT;
4217 ulen = card.uidlen;
4218 memcpy(uid, card.uid, card.uidlen);
4219 } else {
4220 if (ulen != 4 && ulen != 7) {
4221 PrintAndLogEx(ERR, "Must supply 4 or 7 hex byte uid");
4222 return PM3_EINVARG;
4226 uint8_t iv[8] = { 0x00 };
4228 uint8_t mifarekeyA[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
4229 uint8_t mifarekeyB[] = { 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5 };
4230 uint8_t dkeyA[8] = { 0x00 };
4231 uint8_t dkeyB[8] = { 0x00 };
4233 uint8_t masterkey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
4234 uint8_t mix[8] = { 0x00 };
4235 uint8_t divkey[8] = { 0x00 };
4237 memcpy(mix, mifarekeyA, 4);
4239 mix[4] = mifarekeyA[4] ^ uid[0];
4240 mix[5] = mifarekeyA[5] ^ uid[1];
4241 mix[6] = block ^ uid[2];
4242 mix[7] = uid[3];
4244 mbedtls_des3_context ctx_des3;
4245 mbedtls_des3_set2key_enc(&ctx_des3, masterkey);
4247 mbedtls_des3_crypt_cbc(&ctx_des3 // des3_context
4248 , MBEDTLS_DES_ENCRYPT // int mode
4249 , sizeof(mix) // length
4250 , iv // iv[8]
4251 , mix // input
4252 , divkey // output
4255 PrintAndLogEx(SUCCESS, "-- 3DES version");
4256 PrintAndLogEx(SUCCESS, "Masterkey......... %s", sprint_hex(masterkey, sizeof(masterkey)));
4257 PrintAndLogEx(SUCCESS, "UID............... %s", sprint_hex(uid, ulen));
4258 PrintAndLogEx(SUCCESS, "block............. %0d", block);
4259 PrintAndLogEx(SUCCESS, "Mifare key........ %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA)));
4260 PrintAndLogEx(SUCCESS, "Message........... %s", sprint_hex(mix, sizeof(mix)));
4261 PrintAndLogEx(SUCCESS, "Diversified key... %s", sprint_hex(divkey + 1, 6));
4263 for (int i = 0; i < ARRAYLEN(mifarekeyA); ++i) {
4264 dkeyA[i] = (mifarekeyA[i] << 1) & 0xff;
4265 dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i + 1);
4268 for (int i = 0; i < ARRAYLEN(mifarekeyB); ++i) {
4269 dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i + 1);
4270 dkeyB[2 + i] = (mifarekeyB[i] << 1) & 0xff;
4273 uint8_t zeros[8] = {0x00};
4274 uint8_t newpwd[8] = {0x00};
4275 uint8_t dmkey[24] = {0x00};
4276 memcpy(dmkey, dkeyA, 8);
4277 memcpy(dmkey + 8, dkeyB, 8);
4278 memcpy(dmkey + 16, dkeyA, 8);
4279 memset(iv, 0x00, 8);
4281 mbedtls_des3_set3key_enc(&ctx_des3, dmkey);
4283 mbedtls_des3_crypt_cbc(&ctx_des3 // des3_context
4284 , MBEDTLS_DES_ENCRYPT // int mode
4285 , sizeof(newpwd) // length
4286 , iv // iv[8]
4287 , zeros // input
4288 , newpwd // output
4291 PrintAndLogEx(SUCCESS, "\n-- DES version");
4292 PrintAndLogEx(SUCCESS, "MIFARE dkeyA...... %s", sprint_hex(dkeyA, sizeof(dkeyA)));
4293 PrintAndLogEx(SUCCESS, "MIFARE dkeyB...... %s", sprint_hex(dkeyB, sizeof(dkeyB)));
4294 PrintAndLogEx(SUCCESS, "MIFARE ABA........ %s", sprint_hex(dmkey, sizeof(dmkey)));
4295 PrintAndLogEx(SUCCESS, "MIFARE PWD........ %s", sprint_hex(newpwd, sizeof(newpwd)));
4297 mbedtls_des3_free(&ctx_des3);
4299 mbedtls_aes_context ctx_aes;
4300 uint8_t aes_iv[16] = { 0x00 };
4301 uint8_t aes_masterkey[] = { 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
4302 uint8_t aes_input[16] = {0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80, 0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80};
4303 uint8_t aes_output[16] = {0x00};
4304 mbedtls_aes_setkey_enc(&ctx_aes, aes_masterkey, 128);
4305 mbedtls_aes_crypt_cbc(&ctx_aes, MBEDTLS_AES_ENCRYPT, 16, aes_iv, aes_input, aes_output);
4306 mbedtls_aes_free(&ctx_aes);
4308 PrintAndLogEx(SUCCESS, "\n-- AES version");
4309 PrintAndLogEx(SUCCESS, "MIFARE AES mk..... %s", sprint_hex(aes_masterkey, sizeof(aes_masterkey)));
4310 PrintAndLogEx(SUCCESS, "MIFARE Div........ %s", sprint_hex(aes_output, sizeof(aes_output)));
4312 // next. from the diversify_key method.
4313 return PM3_SUCCESS;
4316 static int CmdHF14AMfUPwdGen(const char *Cmd) {
4317 CLIParserContext *ctx;
4318 CLIParserInit(&ctx, "hf mfu pwdgen",
4319 "Generate different passwords from known pwdgen algos",
4320 "hf mfu pwdgen -r\n"
4321 "hf mfu pwdgen --uid 11223344556677\n"
4322 "hf mfu pwdgen --test"
4325 void *argtable[] = {
4326 arg_param_begin,
4327 arg_str0("u", "uid", "<hex>", "UID (7 hex bytes)"),
4328 arg_lit0("r", NULL, "Read UID from tag"),
4329 arg_lit0(NULL, "test", "self test"),
4330 arg_param_end
4332 CLIExecWithReturn(ctx, Cmd, argtable, true);
4334 int u_len = 0;
4335 uint8_t uid[7] = {0x00};
4336 CLIGetHexWithReturn(ctx, 1, uid, &u_len);
4337 bool use_tag = arg_get_lit(ctx, 2);
4338 bool selftest = arg_get_lit(ctx, 3);
4339 CLIParserFree(ctx);
4341 if (selftest) {
4342 return generator_selftest();
4345 uint8_t philips_mfg[10] = {0};
4347 if (use_tag) {
4348 // read uid from tag
4349 int res = ul_read_uid(uid);
4350 if (res == PM3_ELENGTH) {
4351 // got 4 byte UID, lets adapt to 7 bytes :)
4352 memset(uid + 4, 0x00, 3);
4353 u_len = 7;
4354 } else {
4356 if (res != PM3_SUCCESS) {
4357 return res;
4360 iso14a_card_select_t card;
4361 if (ul_select(&card)) {
4362 // Philips toothbrush needs page 0x21-0x23
4363 uint8_t data[16] = {0x00};
4364 int status = ul_read(0x21, data, sizeof(data));
4365 if (status <= 0) {
4366 PrintAndLogEx(DEBUG, "Error: tag didn't answer to READ");
4367 } else if (status == 16) {
4368 memcpy(philips_mfg, data + 2, sizeof(philips_mfg));
4370 DropField();
4373 } else {
4374 if (u_len != 7 && u_len != 4) {
4375 PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
4376 return PM3_EINVARG;
4377 } else {
4378 // adapt to 7 bytes :)
4379 memset(uid + 4, 0x00, 3);
4380 u_len = 7;
4384 PrintAndLogEx(INFO, "-----------------------------------");
4385 PrintAndLogEx(INFO, " UID 4b... " _YELLOW_("%s"), sprint_hex(uid, 4));
4386 PrintAndLogEx(INFO, " UID 7b... " _YELLOW_("%s"), sprint_hex(uid, 7));
4387 PrintAndLogEx(INFO, "-----------------------------------");
4388 PrintAndLogEx(INFO, " algo pwd pack");
4389 PrintAndLogEx(INFO, "-----------------------------+-----");
4390 PrintAndLogEx(INFO, " Transport EV1..... %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
4391 PrintAndLogEx(INFO, " Amiibo............ %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
4392 PrintAndLogEx(INFO, " Lego Dimension.... %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
4393 PrintAndLogEx(INFO, " XYZ 3D printer.... %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
4394 PrintAndLogEx(INFO, " Xiaomi purifier... %08X | %04X", ul_ev1_pwdgenE(uid), ul_ev1_packgenE(uid));
4395 PrintAndLogEx(INFO, " NTAG tools........ %08X | %04X", ul_ev1_pwdgenF(uid), ul_ev1_packgen_def(uid));
4396 if (philips_mfg[0] != 0) {
4397 PrintAndLogEx(INFO, " Philips Toothbrush | %08X | %04X", ul_ev1_pwdgenG(uid, philips_mfg), ul_ev1_packgenG(uid, philips_mfg));
4399 PrintAndLogEx(INFO, "-----------------------------+-----");
4400 PrintAndLogEx(INFO, _CYAN_("Vingcard"));
4401 uint64_t key = 0;
4402 mfc_algo_saflok_one(uid, 0, 0, &key);
4403 PrintAndLogEx(INFO, " Saflok algo | %012" PRIX64, key);
4404 PrintAndLogEx(INFO, " SALTO algo");
4405 PrintAndLogEx(INFO, " Dorma Kaba algo");
4406 PrintAndLogEx(INFO, " STiD algo");
4407 PrintAndLogEx(INFO, "-------------------------------------");
4408 return PM3_SUCCESS;
4412 // MFU TearOff against OTP
4413 // Moebius et al
4415 static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
4416 CLIParserContext *ctx;
4417 CLIParserInit(&ctx, "hf mfu otptear",
4418 "Tear-off test against OTP block",
4419 "hf mfu otptear -b 3\n"
4420 "hf mfu otptear -b 3 -i 100 -s 1000\n"
4421 "hf mfu otptear -b 3 -i 1 -e 200\n"
4422 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE\n"
4423 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quit when OTP is reset"
4426 void *argtable[] = {
4427 arg_param_begin,
4428 arg_u64_0("b", "blk", "<dec>", "target block (def 8)"),
4429 arg_u64_0("i", "inc", "<dec>", "increase time steps (def 500 us)"),
4430 arg_u64_0("e", "end", "<dec>", "end time (def 3000 us)"),
4431 arg_u64_0("s", "start", "<dec>", "start time (def 0 us)"),
4432 arg_str0("d", "data", "<hex>", "initialise data before run (4 bytes)"),
4433 arg_str0("t", "test", "<hex>", "test write data (4 bytes, 00000000 by default)"),
4434 arg_str0("m", "match", "<hex>", "exit criteria, if block matches this value (4 bytes)"),
4435 arg_param_end
4437 CLIExecWithReturn(ctx, Cmd, argtable, true);
4439 uint8_t blockno = arg_get_u32_def(ctx, 1, 8);
4440 uint32_t steps = arg_get_u32_def(ctx, 2, 500);
4441 uint32_t end = arg_get_u32_def(ctx, 3, 3000);
4442 uint32_t start = arg_get_u32_def(ctx, 4, 0);
4444 int d_len = 0;
4445 uint8_t data[4] = {0x00};
4446 CLIGetHexWithReturn(ctx, 5, data, &d_len);
4447 bool use_data = (d_len > 0);
4449 int t_len = 0;
4450 uint8_t test[4] = {0x00};
4451 CLIGetHexWithReturn(ctx, 6, test, &t_len);
4453 int m_len = 0;
4454 uint8_t match[4] = {0x00};
4455 CLIGetHexWithReturn(ctx, 7, match, &m_len);
4456 bool use_match = (m_len > 0);
4457 CLIParserFree(ctx);
4459 if (blockno < 2) {
4460 PrintAndLogEx(WARNING, "Block number must be larger than 2.");
4461 return PM3_EINVARG;
4463 if (end < steps) {
4464 PrintAndLogEx(WARNING, "end time smaller than increase value");
4465 return PM3_EINVARG;
4467 if (end > 43000) {
4468 PrintAndLogEx(WARNING, "end time - out of 1 .. 43000 range");
4469 return PM3_EINVARG;
4471 if (start > (end - steps)) {
4472 PrintAndLogEx(WARNING, "Start time larger than (end time + steps)");
4473 return PM3_EINVARG;
4476 if (d_len && d_len != 4) {
4477 PrintAndLogEx(WARNING, "data must be 4 hex bytes");
4478 return PM3_EINVARG;
4481 if (t_len && t_len != 4) {
4482 PrintAndLogEx(WARNING, "test data must be 4 hex bytes");
4483 return PM3_EINVARG;
4486 if (m_len && m_len != 4) {
4487 PrintAndLogEx(WARNING, "match data must be 4 hex bytes");
4488 return PM3_EINVARG;
4491 uint8_t teardata[4] = {0x00};
4492 memcpy(teardata, test, sizeof(test));
4494 PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Tear off") " ---------------------");
4495 PrintAndLogEx(INFO, "Starting Tear-off test");
4496 PrintAndLogEx(INFO, "Target block no: %u", blockno);
4497 if (use_data) {
4498 PrintAndLogEx(INFO, "Target initial block data : %s", sprint_hex_inrow(data, 4));
4500 PrintAndLogEx(INFO, "Target write block data : %s", sprint_hex_inrow(teardata, 4));
4501 if (use_match) {
4502 PrintAndLogEx(INFO, "Target match block data : %s", sprint_hex_inrow(match, 4));
4504 PrintAndLogEx(INFO, "----------------------------------------------------");
4505 uint8_t isOK;
4506 bool lock_on = false;
4507 uint8_t pre[4] = {0};
4508 uint8_t post[4] = {0};
4509 uint32_t current = start;
4510 int phase_begin_clear = -1;
4511 int phase_end_clear = -1;
4512 int phase_begin_newwr = -1;
4513 int phase_end_newwr = -1;
4514 bool skip_phase1 = false;
4515 uint8_t retries = 0;
4516 uint8_t error_retries = 0;
4518 while ((current <= (end - steps)) && (error_retries < 10)) {
4520 if (kbd_enter_pressed()) {
4521 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
4522 break;
4525 PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", current);
4527 clearCommandBuffer();
4528 PacketResponseNG resp;
4530 if (use_data) {
4531 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, 0, 0, data, d_len);
4532 bool got_written = false;
4533 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4534 isOK = resp.oldarg[0] & 0xff;
4535 if (isOK) {
4536 got_written = true;
4539 if (! got_written) {
4540 PrintAndLogEx(FAILED, "Failed to write block BEFORE");
4541 error_retries++;
4542 continue; // try again
4546 SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0);
4548 bool got_pre = false;
4549 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4550 isOK = resp.oldarg[0] & 0xFF;
4551 if (isOK) {
4552 memcpy(pre, resp.data.asBytes, sizeof(pre));
4553 got_pre = true;
4556 if (! got_pre) {
4557 PrintAndLogEx(FAILED, "Failed to read block BEFORE");
4558 error_retries++;
4559 continue; // try again
4561 clearCommandBuffer();
4562 SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockno, current, 0, teardata, sizeof(teardata));
4564 // we be getting ACK that we are silently ignoring here..
4566 if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
4567 PrintAndLogEx(WARNING, "Failed");
4568 return PM3_ESOFT;
4571 if (resp.status != PM3_SUCCESS) {
4572 PrintAndLogEx(WARNING, "Tear off reporting failure to select tag");
4573 error_retries++;
4574 continue;
4577 bool got_post = false;
4578 clearCommandBuffer();
4579 SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0);
4580 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4581 isOK = resp.oldarg[0] & 0xFF;
4582 if (isOK) {
4583 memcpy(post, resp.data.asBytes, sizeof(post));
4584 got_post = true;
4587 if (! got_post) {
4588 PrintAndLogEx(FAILED, "Failed to read block BEFORE");
4589 error_retries++;
4590 continue; // try again
4592 error_retries = 0;
4593 char prestr[20] = {0};
4594 snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
4595 char poststr[20] = {0};
4596 snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
4598 if (memcmp(pre, post, sizeof(pre)) == 0) {
4600 PrintAndLogEx(INFO, "Current : %02d (0x%02X) %s"
4601 , blockno
4602 , blockno
4603 , poststr
4605 } else {
4606 PrintAndLogEx(INFO, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s")
4607 , blockno
4608 , blockno
4609 , prestr
4610 , poststr
4613 lock_on = true;
4615 uint32_t post32 = bytes_to_num(post, 4);
4616 uint32_t pre32 = bytes_to_num(pre, 4);
4618 if ((phase_begin_clear == -1) && (bitcount32(pre32) > bitcount32(post32)))
4619 phase_begin_clear = current;
4621 if ((phase_begin_clear > -1) && (phase_end_clear == -1) && (bitcount32(post32) == 0))
4622 phase_end_clear = current;
4624 if ((current == start) && (phase_end_clear > -1))
4625 skip_phase1 = true;
4626 // new write phase must be atleast 100us later..
4627 if (((bitcount32(pre32) == 0) || (phase_end_clear > -1)) && (phase_begin_newwr == -1) && (bitcount32(post32) != 0) && (skip_phase1 || (current > (phase_end_clear + 100))))
4628 phase_begin_newwr = current;
4630 if ((phase_begin_newwr > -1) && (phase_end_newwr == -1) && (memcmp(post, teardata, sizeof(teardata)) == 0))
4631 phase_end_newwr = current;
4634 if (use_match && memcmp(post, match, sizeof(post)) == 0) {
4635 PrintAndLogEx(SUCCESS, "Block matches stop condition!\n");
4636 break;
4639 /* TEMPORALLY DISABLED
4640 uint8_t d0, d1, d2, d3;
4641 d0 = *resp.data.asBytes;
4642 d1 = *(resp.data.asBytes + 1);
4643 d2 = *(resp.data.asBytes + 2);
4644 d3 = *(resp.data.asBytes + 3);
4645 if ((d0 != 0xFF) || (d1 != 0xFF) || (d2 != 0xFF) || (d3 = ! 0xFF)) {
4646 PrintAndLogEx(NORMAL, "---------------------------------");
4647 PrintAndLogEx(NORMAL, " EFFECT AT: %d us", actualTime);
4648 PrintAndLogEx(NORMAL, "---------------------------------\n");
4651 if (start != end) {
4652 current += steps;
4653 } else {
4654 if (lock_on == false) {
4655 if (++retries == 20) {
4656 current++;
4657 end++;
4658 start++;
4659 retries = 0;
4660 PrintAndLogEx(INFO, _CYAN_("Retried %u times, increased delay with 1us"), retries);
4666 PrintAndLogEx(INFO, "----------------------------------------------------");
4667 if ((phase_begin_clear > - 1) && (phase_begin_clear != start)) {
4668 PrintAndLogEx(INFO, "Erase phase start boundary around " _YELLOW_("%5d") " us", phase_begin_clear);
4670 if ((phase_end_clear > - 1) && (phase_end_clear != start)) {
4671 PrintAndLogEx(INFO, "Erase phase end boundary around " _YELLOW_("%5d") " us", phase_end_clear);
4673 if (phase_begin_newwr > - 1) {
4674 PrintAndLogEx(INFO, "Write phase start boundary around " _YELLOW_("%5d") " us", phase_begin_newwr);
4676 if (phase_end_newwr > - 1) {
4677 PrintAndLogEx(INFO, "Write phase end boundary around " _YELLOW_("%5d") " us", phase_end_newwr);
4679 PrintAndLogEx(NORMAL, "");
4680 return PM3_SUCCESS;
4684 static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
4686 PrintAndLogEx(INFO, "Reset tear check");
4688 uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00};
4689 uint8_t ct[1] = {0};
4690 uint8_t resp[10] = {0};
4692 if (ul_select(card) == false) {
4693 PrintAndLogEx(FAILED, "failed to select card, exiting...");
4694 return PM3_ESOFT;
4696 if (ul_send_cmd_raw(cw, sizeof(cw), resp, sizeof(resp)) < 0) {
4697 PrintAndLogEx(FAILED, "failed to write all ZEROS");
4698 return PM3_ESOFT;
4700 if (ulev1_readTearing(cnt_no, ct, sizeof(ct)) < 0) {
4701 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
4702 return PM3_ESOFT;
4704 DropField();
4706 if (ct[0] != 0xBD) {
4707 PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
4708 return PM3_ESOFT;
4710 return PM3_SUCCESS;
4715 static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
4717 CLIParserContext *ctx;
4718 CLIParserInit(&ctx, "hf mfu countertear",
4719 "Tear-off test against a Ev1 counter",
4720 "hf mfu countertear\n"
4721 "hf mfu countertear -s 200 -l 2500 -> target counter 0, start delay 200\n"
4722 "hf mfu countertear -i 2 -s 200 -l 400 -> target counter 0, start delay 200\n"
4725 void *argtable[] = {
4726 arg_param_begin,
4727 arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
4728 arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
4729 arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
4730 arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
4731 arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"),
4732 arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"),
4733 arg_param_end
4735 CLIExecWithReturn(ctx, Cmd, argtable, false);
4737 int interval = 0;
4738 int time_limit, start_time = 0;
4739 int counter = arg_get_int_def(ctx, 1, 0);
4740 int fixed = arg_get_int_def(ctx, 5, -1);
4742 if ( fixed == -1 ) {
4743 interval = arg_get_int_def(ctx, 2, 10);
4744 time_limit = arg_get_int_def(ctx, 3, 3000);
4745 start_time = arg_get_int_def(ctx, 4, 0);
4746 } else {
4747 start_time = fixed;
4748 interval = 0;
4749 time_limit = fixed;
4752 uint8_t newvalue[5] = {0};
4753 int newvaluelen = 0;
4754 CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
4755 CLIParserFree(ctx);
4757 // Validations
4758 if (start_time > (time_limit - interval)) {
4759 PrintAndLogEx(WARNING, "Wrong start time number");
4760 return PM3_EINVARG;
4762 if (time_limit < interval) {
4763 PrintAndLogEx(WARNING, "Wrong time limit number");
4764 return PM3_EINVARG;
4766 if (time_limit > 43000) {
4767 PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
4768 return PM3_EINVARG;
4770 uint8_t cnt_no = 0;
4771 if (counter < 0 || counter > 2) {
4772 PrintAndLogEx(WARNING, "Counter must 0, 1 or 2");
4773 return PM3_EINVARG;
4776 cnt_no = (uint8_t)counter;
4778 iso14a_card_select_t card;
4780 // reset counter tear
4781 counter_reset_tear(&card, cnt_no);
4783 if (ul_select(&card) == false) {
4784 PrintAndLogEx(INFO, "failed to select card, exiting...");
4785 return PM3_ESOFT;
4788 uint8_t initial_cnt[3] = {0, 0, 0};
4789 int len = ulev1_readCounter(cnt_no, initial_cnt, sizeof(initial_cnt));
4790 if ( len != sizeof(initial_cnt) ) {
4791 PrintAndLogEx(WARNING, "failed to read counter");
4792 return PM3_ESOFT;
4795 uint8_t initial_tear[1] = {0};
4796 len = ulev1_readTearing(cnt_no, initial_tear, sizeof(initial_tear));
4797 DropField();
4798 if ( len != sizeof(initial_tear) ) {
4799 PrintAndLogEx(WARNING, "failed to read ANTITEAR, exiting... %d", len);
4800 return PM3_ESOFT;
4803 uint32_t wr_value = ( newvalue[0] | newvalue[1] << 8 | newvalue[2] << 16 );
4804 uint32_t initial_value = ( initial_cnt[0] | initial_cnt[1] << 8 | initial_cnt[2] << 16 );;
4806 PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
4807 PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter);
4808 PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(initial_cnt, sizeof(initial_cnt)));
4809 PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", initial_tear[0]);
4810 PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen));
4811 PrintAndLogEx(INFO, "----------------------------------------------------");
4813 uint8_t pre_tear = 0, post_tear = 0;
4814 uint8_t pre[3] = {0};
4815 uint8_t post[3] = {0};
4816 uint32_t actual_time = start_time;
4817 uint32_t a = 0, b = 0;
4818 uint32_t loop = 0;
4820 uint16_t late = 0;
4822 while (actual_time <= (time_limit - interval)) {
4824 DropField();
4826 loop++;
4828 if (kbd_enter_pressed()) {
4829 PrintAndLogEx(INFO, "\naborted via keyboard!\n");
4830 break;
4833 PrintAndLogEx(INPLACE, "Using tear-off delay " _GREEN_("%" PRIu32) " µs (attempt %u)", actual_time, loop);
4835 if (ul_select(&card) == false) {
4836 PrintAndLogEx(FAILED, "BEFORE, failed to select card, looping...");
4837 continue;
4840 uint8_t cntresp[3] = {0, 0, 0};
4841 int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
4842 if ( rlen == sizeof(cntresp) ) {
4843 memcpy(pre, cntresp, sizeof(pre));
4844 } else {
4845 PrintAndLogEx(NORMAL, "");
4846 PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
4847 break;
4850 uint8_t tear[1] = {0};
4851 int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
4852 if ( tlen == sizeof(tear) ) {
4853 pre_tear = tear[0];
4854 } else {
4855 PrintAndLogEx(NORMAL, "");
4856 PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
4857 break;
4860 DropField();
4862 struct p {
4863 uint8_t counter;
4864 uint32_t tearoff_time;
4865 uint8_t value[3];
4866 } PACKED payload;
4867 payload.counter = cnt_no;
4868 payload.tearoff_time = actual_time;
4869 memcpy(payload.value, newvalue, sizeof(payload.value));
4871 clearCommandBuffer();
4872 PacketResponseNG resp;
4873 SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
4874 if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
4875 PrintAndLogEx(WARNING, "\ntear off command failed");
4876 continue;
4879 if (ul_select(&card) == false) {
4880 PrintAndLogEx(FAILED, "AFTER, failed to select card, exiting...");
4881 break;
4884 rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
4885 if ( rlen == sizeof(cntresp) ) {
4886 memcpy(post, cntresp, sizeof(post));
4887 } else {
4888 PrintAndLogEx(NORMAL, "");
4889 PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
4890 break;
4893 tear[0] = 0;
4894 tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
4895 if ( tlen == sizeof(tear) ) {
4896 post_tear = tear[0];
4897 } else {
4898 PrintAndLogEx(NORMAL, "");
4899 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
4900 break;
4903 DropField();
4905 char prestr[20] = {0};
4906 snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
4907 char poststr[20] = {0};
4908 snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
4910 bool post_tear_check = (post_tear == 0xBD);
4911 a = (pre[0] | pre[1] << 8 | pre[2] << 16);
4912 b = (post[0] | post[1] << 8 | post[2] << 16);
4914 // A != B
4915 if (memcmp(pre, post, sizeof(pre)) != 0) {
4918 PrintAndLogEx(NORMAL, "");
4920 if (initial_value != a ) {
4922 if ( initial_value != b )
4923 PrintAndLogEx(INFO, "pre %08x, post %08x != initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4924 else
4925 PrintAndLogEx(INFO, "pre %08x != initial and post %08x == initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4926 } else {
4928 if ( initial_value != b )
4929 PrintAndLogEx(INFO, "pre %08x == initial and post %08x != initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4932 if ( b == 0 ) {
4933 PrintAndLogEx(INFO, _CYAN_("Tear off occurred (ZEROS value!) -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
4934 , prestr
4935 , poststr
4936 , pre_tear
4937 , post_tear
4938 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4940 break;
4943 if ( a > b ) {
4944 PrintAndLogEx(INFO, _CYAN_("Tear off occurred " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
4945 , prestr
4946 , poststr
4947 , pre_tear
4948 , post_tear
4949 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4953 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
4954 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
4955 break;
4958 uint32_t bar = (0x1000000 - b) + 2;
4959 // wr_value = bar;
4960 // newvalue[0] = (bar) & 0xFF;
4961 // newvalue[1] = ((bar >> 8) & 0xFF);
4962 // newvalue[2] = ((bar >> 16) & 0xFF);
4964 wr_value = 0;
4965 newvalue[0] = 0;
4966 newvalue[1] = 0;
4967 newvalue[2] = 0;
4969 PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar);
4970 PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value);
4971 PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b);
4973 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
4974 continue;
4975 } else {
4977 PrintAndLogEx(NORMAL, "");
4978 PrintAndLogEx(INFO, _CYAN_("Tear off occurred (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
4979 , prestr
4980 , poststr
4981 , pre_tear
4982 , post_tear
4983 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4986 if ( post_tear_check && b == initial_value) {
4987 PrintAndLogEx(INFO, "Reverted to previous value");
4988 break;
4990 if ( wr_value != 0 ) {
4992 //uint32_t bar = (0x1000000 - b) + 2;
4993 wr_value = 0;
4994 newvalue[0] = 0;
4995 newvalue[1] = 0;
4996 newvalue[2] = 0;
4998 if ( b >= (initial_value + (2 * wr_value))) {
4999 PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
5002 // wr_value = bar;
5003 // newvalue[0] = (bar) & 0xFF;
5004 // newvalue[1] = ((bar >> 8) & 0xFF);
5005 // newvalue[2] = ((bar >> 16) & 0xFF);
5006 } else {
5008 // wr_value = bar;
5009 // newvalue[0] = (bar) & 0xFF;
5010 // newvalue[1] = ((bar >> 8) & 0xFF);
5011 // newvalue[2] = ((bar >> 16) & 0xFF);
5012 // wr_value = 0;
5013 // newvalue[0] = 0;
5014 // newvalue[1] = 0;
5015 // newvalue[2] = 0;
5019 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
5021 //actual_time--;
5022 late++;
5024 } else {
5025 PrintAndLogEx(NORMAL, "");
5026 PrintAndLogEx(INFO, _CYAN_("Status: same value! -> ") "%s == %s Tear: 0x%02X == 0x%02X ( %s )"
5027 , prestr
5028 , poststr
5029 , pre_tear
5030 , post_tear
5031 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
5034 if ( post_tear_check ) {
5035 if ( a == b ) {
5036 //actual_time--;
5037 continue;
5040 if ( b == initial_value ) {
5041 PrintAndLogEx(INFO, "Reverted to previous value");
5042 break;
5044 } else {
5046 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
5047 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
5048 break;
5054 actual_time += interval;
5057 DropField();
5059 PrintAndLogEx(INFO, " Sent %u tear offs ", loop);
5061 counter_reset_tear(&card, cnt_no);
5063 PrintAndLogEx(INFO, "hf 14a raw -s -c 3900 --> read counter 0");
5064 PrintAndLogEx(INFO, "hf 14a raw -s -c 3e00 --> read tearing 0");
5065 PrintAndLogEx(NORMAL, "");
5066 char read_cnt_str[30];
5067 snprintf(read_cnt_str, sizeof(read_cnt_str), "hf 14a raw -s -c 39%02x", counter);
5068 CommandReceived(read_cnt_str);
5069 char read_tear_str[30];
5070 snprintf(read_tear_str, sizeof(read_tear_str), "hf 14a raw -s -c 3e%02x", counter);
5071 CommandReceived(read_tear_str);
5072 return PM3_SUCCESS;
5078 // name, identifying bytes, decode function, hints text
5079 // identifying bits
5080 // 1. getversion data must match.
5081 // 2. magic bytes in the readable payload
5084 int CmdHF14MfuNDEFRead(const char *Cmd) {
5086 int keylen;
5087 int maxsize = 16, status;
5088 bool hasAuthKey = false;
5089 bool swapEndian = false;
5091 iso14a_card_select_t card;
5092 uint8_t data[16] = {0x00};
5093 uint8_t key[16] = {0x00};
5094 uint8_t *p_key = key;
5095 uint8_t pack[4] = {0, 0, 0, 0};
5097 CLIParserContext *ctx;
5098 CLIParserInit(&ctx, "hf mfu ndefread",
5099 "Prints NFC Data Exchange Format (NDEF)",
5100 "hf mfu ndefread -> shows NDEF data\n"
5101 "hf mfu ndefread -k ffffffff -> shows NDEF data with key\n"
5102 "hf mfu ndefread -f myfilename -> save raw NDEF to file"
5105 void *argtable[] = {
5106 arg_param_begin,
5107 arg_str0("k", "key", "Replace default key for NDEF", NULL),
5108 arg_lit0("l", NULL, "Swap entered key's endianness"),
5109 arg_str0("f", "file", "<fn>", "Save raw NDEF to file"),
5110 arg_lit0("v", "verbose", "Verbose output"),
5111 arg_param_end
5113 CLIExecWithReturn(ctx, Cmd, argtable, true);
5114 CLIGetHexWithReturn(ctx, 1, key, &keylen);
5115 swapEndian = arg_get_lit(ctx, 2);
5116 int fnlen = 0;
5117 char filename[FILE_PATH_SIZE] = {0};
5118 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5119 bool verbose = arg_get_lit(ctx, 4);
5120 CLIParserFree(ctx);
5122 switch (keylen) {
5123 case 0:
5124 break;
5125 case 4:
5126 case 16:
5127 hasAuthKey = true;
5128 break;
5129 default:
5130 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
5131 return PM3_EINVARG;
5134 // Get tag type
5135 uint64_t tagtype = GetHF14AMfU_Type();
5136 if (tagtype == MFU_TT_UL_ERROR) {
5137 PrintAndLogEx(WARNING, "No Ultralight / NTAG based tag found");
5138 return PM3_ESOFT;
5141 // Is tag UL/NTAG?
5143 // Swap endianness
5144 if (swapEndian && hasAuthKey) p_key = SwapEndian64(key, keylen, (keylen == 16) ? 8 : 4);
5146 // Select and Auth
5147 if (ul_auth_select(&card, tagtype, hasAuthKey, p_key, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
5149 // read pages 0,1,2,3 (should read 4pages)
5150 status = ul_read(0, data, sizeof(data));
5151 if (status <= 0) {
5152 DropField();
5153 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
5154 return PM3_ESOFT;
5155 } else if (status == 16) {
5157 status = ndef_print_CC(data + 12);
5158 if (status == PM3_ESOFT) {
5159 DropField();
5160 PrintAndLogEx(ERR, "Error: tag didn't contain a NDEF Container");
5161 return PM3_ESOFT;
5164 // max datasize;
5165 maxsize = ndef_get_maxsize(data + 12);
5168 // iceman: maybe always take MIN of tag identified size vs NDEF reported size?
5169 // fix: UL_EV1 48bytes != NDEF reported size
5170 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
5171 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
5173 if (maxsize != (UL_MEMORY_ARRAY[idx] * 4)) {
5174 PrintAndLogEx(INFO, "Tag reported size vs NDEF reported size mismatch. Using smallest value");
5176 maxsize = MIN(maxsize, (UL_MEMORY_ARRAY[idx] * 4));
5177 break;
5181 // The following read will read in blocks of 16 bytes.
5182 // ensure maxsize is rounded up to a multiple of 16
5183 maxsize = maxsize + (16 - (maxsize % 16));
5184 // allocate mem
5185 uint8_t *records = calloc(maxsize, sizeof(uint8_t));
5186 if (records == NULL) {
5187 DropField();
5188 return PM3_EMALLOC;
5191 // read NDEF records.
5192 for (uint32_t i = 0, j = 0; i < maxsize; i += 16, j += 4) {
5193 status = ul_read(4 + j, records + i, 16);
5194 if (status <= 0) {
5195 DropField();
5196 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
5197 free(records);
5198 return PM3_ESOFT;
5202 DropField();
5204 status = NDEFRecordsDecodeAndPrint(records, (size_t)maxsize, verbose);
5205 if (status != PM3_SUCCESS) {
5206 status = NDEFDecodeAndPrint(records, (size_t)maxsize, verbose);
5209 // get total NDEF length before save. If fails, we save it all
5210 size_t n = 0;
5211 if (NDEFGetTotalLength(records, maxsize, &n) != PM3_SUCCESS)
5212 n = maxsize;
5214 pm3_save_dump(filename, records, n, jsfNDEF);
5217 char *jooki = strstr((char *)records, "s.jooki.rocks/s/?s=");
5218 if (jooki) {
5219 jooki += 17;
5220 while (jooki) {
5221 if ((*jooki) != '=')
5222 jooki++;
5223 else {
5224 jooki++;
5225 char s[17] = {0};
5226 strncpy(s, jooki, 16);
5227 PrintAndLogEx(HINT, "Use `" _YELLOW_("hf jooki decode -d %s") "` to decode", s);
5228 break;
5232 char *mattel = strstr((char *)records, ".pid.mattel/");
5233 if (mattel) {
5234 mattel += 12;
5235 while (mattel) {
5236 if ((*mattel) != '/')
5237 mattel++;
5238 else {
5239 mattel++;
5240 char b64[33] = {0};
5241 strncpy(b64, mattel, 32);
5242 uint8_t arr[24] = {0};
5243 size_t arrlen = 0;
5244 mbedtls_base64_decode(arr, sizeof(arr), &arrlen, (const unsigned char *)b64, 32);
5246 PrintAndLogEx(INFO, "decoded... %s", sprint_hex(arr, arrlen));
5247 break;
5252 free(records);
5253 return status;
5256 // utility function. Retrieves emulator memory
5257 static int GetMfuDumpFromEMul(mfu_dump_t **buf) {
5259 mfu_dump_t *dump = calloc(1, sizeof(mfu_dump_t));
5260 if (dump == NULL) {
5261 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
5262 return PM3_EMALLOC;
5265 PrintAndLogEx(INFO, "downloading from emulator memory");
5266 if (!GetFromDevice(BIG_BUF_EML, (uint8_t *)dump, MFU_MAX_BYTES + MFU_DUMP_PREFIX_LENGTH, 0, NULL, 0, NULL, 2500, false)) {
5267 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
5268 free(dump);
5269 return PM3_ETIMEOUT;
5272 *buf = dump ;
5273 return PM3_SUCCESS ;
5276 static int CmdHF14AMfuEView(const char *Cmd) {
5277 CLIParserContext *ctx;
5278 CLIParserInit(&ctx, "hf mfu eview",
5279 "Displays emulator memory\n"
5280 "By default number of pages shown depends on defined tag type.\n"
5281 "You can override this with option --end.",
5282 "hf mfu eview\n"
5283 "hf mfu eview --end 255 -> dumps whole memory"
5286 void *argtable[] = {
5287 arg_param_begin,
5288 arg_int0("e", "end", "<dec>", "index of last block"),
5289 arg_lit0("z", "dense", "dense dump output style"),
5290 arg_param_end
5293 CLIExecWithReturn(ctx, Cmd, argtable, true);
5294 int end = arg_get_int_def(ctx, 1, -1);
5295 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 2));
5296 CLIParserFree(ctx);
5298 bool override_end = (end != -1) ;
5300 if (override_end && (end < 0 || end > MFU_MAX_BLOCKS)) {
5301 PrintAndLogEx(WARNING, "Invalid value for end: %d Must be be positive integer < %d", end, MFU_MAX_BLOCKS);
5302 return PM3_EINVARG ;
5305 mfu_dump_t *dump ;
5306 int res = GetMfuDumpFromEMul(&dump) ;
5307 if (res != PM3_SUCCESS) {
5308 return res ;
5311 if (override_end) {
5312 ++end ;
5313 } else {
5314 end = dump->pages + 1;
5317 mfu_print_dump(dump, end, 0, dense_output);
5318 free(dump);
5319 return PM3_SUCCESS;
5322 static int CmdHF14AMfuESave(const char *Cmd) {
5323 CLIParserContext *ctx;
5324 CLIParserInit(&ctx, "hf mfu esave",
5325 "Saves emulator memory to a MIFARE Ultralight/NTAG dump file (bin/json)\n"
5326 "By default number of pages saved depends on defined tag type.\n"
5327 "You can override this with option --end.",
5328 "hf mfu esave\n"
5329 "hf mfu esave --end 255 -> saves whole memory\n"
5330 "hf mfu esave -f hf-mfu-04010203040506-dump"
5333 void *argtable[] = {
5334 arg_param_begin,
5335 arg_int0("e", "end", "<dec>", "index of last block"),
5336 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5337 arg_param_end
5340 CLIExecWithReturn(ctx, Cmd, argtable, true);
5341 int end = arg_get_int_def(ctx, 1, -1);
5343 char filename[FILE_PATH_SIZE];
5344 int fnlen = 0 ;
5345 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5347 CLIParserFree(ctx);
5349 bool override_end = (end != -1) ;
5351 if (override_end && (end < 0 || end > MFU_MAX_BLOCKS)) {
5352 PrintAndLogEx(WARNING, "Invalid value for end:%d. Must be be positive integer <= %d.", end, MFU_MAX_BLOCKS);
5353 return PM3_EINVARG ;
5356 // get dump from memory
5357 mfu_dump_t *dump ;
5358 int res = GetMfuDumpFromEMul(&dump) ;
5359 if (res != PM3_SUCCESS) {
5360 return res ;
5363 // initialize filename
5364 if (fnlen < 1) {
5365 PrintAndLogEx(INFO, "Using UID as filename");
5366 uint8_t uid[7] = {0};
5367 memcpy(uid, (uint8_t *) & (dump->data), 3);
5368 memcpy(uid + 3, (uint8_t *) & (dump->data) + 4, 4);
5369 strcat(filename, "hf-mfu-");
5370 FillFileNameByUID(filename, uid, "-dump", sizeof(uid));
5373 if (override_end) {
5374 end ++ ;
5375 } else {
5376 end = dump->pages ;
5379 // save dump. Last block contains PACK + RFU
5380 uint16_t datalen = (end + 1) * MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
5381 res = pm3_save_dump(filename, (uint8_t *)dump, datalen, jsfMfuMemory);
5383 free(dump);
5384 return res;
5387 static int CmdHF14AMfuView(const char *Cmd) {
5389 CLIParserContext *ctx;
5390 CLIParserInit(&ctx, "hf mfu view",
5391 "Print a MIFARE Ultralight/NTAG dump file (bin/eml/json)",
5392 "hf mfu view -f hf-mfu-01020304-dump.bin"
5394 void *argtable[] = {
5395 arg_param_begin,
5396 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
5397 arg_lit0("v", "verbose", "Verbose output"),
5398 arg_lit0("z", "dense", "dense dump output style"),
5399 arg_param_end
5401 CLIExecWithReturn(ctx, Cmd, argtable, false);
5402 int fnlen = 0;
5403 char filename[FILE_PATH_SIZE];
5404 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5405 bool verbose = arg_get_lit(ctx, 2);
5406 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 3));
5407 CLIParserFree(ctx);
5409 // read dump file
5410 uint8_t *dump = NULL;
5411 size_t bytes_read = 0;
5412 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (MFU_MAX_BYTES + MFU_DUMP_PREFIX_LENGTH));
5413 if (res != PM3_SUCCESS) {
5414 return res;
5417 if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
5418 PrintAndLogEx(ERR, "Error, dump file is too small");
5419 free(dump);
5420 return PM3_ESOFT;
5423 res = convert_mfu_dump_format(&dump, &bytes_read, verbose);
5424 if (res != PM3_SUCCESS) {
5425 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
5426 free(dump);
5427 return res;
5430 uint16_t block_cnt = ((bytes_read - MFU_DUMP_PREFIX_LENGTH) / MFU_BLOCK_SIZE);
5432 if (verbose) {
5433 PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
5434 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
5437 mfu_print_dump((mfu_dump_t *)dump, block_cnt, 0, dense_output);
5438 free(dump);
5439 return PM3_SUCCESS;
5442 static int CmdHF14AMfuList(const char *Cmd) {
5443 return CmdTraceListAlias(Cmd, "hf 14a", "14a -c");
5446 static int CmdHF14AAmiibo(const char *Cmd) {
5448 CLIParserContext *ctx;
5449 CLIParserInit(&ctx, "hf mfu amiibo",
5450 "Tries to read all memory from amiibo tag and decrypt it",
5451 "hf mfu amiiboo --dec -f hf-mfu-04579DB27C4880-dump.bin --> decrypt file\n"
5452 "hf mfu amiiboo -v --dec --> decrypt tag"
5455 void *argtable[] = {
5456 arg_param_begin,
5457 arg_lit0(NULL, "dec", "Decrypt memory"),
5458 arg_lit0(NULL, "enc", "Encrypt memory"),
5459 arg_str0("i", "in", "<fn>", "Specify a filename for input dump file"),
5460 arg_str0("o", "out", "<fn>", "Specify a filename for output dump file"),
5461 arg_lit0("v", "verbose", "Verbose output"),
5462 arg_param_end
5464 CLIExecWithReturn(ctx, Cmd, argtable, true);
5466 bool shall_decrypt = arg_get_lit(ctx, 1);
5467 bool shall_encrypt = arg_get_lit(ctx, 2);
5469 int infnlen = 0;
5470 char infilename[FILE_PATH_SIZE];
5471 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)infilename, FILE_PATH_SIZE, &infnlen);
5473 int outfnlen = 0;
5474 char outfilename[FILE_PATH_SIZE];
5475 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)outfilename, FILE_PATH_SIZE, &outfnlen);
5477 bool verbose = arg_get_lit(ctx, 5);
5478 CLIParserFree(ctx);
5480 // sanity checks
5481 if ((shall_decrypt + shall_encrypt) > 1) {
5482 PrintAndLogEx(WARNING, "Only specify decrypt or encrypt");
5483 return PM3_EINVARG;
5486 // load keys
5487 nfc3d_amiibo_keys_t amiibo_keys;
5488 if (nfc3d_amiibo_load_keys(&amiibo_keys) == false) {
5489 PrintAndLogEx(INFO, "loading key file ( " _RED_("fail") " )");
5490 return PM3_EFILE;
5493 int res = PM3_ESOFT;
5495 uint8_t original[NFC3D_AMIIBO_SIZE] = {0};
5497 // load dump file if available
5498 if (infnlen > 0) {
5499 uint8_t *dump = NULL;
5500 size_t dumplen = 0;
5501 res = loadFile_safe(infilename, "", (void **)&dump, &dumplen);
5502 if (res != PM3_SUCCESS) {
5503 free(dump);
5504 return PM3_EFILE;
5507 if (dumplen < MFU_DUMP_PREFIX_LENGTH) {
5508 PrintAndLogEx(ERR, "Error, dump file is too small");
5509 free(dump);
5510 return PM3_ESOFT;
5513 res = convert_mfu_dump_format(&dump, &dumplen, verbose);
5514 if (res != PM3_SUCCESS) {
5515 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
5516 free(dump);
5517 return res;
5520 mfu_dump_t *d = (mfu_dump_t *)dump;
5521 memcpy(original, d->data, sizeof(original));
5522 free(dump);
5523 } else {
5524 uint16_t dlen = 0;
5525 uint8_t *dump = NULL;
5526 res = mfu_dump_tag(MAX_NTAG_215, (void **)&dump, &dlen);
5527 if (res != PM3_SUCCESS) {
5528 PrintAndLogEx(FAILED, "Failed to dump memory from tag");
5529 free(dump);
5530 return res;
5532 memcpy(original, dump, sizeof(original));
5533 free(dump);
5537 uint8_t decrypted[NFC3D_AMIIBO_SIZE] = {0};
5538 if (shall_decrypt) {
5539 if (nfc3d_amiibo_unpack(&amiibo_keys, original, decrypted) == false) {
5540 PrintAndLogEx(INFO, "Tag signature ( " _RED_("fail") " )");
5541 return PM3_ESOFT;
5543 // print
5544 if (verbose) {
5545 for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++) {
5546 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(decrypted + (i * 16), 16));
5551 if (shall_encrypt) {
5552 uint8_t encrypted[NFC3D_AMIIBO_SIZE] = {0};
5553 nfc3d_amiibo_pack(&amiibo_keys, decrypted, encrypted);
5554 // print
5555 if (verbose) {
5556 for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++) {
5557 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(encrypted + (i * 16), 16));
5562 if (outfnlen) {
5563 // save dump. Last block contains PACK + RFU
5564 // uint16_t datalen = MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
5565 // res = pm3_save_dump(outfilename, (uint8_t *)dump, datalen, jsfMfuMemory);
5568 return PM3_SUCCESS;
5571 static int CmdHF14AMfuWipe(const char *Cmd) {
5572 CLIParserContext *ctx;
5573 CLIParserInit(&ctx, "hf mfu wipe",
5574 "Wipe card to zeros. It will ignore block0,1,2,3\n"
5575 "you will need to call it with password in order to wipe the config and sett default pwd/pack\n"
5576 "Abort by pressing a key\n"
5577 "New password.... FFFFFFFF\n"
5578 "New 3-DES key... 49454D4B41455242214E4143554F5946\n",
5579 "hf mfu wipe\n"
5580 "hf mfu wipe -k 49454D4B41455242214E4143554F5946\n"
5582 void *argtable[] = {
5583 arg_param_begin,
5584 arg_str0("k", "key", "<hex>", "Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
5585 arg_lit0("l", NULL, "Swap entered key's endianness"),
5586 arg_param_end
5588 CLIExecWithReturn(ctx, Cmd, argtable, true);
5590 int ak_len = 0;
5591 uint8_t authenticationkey[16] = {0x00};
5592 uint8_t *auth_key_ptr = authenticationkey;
5593 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
5594 bool swap_endian = arg_get_lit(ctx, 2);
5596 CLIParserFree(ctx);
5598 bool has_auth_key = false;
5599 bool has_pwd = false;
5600 if (ak_len == 16) {
5601 has_auth_key = true;
5602 } else if (ak_len == 4) {
5603 has_pwd = true;
5604 } else if (ak_len != 0) {
5605 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
5606 return PM3_EINVARG;
5609 uint8_t card_mem_size = 0;
5611 // Swap endianness
5612 if (swap_endian) {
5613 if (has_auth_key) {
5614 auth_key_ptr = SwapEndian64(authenticationkey, ak_len, 8);
5617 if (has_pwd) {
5618 auth_key_ptr = SwapEndian64(authenticationkey, ak_len, 4);
5622 uint64_t tagtype = GetHF14AMfU_Type();
5623 if (tagtype == MFU_TT_UL_ERROR) {
5624 return PM3_ESOFT;
5627 // number of pages to WRITE
5628 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
5629 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
5630 //add one as maxblks starts at 0
5631 card_mem_size = UL_MEMORY_ARRAY[idx] + 1;
5632 break;
5636 ul_print_type(tagtype, 0);
5638 // GDM / GEN1A / GEN4 / NTAG21x read the key
5639 if (ak_len == 0) {
5641 DropField();
5643 int res = get_ulc_3des_key_magic(tagtype, auth_key_ptr);
5644 if (res != PM3_SUCCESS) {
5645 return res;
5647 PrintAndLogEx(SUCCESS, "Using 3DES key... %s", sprint_hex_inrow(auth_key_ptr, 16));
5648 has_auth_key = true;
5651 DropField();
5653 PrintAndLogEx(INFO, "Start wiping...");
5654 PrintAndLogEx(INFO, "-----+-----------------------------");
5655 // time to wipe card
5656 // We skip the first four blocks.
5657 // block 0,1 - UID
5658 // block 2 - lock
5659 // block 3 - OTP
5660 for (uint8_t i = 4; i < card_mem_size; i++) {
5662 if (kbd_enter_pressed()) {
5663 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
5664 goto out;
5667 uint8_t data[MFU_BLOCK_SIZE];
5668 memset(data, 0x00, sizeof(data));
5670 // UL_C specific
5671 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
5672 // default config?
5674 switch (i) {
5675 case 4:
5676 memcpy(data, "\x02\x00\x00\x10", 4);
5677 break;
5678 case 5:
5679 memcpy(data, "\x00\x06\x01\x10", 4);
5680 break;
5681 case 6:
5682 memcpy(data, "\x11\xFF\x00\x00", 4);
5683 break;
5684 case 42:
5685 memcpy(data, "\x30\x00\x00\x00", 4);
5686 break;
5687 case 44:
5688 goto ulc;
5692 // UL_AES specific
5693 if ((tagtype & MFU_TT_UL_AES)) {
5694 // default config?
5697 // UL / NTAG with PWD/PACK
5698 if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
5699 MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
5700 MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216 | MFU_TT_NTAG_216_F |
5701 MFU_TT_NTAG_I2C_1K | MFU_TT_NTAG_I2C_2K | MFU_TT_NTAG_I2C_1K_PLUS | MFU_TT_NTAG_I2C_2K_PLUS
5702 ))) {
5705 // cfg 1
5706 if (i == card_mem_size - 4) {
5707 // strong modulation mode disabled
5708 // pages don't need authentication
5709 uint8_t cfg1[MFU_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0xFF};
5710 memcpy(data, cfg1, sizeof(cfg1));
5713 // cfg 2
5714 if (i == card_mem_size - 3) {
5715 // Unlimited password attempts
5716 // NFC counter disabled
5717 // NFC counter not protected
5718 // user configuration writeable
5719 // write access is protected with password
5720 // 05, Virtual Card Type Identifier is default
5721 uint8_t cfg2[MFU_BLOCK_SIZE] = {0x00, 0x05, 0x00, 0x00};
5722 memcpy(data, cfg2, sizeof(cfg2));
5725 // Set PWD blocks 0xFF FF FF FF
5726 if (i == card_mem_size - 2) {
5727 memset(data, 0xFF, sizeof(data));
5730 // Since we changed PWD before, we need to use new PWD to set PACK
5731 // Pack will be all zeros,
5732 if (i == card_mem_size - 1) {
5733 memset(auth_key_ptr, 0xFF, ak_len);
5738 int res = PM3_SUCCESS;
5739 if (res == PM3_ESOFT) {
5740 res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
5744 int res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
5746 PrintAndLogEx(INFO, " %3d | %s" NOLF, i, sprint_hex(data, MFU_BLOCK_SIZE));
5747 switch (res) {
5748 case PM3_SUCCESS: {
5749 PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )");
5750 break;
5752 case PM3_ESOFT: {
5753 PrintAndLogEx(NORMAL, "( " _RED_("fail") " )");
5754 break;
5756 case PM3_ETIMEOUT:
5757 default: {
5758 PrintAndLogEx(NORMAL, "");
5759 PrintAndLogEx(WARNING, "Command execute timeout");
5760 goto out;
5765 PrintAndLogEx(INFO, "-----+-----------------------------");
5767 ulc:
5769 // UL-C - set 3-DES key
5770 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
5772 uint8_t key[16] = {
5773 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42,
5774 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46
5777 clearCommandBuffer();
5778 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, key, sizeof(key));
5779 PacketResponseNG resp;
5780 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
5781 if ((resp.oldarg[0] & 0xff) == 1) {
5782 PrintAndLogEx(INFO, "Ultralight-C new key... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key)));
5783 } else {
5784 PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
5785 return PM3_ESOFT;
5787 } else {
5788 PrintAndLogEx(WARNING, "command execute timeout");
5789 return PM3_ETIMEOUT;
5793 // UL_AES specific
5794 if ((tagtype & MFU_TT_UL_AES)) {
5795 // Set AES key
5799 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mfu dump --ns") "` to verify");
5800 PrintAndLogEx(NORMAL, "");
5801 PrintAndLogEx(INFO, "Done!");
5803 out:
5804 return PM3_SUCCESS;
5807 static command_t CommandTable[] = {
5808 {"help", CmdHelp, AlwaysAvailable, "This help"},
5809 {"list", CmdHF14AMfuList, AlwaysAvailable, "List MIFARE Ultralight / NTAG history"},
5810 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -------------------------"},
5811 {"keygen", CmdHF14AMfUKeyGen, AlwaysAvailable, "Generate DES/3DES/AES MIFARE diversified keys"},
5812 {"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
5813 {"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
5814 // {"tear_cnt", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1/NTAG Counter bits"},
5815 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
5816 {"cauth", CmdHF14AMfUCAuth, IfPm3Iso14443a, "Ultralight-C - Authentication"},
5817 {"setpwd", CmdHF14AMfUCSetPwd, IfPm3Iso14443a, "Ultralight-C - Set 3DES key"},
5818 {"dump", CmdHF14AMfUDump, IfPm3Iso14443a, "Dump MIFARE Ultralight family tag to binary file"},
5819 {"info", CmdHF14AMfUInfo, IfPm3Iso14443a, "Tag information"},
5820 {"ndefread", CmdHF14MfuNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"},
5821 {"rdbl", CmdHF14AMfURdBl, IfPm3Iso14443a, "Read block"},
5822 {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump file onto a tag"},
5823 {"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "NTAG 213TT - Configure the tamper feature"},
5824 {"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"},
5825 {"wipe", CmdHF14AMfuWipe, IfPm3Iso14443a, "Wipe card to zeros and default key"},
5826 {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"},
5827 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
5828 {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Upload file into emulator memory"},
5829 {"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save emulator memory to file"},
5830 {"eview", CmdHF14AMfuEView, IfPm3Iso14443a, "View emulator memory"},
5831 {"sim", CmdHF14AMfUSim, IfPm3Iso14443a, "Simulate MIFARE Ultralight from emulator memory"},
5832 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " ----------------------------"},
5833 {"setuid", CmdHF14AMfUCSetUid, IfPm3Iso14443a, "Set UID - MAGIC tags only"},
5834 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("amiibo") " ----------------------------"},
5835 {"amiibo", CmdHF14AAmiibo, IfPm3Iso14443a, "Amiibo tag operations"},
5836 {NULL, NULL, NULL, NULL}
5839 static int CmdHelp(const char *Cmd) {
5840 (void)Cmd; // Cmd is not used so far
5841 CmdsHelp(CommandTable);
5842 return PM3_SUCCESS;
5845 int CmdHFMFUltra(const char *Cmd) {
5846 clearCommandBuffer();
5847 return CmdsParse(CommandTable, Cmd);