Add initial support for ST25TN and its signature verification
[RRG-proxmark3.git] / client / src / cmdhfmfu.c
blob5094d40a3ba39c0928abec0cff600453ba38ebf8
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
38 #include "crypto/originality.h"
40 #define MAX_UL_BLOCKS 0x0F
41 #define MAX_ULC_BLOCKS 0x2F
42 #define MAX_ULEV1a_BLOCKS 0x13
43 #define MAX_ULEV1b_BLOCKS 0x28
44 #define MAX_NTAG_203 0x29
45 #define MAX_NTAG_210 0x13
46 #define MAX_NTAG_212 0x28
47 #define MAX_NTAG_213 0x2C
48 #define MAX_NTAG_215 0x86
49 #define MAX_NTAG_216 0xE6
50 #define MAX_NTAG_I2C_1K 0xE9
51 #define MAX_NTAG_I2C_2K 0xE9
52 #define MAX_MY_D_NFC 0xFF
53 #define MAX_MY_D_MOVE 0x25
54 #define MAX_MY_D_MOVE_LEAN 0x0F
55 #define MAX_UL_NANO_40 0x0A
56 #define MAX_UL_AES 0x37
57 #define MAX_ST25TN512 0x3F
58 #define MAX_ST25TN01K 0x3F
60 static int CmdHelp(const char *Cmd);
62 static uint8_t default_aes_keys[][16] = {
63 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
64 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
65 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
66 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
67 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
68 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
69 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33
70 { 0x47, 0x45, 0x4D, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x4F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45 }, // gemalto
71 { 0x56, 0x4c, 0x67, 0x56, 0x99, 0x69, 0x64, 0x9f, 0x17, 0xC6, 0xC6, 0x16, 0x01, 0x10, 0x4D, 0xCA } // Virtual Dorma Kaba
74 static uint8_t default_3des_keys[][16] = {
75 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
76 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
77 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
78 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
79 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
80 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
81 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33
82 { 0x47, 0x45, 0x4D, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x4F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45 } // gemalto
85 static uint8_t default_pwd_pack[][4] = {
86 {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default
87 {0x4E, 0x45, 0x78, 0x54}, // NExT
88 {0xB6, 0xAA, 0x55, 0x8D}, // copykey
91 static uint64_t UL_TYPES_ARRAY[] = {
92 MFU_TT_UNKNOWN, MFU_TT_UL,
93 MFU_TT_UL_C, MFU_TT_UL_EV1_48,
94 MFU_TT_UL_EV1_128, MFU_TT_NTAG,
95 MFU_TT_NTAG_203, MFU_TT_NTAG_210,
96 MFU_TT_NTAG_212, MFU_TT_NTAG_213,
97 MFU_TT_NTAG_215, MFU_TT_NTAG_216,
98 MFU_TT_MY_D, MFU_TT_MY_D_NFC,
99 MFU_TT_MY_D_MOVE, MFU_TT_MY_D_MOVE_NFC,
100 MFU_TT_MY_D_MOVE_LEAN, MFU_TT_NTAG_I2C_1K,
101 MFU_TT_NTAG_I2C_2K, MFU_TT_NTAG_I2C_1K_PLUS,
102 MFU_TT_NTAG_I2C_2K_PLUS, MFU_TT_FUDAN_UL,
103 MFU_TT_NTAG_213_F, MFU_TT_NTAG_216_F,
104 MFU_TT_UL_EV1, MFU_TT_UL_NANO_40,
105 MFU_TT_NTAG_213_TT, MFU_TT_NTAG_213_C,
106 MFU_TT_MAGIC_1A, MFU_TT_MAGIC_1B,
107 MFU_TT_MAGIC_NTAG, MFU_TT_NTAG_210u,
108 MFU_TT_UL_MAGIC, MFU_TT_UL_C_MAGIC,
109 MFU_TT_UL_AES,
110 MFU_TT_ST25TN512, MFU_TT_ST25TN01K,
114 static uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = {
115 // UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128,
116 MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS,
117 // NTAG, NTAG_203, NTAG_210, NTAG_212,
118 MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212,
119 // NTAG_213, NTAG_215, NTAG_216,
120 MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216,
121 // MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN,
122 MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN,
123 // NTAG_I2C_1K, NTAG_I2C_2K, NTAG_I2C_1K_PLUS, NTAG_I2C_2K_PLUS,
124 MAX_NTAG_I2C_1K, MAX_NTAG_I2C_2K, MAX_NTAG_I2C_1K, MAX_NTAG_I2C_2K,
125 // FUDAN_UL, NTAG_213_F, NTAG_216_F, UL_EV1, UL_NANO_40,
126 MAX_UL_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_ULEV1a_BLOCKS, MAX_UL_NANO_40,
127 // NTAG_213_TT, NTAG_213_C,
128 MAX_NTAG_213, MAX_NTAG_213,
129 // MAGIC_1A, MAGIC_1B, MAGIC_NTAG,
130 MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_NTAG_216,
131 // NTAG_210u, UL_MAGIC, UL_C_MAGIC
132 MAX_NTAG_210, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_UL_AES,
133 // ST25TN512, ST25TN01K,
134 MAX_ST25TN512, MAX_ST25TN01K,
137 static const ul_family_t ul_family[] = {
138 {"UL-C", "UL-C", "\x00\x00\x00\x00\x00\x00\x00\x00"},
139 {"UL", "MF0UL1001DUx", "\x00\x04\x03\x01\x00\x00\x0B\x03"},
140 {"UL EV1 48", "MF0UL1101DUx", "\x00\x04\x03\x01\x01\x00\x0B\x03"},
141 {"UL EV1 48", "MF0ULH1101DUx", "\x00\x04\x03\x02\x01\x00\x0B\x03"},
142 {"UL EV1 48", "MF0UL1141DUF", "\x00\x04\x03\x03\x01\x00\x0B\x03"},
143 {"UL EV1 128", "MF0UL2101Dxy", "\x00\x04\x03\x01\x01\x00\x0E\x03"},
144 {"UL EV1 128", "MF0UL2101DUx", "\x00\x04\x03\x02\x01\x00\x0E\x03"},
145 {"UL Ev1 n/a ", "MF0UL3101DUx", "\x00\x04\x03\x01\x01\x00\x11\x03"},
146 {"UL Ev1 n/a", "MF0ULH3101DUx", "\x00\x04\x03\x02\x01\x00\x11\x03"},
147 {"UL Ev1 n/a", "MF0UL5101DUx", "\x00\x04\x03\x01\x01\x00\x13\x03"},
148 {"NTAG 210", "NT2L1011F0DUx", "\x00\x04\x04\x01\x01\x00\x0B\x03"},
149 {"NTAG 210", "NT2H1011G0DUD", "\x00\x04\x04\x02\x01\x00\x0B\x03"},
150 {"NTAG 212", "NT2L1211F0DUx", "\x00\x04\x04\x01\x01\x00\x0E\x03"},
151 {"NTAG 213", "NT2H1311G0DUx", "\x00\x04\x04\x02\x01\x00\x0F\x03"},
152 {"NTAG", "NT2H1411G0DUx", "\x00\x04\x04\x02\x01\x01\x11\x03"},
153 {"NTAG 215", "NT2H1511G0DUx", "\x00\x04\x04\x02\x01\x00\x11\x03"},
154 {"NTAG 215", "NT2H1511F0Dxy", "\x00\x04\x04\x04\x01\x00\x11\x03"},
155 {"NTAG 216", "NT2H1611G0DUx", "\x00\x04\x04\x02\x01\x00\x13\x03"},
156 {"NTAG 213F", "NT2H1311F0Dxy", "\x00\x04\x04\x04\x01\x00\x0F\x03"},
157 {"NTAG 216F", "NT2H1611F0Dxy", "\x00\x04\x04\x04\x01\x00\x13\x03"},
158 {"NTAG 213C", "NT2H1311C1DTL", "\x00\x04\x04\x02\x01\x01\x0F\x03"},
159 {"NTAG 213TT", "NT2H1311TTDUx", "\x00\x04\x04\x02\x03\x00\x0F\x03"},
160 {"NTAG I2C 1k", "NT3H1101W0FHK", "\x00\x04\x04\x05\x02\x00\x13\x03"},
161 {"NTAG I2C 1k", "NT3H1101W0FHK_Variant", "\x00\x04\x04\x05\x02\x01\x13\x03"},
162 {"NTAG I2C 2k", "NT3H1201W0FHK", "\x00\x04\x04\x05\x02\x00\x15\x03"},
163 {"NTAG I2C 2k", "NT3H1201", "\x00\x04\x04\x05\x02\x01\x15\x03"},
164 {"NTAG I2C 1k Plus", "NT3H2111", "\x00\x04\x04\x05\x02\x02\x13\x03"},
165 {"NTAG I2C 2k Plus", "NT3H2211", "\x00\x04\x04\x05\x02\x02\x15\x03"},
166 {"NTAG unk", "nhs", "\x00\x04\x04\x06\x00\x00\x13\x03"},
167 {"UL NANO 40", "MF0UN0001DUx 17pF", "\x00\x04\x03\x01\x02\x00\x0B\x03"},
168 {"UL NANO", "MF0UN1001DUx 17pF", "\x00\x04\x03\x01\x03\x00\x0B\x03"},
169 {"UL NANO 40", "MF0UNH0001DUx 50pF", "\x00\x04\x03\x02\x02\x00\x0B\x03"},
170 {"UL NANO", "MF0UNH1001DUx 50pF", "\x00\x04\x03\x02\x03\x00\x0B\x03"},
171 {"NTAG 210u", "NT2L1001G0DUx", "\x00\x04\x04\x01\x02\x00\x0B\x03"},
172 {"NTAG 210u", "NT2H1001G0DUx", "\x00\x04\x04\x02\x02\x00\x0B\x03"},
173 {"UL EV1 128", "Mikron JSC Russia EV1", "\x00\x34\x21\x01\x01\x00\x0E\x03"},
174 {"NTAG 213", "Shanghai Feiju NTAG", "\x00\x53\x04\x02\x01\x00\x0F\x03"},
175 {"NTAG 215", "Shanghai Feiju NTAG", "\x00\x05\x34\x02\x01\x00\x11\x03"},
176 {"UL AES", "MF0AES2001DUD", "\x00\x04\x03\x01\x04\x00\x0F\x03"},
179 static bool compare_ul_family(const uint8_t *d, uint8_t n) {
180 if (d == NULL) {
181 return false;
184 if (n > 8) {
185 n = 8;
188 for (int i = 0; i < ARRAYLEN(ul_family); ++i) {
189 if (memcmp(d, ul_family[i].version, n) == 0) {
190 return true;
193 return false;
196 //------------------------------------
197 // get version nxp product type
198 static const char *getProductTypeStr(uint8_t id) {
199 static char buf[20];
200 memset(buf, 0, sizeof(buf));
202 switch (id) {
203 case 3:
204 return "Ultralight";
205 case 4:
206 return "NTAG";
207 default:
208 snprintf(buf, sizeof(buf), "%02X, unknown", id);
209 return buf;
213 static int ul_print_nxp_silicon_info(const uint8_t *card_uid) {
215 if (card_uid[0] != 0x04) {
216 return PM3_SUCCESS;
219 uint8_t uid[7];
220 memcpy(&uid, card_uid, 7);
222 uint16_t waferCoordX = ((uid[6] & 3) << 8) | uid[1];
223 uint16_t waferCoordY = ((uid[6] & 12) << 6) | uid[2];
224 uint32_t waferCounter = (
225 (uid[4] << 5) |
226 ((uid[6] & 0xF0) << 17) |
227 (uid[5] << 13) |
228 (uid[3] >> 3)
230 uint8_t testSite = uid[3] & 7;
232 PrintAndLogEx(NORMAL, "");
233 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Silicon Information"));
234 PrintAndLogEx(INFO, " Wafer Counter: %" PRId32 " ( 0x%02" PRIX32 " )", waferCounter, waferCounter);
235 PrintAndLogEx(INFO, " Wafer Coordinates: x %" PRId16 ", y %" PRId16 " (0x%02" PRIX16 ", 0x%02" PRIX16 ")"
236 , waferCoordX
237 , waferCoordY
238 , waferCoordX
239 , waferCoordY
241 PrintAndLogEx(INFO, " Test Site: %u", testSite);
242 return PM3_SUCCESS;
245 static int get_ulc_3des_key_magic(uint64_t magic_type, uint8_t *key) {
247 mf_readblock_ex_t payload = {
248 .read_cmd = ISO14443A_CMD_READBLOCK,
249 .block_no = 0x2C,
252 if ((magic_type & MFU_TT_MAGIC_1A) == MFU_TT_MAGIC_1A) {
253 payload.wakeup = MF_WAKE_GEN1A;
254 payload.auth_cmd = 0;
255 } else if ((magic_type & MFU_TT_MAGIC_1B) == MFU_TT_MAGIC_1B) {
256 payload.wakeup = MF_WAKE_GEN1B;
257 payload.auth_cmd = 0;
258 } else if ((magic_type & MFU_TT_MAGIC_4) == MFU_TT_MAGIC_4) {
259 payload.wakeup = MF_WAKE_GDM_ALT;
260 payload.auth_cmd = 0;
261 } else if ((magic_type & MFU_TT_MAGIC_NTAG21X) == MFU_TT_MAGIC_NTAG21X) {
262 payload.wakeup = MF_WAKE_WUPA;
263 payload.auth_cmd = 0;
264 } else {
265 payload.wakeup = MF_WAKE_WUPA;
266 payload.auth_cmd = MIFARE_MAGIC_GDM_AUTH_KEY;
269 clearCommandBuffer();
270 SendCommandNG(CMD_HF_MIFARE_READBL_EX, (uint8_t *)&payload, sizeof(payload));
271 PacketResponseNG resp;
272 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL_EX, &resp, 1500) == false) {
273 PrintAndLogEx(WARNING, "command execution time out");
274 return PM3_ETIMEOUT;
277 if (resp.status == PM3_SUCCESS && resp.length == MFBLOCK_SIZE) {
278 uint8_t *d = resp.data.asBytes;
279 reverse_array(d, 8);
280 reverse_array(d + 8, 8);
281 memcpy(key, d, MFBLOCK_SIZE);
284 return resp.status;
288 The 7 MSBits (=n) code the storage size itself based on 2^n,
289 the LSBit is set to '0' if the size is exactly 2^n
290 and set to '1' if the storage size is between 2^n and 2^(n+1).
292 static const char *getUlev1CardSizeStr(uint8_t fsize) {
294 static char buf[40];
295 memset(buf, 0, sizeof(buf));
297 uint16_t usize = 1 << ((fsize >> 1) + 1);
298 uint16_t lsize = 1 << (fsize >> 1);
300 // is LSB set?
301 if (fsize & 1)
302 snprintf(buf, sizeof(buf), "%02X, (%u <-> %u bytes)", fsize, usize, lsize);
303 else
304 snprintf(buf, sizeof(buf), "%02X, (%u bytes)", fsize, lsize);
305 return buf;
308 int ul_read_uid(uint8_t *uid) {
309 if (uid == NULL) {
310 PrintAndLogEx(WARNING, "NUll parameter UID");
311 return PM3_ESOFT;
313 // read uid from tag
314 clearCommandBuffer();
315 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
316 PacketResponseNG resp;
317 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
318 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
319 return PM3_ETIMEOUT;
321 iso14a_card_select_t card;
322 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
324 uint64_t select_status = resp.oldarg[0];
325 // 0: couldn't read
326 // 1: OK with ATS
327 // 2: OK, no ATS
328 // 3: proprietary Anticollision
329 if (select_status == 0) {
330 PrintAndLogEx(DEBUG, "iso14443a card select failed");
331 return PM3_ESOFT;
333 memcpy(uid, card.uid, 7);
335 if (card.uidlen != 7) {
336 PrintAndLogEx(WARNING, "Wrong sized UID, expected 7 bytes, got " _RED_("%d"), card.uidlen);
337 return PM3_ELENGTH;
339 return PM3_SUCCESS;
342 static void ul_switch_on_field(void) {
343 clearCommandBuffer();
344 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
347 static int ul_send_cmd_raw(const uint8_t *cmd, uint8_t cmdlen, uint8_t *response, uint16_t responseLength) {
348 clearCommandBuffer();
349 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_APPEND_CRC | ISO14A_NO_RATS, cmdlen, 0, cmd, cmdlen);
350 PacketResponseNG resp;
351 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
352 return PM3_ETIMEOUT;
355 if (!resp.oldarg[0] && responseLength) {
356 return PM3_EWRONGANSWER;
359 uint16_t resplen = (resp.oldarg[0] < responseLength) ? resp.oldarg[0] : responseLength;
360 memcpy(response, resp.data.asBytes, resplen);
361 return resplen;
364 static bool ul_select(iso14a_card_select_t *card) {
366 ul_switch_on_field();
368 PacketResponseNG resp;
369 if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
370 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
371 DropField();
372 return false;
373 } else {
375 uint16_t len = (resp.oldarg[1] & 0xFFFF);
376 if (len == 0) {
377 PrintAndLogEx(DEBUG, "iso14443a card select failed");
378 DropField();
379 return false;
382 if (card) {
383 memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
386 return true;
389 static bool ul_select_rats(iso14a_card_select_t *card) {
391 ul_switch_on_field();
393 PacketResponseNG resp;
394 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
395 PrintAndLogEx(DEBUG, "iso14443a card select timeout");
396 DropField();
397 return false;
398 } else {
400 uint16_t len = (resp.oldarg[1] & 0xFFFF);
401 if (len == 0) {
402 PrintAndLogEx(DEBUG, "iso14443a card select failed");
403 DropField();
404 return false;
407 if (card) {
408 memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
411 if (resp.oldarg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
412 // get ATS
413 uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
414 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, sizeof(rats), 0, rats, sizeof(rats));
415 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
416 PrintAndLogEx(WARNING, "command execution time out");
417 return false;
421 if (card) {
422 card->ats_len = resp.oldarg[0];
423 memcpy(card->ats, resp.data.asBytes, card->ats_len);
427 return true;
430 // This read command will at least return 16bytes.
431 static int ul_read(uint8_t page, uint8_t *response, uint16_t responseLength) {
433 uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page};
434 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
437 static int ul_comp_write(uint8_t page, const uint8_t *data, uint8_t datalen) {
439 if (data == NULL) {
440 return PM3_EINVARG;
443 uint8_t cmd[18];
444 memset(cmd, 0x00, sizeof(cmd));
445 datalen = (datalen > 16) ? 16 : datalen;
447 cmd[0] = ISO14443A_CMD_WRITEBLOCK;
448 cmd[1] = page;
449 memcpy(cmd + 2, data, datalen);
451 uint8_t response[1] = {0xFF};
452 ul_send_cmd_raw(cmd, 2 + datalen, response, sizeof(response));
453 // ACK
454 if (response[0] == 0x0a) {
455 return PM3_SUCCESS;
457 // NACK
458 return PM3_EWRONGANSWER;
461 static int ulc_requestAuthentication(uint8_t *nonce, uint16_t nonceLength) {
463 uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00};
464 return ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength);
467 static int ulev1_requestAuthentication(const uint8_t *pwd, uint8_t *pack, uint16_t packLength) {
469 uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
470 int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
471 // NACK tables different tags, but between 0-9 is a NEGATIVE response.
472 // ACK == 0xA
473 if (len == 1 && pack[0] <= 0x09) {
474 return PM3_EWRONGANSWER;
476 return len;
480 Default AES key is 00-00h. Both the data and UID one.
481 Data key is 00, UID is 01. Authenticity is 02h
482 Auth is 1A[Key ID][CRC] - AF[RndB] - AF[RndA][RndB'] - 00[RndA']
484 static int ulaes_requestAuthentication(const uint8_t *key, uint8_t keyno, bool switch_off_field) {
485 struct p {
486 bool turn_off_field;
487 uint8_t keyno;
488 uint8_t key[16];
489 } PACKED payload;
491 payload.turn_off_field = switch_off_field;
492 payload.keyno = keyno;
493 memcpy(payload.key, key, sizeof(payload.key));
495 clearCommandBuffer();
496 SendCommandNG(CMD_HF_MIFAREULAES_AUTH, (uint8_t *)&payload, sizeof(payload));
497 PacketResponseNG resp;
498 if (WaitForResponseTimeout(CMD_HF_MIFAREULAES_AUTH, &resp, 1500) == false) {
499 return PM3_ETIMEOUT;
501 if (resp.status != PM3_SUCCESS) {
502 return resp.status;
504 return PM3_SUCCESS;
507 static int ulc_authentication(const uint8_t *key, bool switch_off_field) {
509 clearCommandBuffer();
510 SendCommandMIX(CMD_HF_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16);
511 PacketResponseNG resp;
512 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
513 return PM3_ETIMEOUT;
515 if (resp.oldarg[0] == 1) {
516 return PM3_SUCCESS;
518 return PM3_ESOFT;
521 static int trace_mfuc_try_key(uint8_t *key, int state, uint8_t (*authdata)[16]) {
522 uint8_t iv[8] = {0};
523 uint8_t RndB[8] = {0};
524 uint8_t RndARndB[16] = {0};
525 uint8_t RndA[8] = {0};
526 mbedtls_des3_context ctx_des3;
527 switch (state) {
528 case 2:
529 mbedtls_des3_set2key_dec(&ctx_des3, key);
530 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
531 8, iv, authdata[0], RndB);
532 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
533 16, iv, authdata[1], RndARndB);
534 if ((memcmp(&RndB[1], &RndARndB[8], 7) == 0) &&
535 (RndB[0] == RndARndB[15])) {
536 return PM3_SUCCESS;
538 break;
539 case 3:
540 if (key == NULL) {// if no key was found
541 return PM3_ESOFT;
543 memcpy(iv, authdata[0], 8);
544 mbedtls_des3_set2key_dec(&ctx_des3, key);
545 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
546 16, iv, authdata[1], RndARndB);
547 mbedtls_des3_crypt_cbc(&ctx_des3, MBEDTLS_DES_DECRYPT,
548 8, iv, authdata[2], RndA);
549 if ((memcmp(&RndARndB[1], RndA, 7) == 0) &&
550 (RndARndB[0] == RndA[7])) {
551 return PM3_SUCCESS;
553 break;
554 default:
555 return PM3_EINVARG;
557 return PM3_ESOFT;
560 int trace_mfuc_try_default_3des_keys(uint8_t **correct_key, int state, uint8_t (*authdata)[16]) {
561 switch (state) {
562 case 2:
563 for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
564 uint8_t *key = default_3des_keys[i];
565 if (trace_mfuc_try_key(key, state, authdata) == PM3_SUCCESS) {
566 *correct_key = key;
567 return PM3_SUCCESS;
570 break;
571 case 3:
572 return trace_mfuc_try_key(*correct_key, state, authdata);
573 break;
574 default:
575 return PM3_EINVARG;
577 return PM3_ESOFT;
580 // param override, means we override hw debug levels.
581 static int try_default_3des_keys(bool override, uint8_t **correct_key) {
583 uint8_t dbg_curr = DBG_NONE;
584 if (override) {
585 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
586 return PM3_ESOFT;
589 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
590 return PM3_ESOFT;
594 int res = PM3_ESOFT;
596 PrintAndLogEx(INFO, "");
597 PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known UL-C 3DES keys"));
599 for (uint8_t i = 0; i < ARRAYLEN(default_3des_keys); ++i) {
600 uint8_t *key = default_3des_keys[i];
601 if (ulc_authentication(key, true) == PM3_SUCCESS) {
602 *correct_key = key;
603 res = PM3_SUCCESS;
604 break;
608 if (override) {
609 setDeviceDebugLevel(dbg_curr, false);
611 return res;
614 // param override, means we override hw debug levels.
615 static int try_default_aes_keys(bool override) {
617 uint8_t dbg_curr = DBG_NONE;
618 if (override) {
619 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
620 return PM3_ESOFT;
623 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
624 return PM3_ESOFT;
628 int res = PM3_ESOFT;
630 PrintAndLogEx(NORMAL, "");
631 PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known UL-AES keys"));
633 for (uint8_t i = 0; i < ARRAYLEN(default_aes_keys); ++i) {
634 uint8_t *key = default_aes_keys[i];
636 for (uint8_t keyno = 0; keyno < 3; keyno++) {
638 if (ulaes_requestAuthentication(key, keyno, true) == PM3_SUCCESS) {
640 char keystr[20] = {0};
641 switch (keyno) {
642 case 0:
643 sprintf(keystr, "Data key");
644 break;
645 case 1:
646 sprintf(keystr, "UID key");
647 break;
648 case 2:
649 sprintf(keystr, "Authenticity key");
650 break;
651 default:
652 break;
654 PrintAndLogEx(SUCCESS, "%02X " _YELLOW_("%s") " - %s ( "_GREEN_("ok") " )"
655 , keyno
656 , keystr
657 , sprint_hex_inrow(key, 16)
660 res = PM3_SUCCESS;
665 if (override) {
666 setDeviceDebugLevel(dbg_curr, false);
668 return res;
671 static int ul_auth_select(iso14a_card_select_t *card, uint64_t tagtype, bool hasAuthKey, uint8_t *authkey, uint8_t *pack, uint8_t packSize) {
673 if (hasAuthKey && (tagtype & MFU_TT_UL_C)) {
674 //will select card automatically and close connection on error
675 if (ulc_authentication(authkey, false) != PM3_SUCCESS) {
676 PrintAndLogEx(WARNING, "Authentication Failed UL-C");
677 return PM3_ESOFT;
680 } else {
681 if (ul_select(card) == false) {
682 return PM3_ESOFT;
685 if (hasAuthKey) {
686 if (ulev1_requestAuthentication(authkey, pack, packSize) == PM3_EWRONGANSWER) {
687 DropField();
688 PrintAndLogEx(WARNING, "Authentication Failed UL-EV1/NTAG");
689 return PM3_ESOFT;
693 return PM3_SUCCESS;
696 static int ntagtt_getTamperStatus(uint8_t *response, uint16_t responseLength) {
697 uint8_t cmd[] = {NTAGTT_CMD_READ_TT, 0x00};
698 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
701 static int ulev1_getVersion(uint8_t *response, uint16_t responseLength) {
702 uint8_t cmd[] = {MIFARE_ULEV1_VERSION};
703 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
706 static int ulev1_readCounter(uint8_t counter, uint8_t *response, uint16_t responseLength) {
707 uint8_t cmd[] = {MIFARE_ULEV1_READ_CNT, counter};
708 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
711 static int ulev1_readTearing(uint8_t counter, uint8_t *response, uint16_t responseLength) {
712 uint8_t cmd[] = {MIFARE_ULEV1_CHECKTEAR, counter};
713 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
716 static int ulev1_readSignature(uint8_t *response, uint16_t responseLength) {
717 uint8_t cmd[] = {MIFARE_ULEV1_READSIG, 0x00};
718 return ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
721 // Fudan check checks for which error is given for a command with incorrect crc
722 // NXP UL chip responds with 01, fudan 00.
723 // other possible checks:
724 // send a0 + crc
725 // UL responds with 00, fudan doesn't respond
726 // or
727 // send a200 + crc
728 // UL doesn't respond, fudan responds with 00
729 // or
730 // send 300000 + crc (read with extra byte(s))
731 // UL responds with read of page 0, fudan doesn't respond.
733 // make sure field is off before calling this function
734 static int ul_fudan_check(void) {
735 iso14a_card_select_t card;
736 if (ul_select(&card) == false) {
737 return MFU_TT_UL_ERROR;
740 uint8_t cmd[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa7}; // wrong crc on purpose, should be 0xa8
741 clearCommandBuffer();
742 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0, cmd, sizeof(cmd));
743 PacketResponseNG resp;
744 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
745 return MFU_TT_UL_ERROR;
747 if (resp.oldarg[0] != 1) {
748 return MFU_TT_UL_ERROR;
751 return (resp.data.asBytes[0] == 0)
752 ? MFU_TT_FUDAN_UL : MFU_TT_UL; //if response == 0x00 then Fudan, else Genuine NXP
755 static int ul_print_default(uint8_t *data, uint8_t *real_uid) {
757 uint8_t uid[7];
758 uid[0] = data[0];
759 uid[1] = data[1];
760 uid[2] = data[2];
761 uid[3] = data[4];
762 uid[4] = data[5];
763 uid[5] = data[6];
764 uid[6] = data[7];
765 bool mful_uid_layout = true;
767 if (memcmp(uid, real_uid, 7) != 0) {
768 mful_uid_layout = false;
770 PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(real_uid, 7));
771 PrintAndLogEx(SUCCESS, " UID[0]: %02X, %s", real_uid[0], getTagInfo(real_uid[0]));
772 if (real_uid[0] == 0x05 && ((real_uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP
773 uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU
774 switch (chip) {
775 case 0xC2:
776 PrintAndLogEx(SUCCESS, " IC type: SLE 66R04P 770 Bytes");
777 break; //77 pages
778 case 0xC4:
779 PrintAndLogEx(SUCCESS, " IC type: SLE 66R16P 2560 Bytes");
780 break; //256 pages
781 case 0xC6:
782 PrintAndLogEx(SUCCESS, " IC type: SLE 66R32P 5120 Bytes");
783 break; //512 pages /2 sectors
786 if (mful_uid_layout) {
787 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
788 int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
789 if (data[3] == crc0)
790 PrintAndLogEx(SUCCESS, " BCC0: %02X ( " _GREEN_("ok") " )", data[3]);
791 else
792 PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0);
794 int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
795 if (data[8] == crc1)
796 PrintAndLogEx(SUCCESS, " BCC1: %02X ( " _GREEN_("ok") " )", data[8]);
797 else
798 PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1);
799 if (uid[0] == 0x04) {
800 PrintAndLogEx(SUCCESS, " Internal: %02X ( %s )", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
801 } else if (uid[0] == 0x02) {
802 PrintAndLogEx(SUCCESS, " Sysblock: %02X ( %s )", data[9], (data[9] == 0x2C) ? _GREEN_("default") : _RED_("not default"));
803 } else {
804 PrintAndLogEx(SUCCESS, " Internal: %02X", data[9]);
806 } else {
807 PrintAndLogEx(SUCCESS, "Blocks 0-2: %s", sprint_hex(data + 0, 12));
810 PrintAndLogEx(SUCCESS, " Lock: %s - %s",
811 sprint_hex(data + 10, 2),
812 sprint_bin(data + 10, 2)
815 PrintAndLogEx(SUCCESS, " OTP: " _YELLOW_("%s") " - %s",
816 sprint_hex(data + 12, 4),
817 sprint_bin(data + 12, 4)
819 return PM3_SUCCESS;
822 static int ndef_get_maxsize(const uint8_t *data) {
823 // no NDEF message
824 if (data[0] != 0xE1)
825 return 0;
827 if (data[2] == 0x06)
828 return 48;
829 else if (data[2] == 0x12)
830 return 144;
831 else if (data[2] == 0x3E)
832 return 496;
833 else if (data[2] == 0x6D)
834 return 872;
835 return 0;
838 static int ndef_print_CC(uint8_t *data) {
840 // no NDEF message
841 if (data[0] != 0xE1 && data[0] != 0xF1) {
842 return PM3_ESOFT;
845 //NFC Forum Type 1,2,3,4
847 // 4 has 1.1 (11)
849 // b7, b6 major version
850 // b5, b4 minor version
851 // b3, b2 read
852 // 00 always, 01 rfu, 10 proprietary, 11 rfu
853 // b1, b0 write
854 // 00 always, 01 rfo, 10 proprietary, 11 never
855 uint8_t cc_write = data[1] & 0x03;
856 uint8_t cc_read = (data[1] & 0x0C) >> 2;
857 uint8_t cc_minor = (data[1] & 0x30) >> 4;
858 uint8_t cc_major = (data[1] & 0xC0) >> 6;
860 const char *wStr;
861 switch (cc_write) {
862 case 0:
863 wStr = "Write access granted without any security";
864 break;
865 case 1:
866 wStr = "RFU";
867 break;
868 case 2:
869 wStr = "Proprietary";
870 break;
871 case 3:
872 wStr = "No write access";
873 break;
874 default:
875 wStr = "Unknown";
876 break;
878 const char *rStr;
879 switch (cc_read) {
880 case 0:
881 rStr = "Read access granted without any security";
882 break;
883 case 1:
884 case 3:
885 rStr = "RFU";
886 break;
887 case 2:
888 rStr = "Proprietary";
889 break;
890 default:
891 rStr = "Unknown";
892 break;
896 PrintAndLogEx(NORMAL, "");
897 PrintAndLogEx(INFO, "--- " _CYAN_("NDEF Message"));
898 PrintAndLogEx(SUCCESS, "Capability Container: " _YELLOW_("%s"), sprint_hex_inrow(data, 4));
899 PrintAndLogEx(SUCCESS, " %02X: NDEF Magic Number", data[0]);
901 // PrintAndLogEx(SUCCESS, " %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0F);
902 PrintAndLogEx(SUCCESS, " %02X: version %d.%d supported by tag", data[1], cc_major, cc_minor);
903 PrintAndLogEx(SUCCESS, " : %s / %s", rStr, wStr);
905 PrintAndLogEx(SUCCESS, " %02X: Physical Memory Size: %d bytes", data[2], data[2] * 8);
906 if (data[2] == 0x06)
907 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 48);
908 else if (data[2] == 0x12)
909 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 144);
910 else if (data[2] == 0x3E)
911 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 496);
912 else if (data[2] == 0x6D)
913 PrintAndLogEx(SUCCESS, " %02X: NDEF Memory Size: %d bytes", data[2], 872);
915 uint8_t msb3 = (data[3] & 0xE0) >> 5;
916 uint8_t sf = (data[3] & 0x10) >> 4;
917 uint8_t lb = (data[3] & 0x08) >> 3;
918 uint8_t mlrule = (data[3] & 0x06) >> 1;
919 uint8_t mbread = (data[3] & 0x01);
921 PrintAndLogEx(SUCCESS, " %02X: Additional feature information", data[3]);
923 uint8_t bits[8 + 1] = {0};
924 num_to_bytebits(data[3], 8, bits);
925 const char *bs = sprint_bytebits_bin(bits, 8);
927 PrintAndLogEx(SUCCESS, " %s", bs);
928 if (msb3 == 0) {
929 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 0, 3, "RFU"));
930 } else {
931 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_RED, bs, 8, 0, 3, "RFU"));
934 if (sf) {
935 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 3, 1, "Support special frame"));
936 } else {
937 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 3, 1, "Don\'t support special frame"));
940 if (lb) {
941 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 4, 1, "Support lock block"));
942 } else {
943 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 4, 1, "Don\'t support lock block"));
946 if (mlrule == 0) {
947 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 5, 2, "RFU"));
948 } else {
949 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_RED, bs, 8, 5, 2, "RFU"));
952 if (mbread) {
953 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "IC support multiple block reads"));
954 } else {
955 PrintAndLogEx(SUCCESS, " %s", sprint_breakdown_bin(C_NONE, bs, 8, 7, 1, "IC don\'t support multiple block reads"));
957 return PM3_SUCCESS;
960 int ul_print_type(uint64_t tagtype, uint8_t spaces) {
962 if (spaces > 10) {
963 spaces = 10;
966 char typestr[140];
967 memset(typestr, 0x00, sizeof(typestr));
969 if (tagtype & MFU_TT_UL)
970 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)"), spaces, "");
971 else if (tagtype & MFU_TT_UL_C)
972 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces, "");
973 else if (tagtype & MFU_TT_UL_NANO_40)
974 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces, "");
975 else if (tagtype & MFU_TT_UL_EV1_48)
976 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces, "");
977 else if (tagtype & MFU_TT_UL_EV1_128)
978 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces, "");
979 else if (tagtype & MFU_TT_UL_EV1)
980 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces, "");
981 else if (tagtype & MFU_TT_UL_AES)
982 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("MIFARE Ultralight AES"), spaces, "");
983 else if (tagtype & MFU_TT_NTAG)
984 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces, "");
985 else if (tagtype & MFU_TT_NTAG_203)
986 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces, "");
987 else if (tagtype & MFU_TT_NTAG_210u)
988 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 210u (micro) 48bytes (NT2L1001G0DU)"), spaces, "");
989 else if (tagtype & MFU_TT_NTAG_210)
990 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces, "");
991 else if (tagtype & MFU_TT_NTAG_212)
992 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces, "");
993 else if (tagtype & MFU_TT_NTAG_213)
994 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, "");
995 else if (tagtype & MFU_TT_NTAG_213_F)
996 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, "");
997 else if (tagtype & MFU_TT_NTAG_213_C)
998 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces, "");
999 else if (tagtype & MFU_TT_NTAG_213_TT)
1000 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, "");
1001 else if (tagtype & MFU_TT_NTAG_215)
1002 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, "");
1003 else if (tagtype & MFU_TT_NTAG_216)
1004 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces, "");
1005 else if (tagtype & MFU_TT_NTAG_216_F)
1006 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces, "");
1007 else if (tagtype & MFU_TT_NTAG_I2C_1K)
1008 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces, "");
1009 else if (tagtype & MFU_TT_NTAG_I2C_2K)
1010 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces, "");
1011 else if (tagtype & MFU_TT_NTAG_I2C_1K_PLUS)
1012 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces, "");
1013 else if (tagtype & MFU_TT_NTAG_I2C_2K_PLUS)
1014 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces, "");
1015 else if (tagtype & MFU_TT_MY_D)
1016 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces, "");
1017 else if (tagtype & MFU_TT_MY_D_NFC)
1018 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces, "");
1019 else if (tagtype & MFU_TT_MY_D_MOVE)
1020 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces, "");
1021 else if (tagtype & MFU_TT_MY_D_MOVE_NFC)
1022 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces, "");
1023 else if (tagtype & MFU_TT_MY_D_MOVE_LEAN)
1024 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces, "");
1025 else if (tagtype & MFU_TT_FUDAN_UL)
1026 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces, "");
1027 else if (tagtype & MFU_TT_ST25TN512)
1028 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("ST ST25TN512 64bytes"), spaces, "");
1029 else if (tagtype & MFU_TT_ST25TN01K)
1030 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("ST ST25TN01K 160bytes"), spaces, "");
1031 else
1032 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("Unknown %06" PRIx64), spaces, "", tagtype);
1036 bool ismagic = ((tagtype & MFU_TT_MAGIC) == MFU_TT_MAGIC);
1037 // clear magic flag
1038 tagtype &= ~(MFU_TT_MAGIC);
1040 if (ismagic) {
1041 snprintf(typestr + strlen(typestr), 4, " ( ");
1044 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_1A) == MFU_TT_MAGIC_1A) ? _GREEN_("Gen 1a") : "");
1045 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_1B) == MFU_TT_MAGIC_1B) ? _GREEN_("Gen 1b") : "");
1046 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_2) == MFU_TT_MAGIC_2) ? _GREEN_("Gen 2 / CUID") : "");
1047 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_4) == MFU_TT_MAGIC_4) ? _GREEN_("USCUID-UL") : "");
1048 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_NTAG) == MFU_TT_MAGIC_NTAG) ? _GREEN_("NTAG CUID") : "");
1049 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), "%s", ((tagtype & MFU_TT_MAGIC_NTAG21X) == MFU_TT_MAGIC_NTAG21X) ? _GREEN_("NTAG21x") : "");
1052 if (ismagic) {
1053 snprintf(typestr + strlen(typestr), 4, " )");
1056 PrintAndLogEx(SUCCESS, "%s", typestr);
1057 return PM3_SUCCESS;
1060 static int ulc_print_3deskey(uint8_t *data) {
1061 PrintAndLogEx(INFO, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data, 4), sprint_ascii(data, 4));
1062 PrintAndLogEx(INFO, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data + 4, 4), sprint_ascii(data + 4, 4));
1063 PrintAndLogEx(INFO, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data + 8, 4), sprint_ascii(data + 8, 4));
1064 PrintAndLogEx(INFO, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data + 12, 4), sprint_ascii(data + 12, 4));
1065 PrintAndLogEx(INFO, "3des key: " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(data, 16, 8), 16));
1066 return PM3_SUCCESS;
1069 // Only takes 16 bytes of data. Now key data available here
1070 static int ulc_print_configuration(uint8_t *data) {
1072 PrintAndLogEx(NORMAL, "");
1073 PrintAndLogEx(INFO, "--- " _CYAN_("UL-C Configuration") " --------------------------");
1074 PrintAndLogEx(INFO, "Total memory....... " _YELLOW_("%u") " bytes", MAX_ULC_BLOCKS * 4);
1075 PrintAndLogEx(INFO, "Available memory... " _YELLOW_("%u") " bytes", (MAX_ULC_BLOCKS - 4) * 4);
1076 PrintAndLogEx(INFO, "40 / 0x28 | %s - %s Higher lockbits", sprint_hex(data, 4), sprint_bin(data, 2));
1077 PrintAndLogEx(INFO, "41 / 0x29 | %s - %s Counter", sprint_hex(data + 4, 4), sprint_bin(data + 4, 2));
1079 bool validAuth = (data[8] >= 0x03 && data[8] < 0x30);
1080 if (validAuth) {
1081 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 Page " _YELLOW_("%d") "/" _YELLOW_("0x%02X") " and above need authentication"
1082 , sprint_hex(data + 8, 4)
1083 , data[8]
1084 , data[8]
1086 } else {
1087 if (data[8] == 0) {
1088 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 default", sprint_hex(data + 8, 4));
1089 } else if (data[8] == 0x30) {
1090 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 " _GREEN_("unlocked"), sprint_hex(data + 8, 4));
1091 } else {
1092 PrintAndLogEx(INFO, "42 / 0x2A | %s Auth0 " _RED_("byte is out-of-range"), sprint_hex(data + 8, 4));
1096 PrintAndLogEx(INFO, "43 / 0x2B | %s Auth1 %s",
1097 sprint_hex(data + 12, 4),
1098 (data[12] & 1) ? "write access restricted" : _RED_("R/W access restricted")
1101 return PM3_SUCCESS;
1104 static int ulaes_print_configuration(uint8_t *data, uint8_t start_page) {
1106 PrintAndLogEx(NORMAL, "");
1107 PrintAndLogEx(INFO, "--- " _CYAN_("UL-AES Configuration") " --------------------------");
1109 bool rid_act = (data[0] & 1);
1110 bool sec_msg_act = (data[0] & 2);
1111 bool prot = (data[4] & 0x80);
1112 bool cfglck = (data[4] & 0x40);
1113 bool cnt_inc_en = (data[4] & 8);
1114 bool cnt_rd_en = (data[4] & 4);
1115 uint16_t authlim = (data[6]) | ((data[7] & 0x3) << 8);
1117 PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: " _YELLOW_("%s"), start_page, start_page, sprint_hex_inrow(data, 4));
1119 PrintAndLogEx(INFO, " - Random ID is %s", (rid_act) ? "enabled" : "disabled");
1120 PrintAndLogEx(INFO, " - Secure messaging is %s", (sec_msg_act) ? "enabled" : "disabled");
1121 if (data[3] < 0x3c) {
1122 PrintAndLogEx(INFO, " - page %d and above need authentication", data[3]);
1123 } else {
1124 PrintAndLogEx(INFO, " - pages don't need authentication");
1126 PrintAndLogEx(INFO, " cfg1 [%u/0x%02X]: " _YELLOW_("%s"), start_page + 1, start_page + 1, sprint_hex_inrow(data + 4, 4));
1128 if (authlim == 0) {
1129 PrintAndLogEx(INFO, " - " _GREEN_("Unlimited authentication attempts"));
1130 } else {
1131 PrintAndLogEx(INFO, " - Max number of authentication attempts is " _YELLOW_("%d"), authlim);
1133 PrintAndLogEx(INFO, " - %s access requires authentication", prot ? "Read and write" : "Write");
1134 PrintAndLogEx(INFO, " - User configuration is %s", cfglck ? _RED_("locked") : "unlocked");
1135 PrintAndLogEx(INFO, " - Counter 2 increment access %s authentication", cnt_inc_en ? "does not require" : "requires");
1136 PrintAndLogEx(INFO, " - Counter 2 read access %s authentication", cnt_rd_en ? "does not require" : "requires");
1137 return PM3_SUCCESS;
1140 static int ulev1_print_configuration(uint64_t tagtype, uint8_t *data, uint8_t startPage) {
1142 PrintAndLogEx(NORMAL, "");
1143 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Configuration"));
1145 bool strg_mod_en = (data[0] & 2);
1147 uint8_t authlim = (data[4] & 0x07);
1148 bool nfc_cnf_prot_pwd = ((data[4] & 0x08) == 0x08);
1149 bool nfc_cnf_en = ((data[4] & 0x10) == 0x10);
1150 bool cfglck = ((data[4] & 0x40) == 0x40);
1151 bool prot = ((data[4] & 0x80) == 0x80);
1153 uint8_t vctid = data[5];
1155 PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: " _YELLOW_("%s"), startPage, startPage, sprint_hex_inrow(data, 4));
1157 //NTAG213TT has different ASCII mirroring options and config bytes interpretation from other ulev1 class tags
1158 if (tagtype & MFU_TT_NTAG_213_TT) {
1159 uint8_t mirror_conf = ((data[0] & 0xE0) >> 5);
1160 uint8_t mirror_byte = ((data[0] & 0x18) >> 3);
1161 uint8_t mirror_page = data[2];
1163 switch (mirror_conf) {
1164 case 0:
1165 PrintAndLogEx(INFO, " - no ASCII mirror");
1166 break;
1167 case 1:
1168 PrintAndLogEx(INFO, " - UID ASCII mirror");
1169 break;
1170 case 2:
1171 PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
1172 break;
1173 case 3:
1174 PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
1175 break;
1176 case 4:
1177 PrintAndLogEx(INFO, " - tag tamper ASCII mirror");
1178 break;
1179 case 5:
1180 PrintAndLogEx(INFO, " - UID and tag tamper ASCII mirror");
1181 break;
1182 case 6:
1183 PrintAndLogEx(INFO, " - NFC counter and tag tamper ASCII mirror");
1184 break;
1185 case 7:
1186 PrintAndLogEx(INFO, " - UID, NFC counter, and tag tamper ASCII mirror");
1187 break;
1188 default:
1189 break;
1192 if (mirror_conf) {
1193 uint8_t mirror_user_mem_start_byte = (4 * (mirror_page - 4)) + mirror_byte;
1194 uint8_t bytes_required_for_mirror_data = 0;
1196 switch (mirror_conf) {
1197 case 1:
1198 bytes_required_for_mirror_data = 14;
1199 break;
1200 case 2:
1201 bytes_required_for_mirror_data = 6;
1202 break;
1203 case 3:
1204 bytes_required_for_mirror_data = 8;
1205 break;
1206 case 4:
1207 bytes_required_for_mirror_data = 21;
1208 break;
1209 case 5:
1210 bytes_required_for_mirror_data = 23;
1211 break;
1212 case 6:
1213 bytes_required_for_mirror_data = 15;
1214 break;
1215 case 7:
1216 bytes_required_for_mirror_data = 30;
1217 break;
1218 default:
1219 break;
1221 PrintAndLogEx(INFO, " mirror start page %02X | byte pos %02X - %s"
1222 , mirror_page, mirror_byte
1223 , (mirror_page >= 0x4 && ((mirror_user_mem_start_byte + bytes_required_for_mirror_data) <= 144)) ? _GREEN_("ok") : _YELLOW_("Invalid value")
1227 } else if (tagtype & (MFU_TT_NTAG_213_F | MFU_TT_NTAG_216_F)) {
1228 uint8_t mirror_conf = ((data[0] & 0xC0) >> 6);
1229 uint8_t mirror_byte = (data[0] & 0x30);
1230 bool sleep_en = (data[0] & 0x08);
1231 strg_mod_en = (data[0] & 0x04);
1232 uint8_t fdp_conf = (data[0] & 0x03);
1234 switch (mirror_conf) {
1235 case 0:
1236 PrintAndLogEx(INFO, " - no ASCII mirror");
1237 break;
1238 case 1:
1239 PrintAndLogEx(INFO, " - UID ASCII mirror");
1240 break;
1241 case 2:
1242 PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
1243 break;
1244 case 3:
1245 PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
1246 break;
1247 default:
1248 break;
1251 PrintAndLogEx(INFO, " - SLEEP mode %s", (sleep_en) ? "enabled" : "disabled");
1253 switch (fdp_conf) {
1254 case 0:
1255 PrintAndLogEx(INFO, " - no field detect");
1256 break;
1257 case 1:
1258 PrintAndLogEx(INFO, " - enabled by first State-of-Frame (start of communication)");
1259 break;
1260 case 2:
1261 PrintAndLogEx(INFO, " - enabled by selection of the tag");
1262 break;
1263 case 3:
1264 PrintAndLogEx(INFO, " - enabled by field presence");
1265 break;
1266 default:
1267 break;
1269 // valid mirror start page and byte position within start page.
1270 if (tagtype & MFU_TT_NTAG_213_F) {
1271 switch (mirror_conf) {
1272 case 1:
1273 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x24) ? "OK" : "Invalid value"); break;}
1274 case 2:
1275 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x26) ? "OK" : "Invalid value"); break;}
1276 case 3:
1277 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x22) ? "OK" : "Invalid value"); break;}
1278 default:
1279 break;
1281 } else if (tagtype & MFU_TT_NTAG_216_F) {
1282 switch (mirror_conf) {
1283 case 1:
1284 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0xDE) ? "OK" : "Invalid value"); break;}
1285 case 2:
1286 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0xE0) ? "OK" : "Invalid value"); break;}
1287 case 3:
1288 { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0xDC) ? "OK" : "Invalid value"); break;}
1289 default:
1290 break;
1294 PrintAndLogEx(INFO, " - strong modulation mode %s", (strg_mod_en) ? "enabled" : "disabled");
1296 if (data[3] < 0xff)
1297 PrintAndLogEx(INFO, " - page %d and above need authentication", data[3]);
1298 else
1299 PrintAndLogEx(INFO, " - pages don't need authentication");
1301 uint8_t tt_enabled = 0;
1302 uint8_t tt_message[4] = {0x00};
1303 uint8_t tt_msg_resp_len = 0;
1304 uint8_t tt_status_resp[5] = {0x00};
1306 if (tagtype & MFU_TT_NTAG_213_TT) {
1307 tt_enabled = (data[1] & 0x02);
1308 tt_msg_resp_len = ul_read(45, tt_message, 4);
1310 PrintAndLogEx(INFO, " - tamper detection feature is %s"
1311 , (tt_enabled) ? _GREEN_("ENABLED") : "disabled"
1314 switch (data[1] & 0x06) {
1315 case 0x00:
1316 PrintAndLogEx(INFO, " - tamper message is unlocked and read/write enabled");
1317 break;
1318 case 0x02:
1319 PrintAndLogEx(INFO, " - tamper message is reversibly read/write locked in memory while the tamper feature is enabled");
1320 break;
1321 case 0x04:
1322 case 0x06:
1323 PrintAndLogEx(INFO, " - tamper message is permanently read/write locked in memory");
1324 break;
1325 default:
1326 break;
1330 PrintAndLogEx(INFO, " cfg1 [%u/0x%02X]: " _YELLOW_("%s"), startPage + 1, startPage + 1, sprint_hex_inrow(data + 4, 4));
1331 if (authlim == 0)
1332 PrintAndLogEx(INFO, " - " _GREEN_("Unlimited password attempts"));
1333 else
1334 PrintAndLogEx(INFO, " - Max number of password attempts is " _YELLOW_("%d"), authlim);
1336 PrintAndLogEx(INFO, " - NFC counter %s", (nfc_cnf_en) ? "enabled" : "disabled");
1337 PrintAndLogEx(INFO, " - NFC counter %s", (nfc_cnf_prot_pwd) ? "password protection enabled" : "not protected");
1339 PrintAndLogEx(INFO, " - user configuration %s", cfglck ? "permanently locked" : "writeable");
1340 PrintAndLogEx(INFO, " - %s access is protected with password", prot ? "read and write" : "write");
1341 PrintAndLogEx(INFO, " - %02X, Virtual Card Type Identifier is %sdefault", vctid, (vctid == 0x05) ? "" : "not ");
1342 PrintAndLogEx(INFO, " PWD [%u/0x%02X]: %s ( cannot be read )", startPage + 2, startPage + 2, sprint_hex_inrow(data + 8, 4));
1343 PrintAndLogEx(INFO, " PACK [%u/0x%02X]: %s ( cannot be read )", startPage + 3, startPage + 3, sprint_hex_inrow(data + 12, 2));
1344 PrintAndLogEx(INFO, " RFU [%u/0x%02X]: %s ( cannot be read )", startPage + 3, startPage + 3, sprint_hex_inrow(data + 14, 2));
1346 if (tagtype & MFU_TT_NTAG_213_TT) {
1347 if (data[1] & 0x06) {
1348 PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s (cannot be read)", sprint_hex_inrow(tt_message, tt_msg_resp_len));
1349 PrintAndLogEx(INFO, " - tamper message is masked in memory");
1350 } else {
1351 PrintAndLogEx(INFO, "TT_MSG [45/0x2D]: %s", sprint_hex_inrow(tt_message, tt_msg_resp_len));
1352 PrintAndLogEx(INFO, " - tamper message is %s and is readable/writablbe in memory", sprint_hex(tt_message, tt_msg_resp_len));
1356 //The NTAG213TT only returns meaningful information for the fields below if the tamper feature is enabled
1357 if ((tagtype & MFU_TT_NTAG_213_TT) && tt_enabled) {
1359 int tt_status_len = ntagtt_getTamperStatus(tt_status_resp, 5);
1360 if (tt_status_len != 5) {
1361 PrintAndLogEx(WARNING, "Error sending the READ_TT_STATUS command to tag\n");
1362 return PM3_ESOFT;
1365 PrintAndLogEx(NORMAL, "");
1366 PrintAndLogEx(INFO, "--- " _CYAN_("Tamper Status"));
1367 PrintAndLogEx(INFO, " READ_TT_STATUS: %s", sprint_hex_inrow(tt_status_resp, 5));
1369 PrintAndLogEx(INFO, " Tamper status result from this power-up:");
1370 switch (tt_status_resp[4]) {
1371 case 0x43:
1372 PrintAndLogEx(INFO, " - Tamper loop was detcted as closed during this power-up");
1373 break;
1374 case 0x4F:
1375 PrintAndLogEx(INFO, " - Tamper loop was detected as open during this power-up");
1376 break;
1377 case 0x49:
1378 PrintAndLogEx(INFO, " - Tamper loop measurement was not enabled or not valid during this power-up");
1379 break;
1380 default:
1381 break;
1384 PrintAndLogEx(INFO, " Tamper detection permanent memory:");
1385 if ((tt_status_resp[0] | tt_status_resp [1] | tt_status_resp[2] | tt_status_resp[3]) == 0x00)
1387 PrintAndLogEx(INFO, " - Tamper loop has never been detected as open during power-up");
1388 else {
1389 PrintAndLogEx(INFO, " - Tamper loop was detected as open during power-up at least once");
1390 PrintAndLogEx(INFO, " - Tamper message returned by READ_TT_STATUS command: %s", sprint_hex(tt_status_resp, 4));
1393 return PM3_SUCCESS;
1396 static int ulev1_print_counters(void) {
1397 PrintAndLogEx(NORMAL, "");
1398 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counters"));
1399 uint8_t tear[1] = {0};
1400 uint8_t counter[3] = {0, 0, 0};
1401 int len = 0;
1402 for (uint8_t i = 0; i < 3; ++i) {
1403 ulev1_readTearing(i, tear, sizeof(tear));
1404 len = ulev1_readCounter(i, counter, sizeof(counter));
1405 if (len == 3) {
1406 PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
1407 PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
1408 , tear[0]
1409 , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
1413 return len;
1416 static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) {
1417 int index = -1;
1418 if (signature_len == 32) {
1419 index = originality_check_verify(uid, 7, signature, signature_len, PK_MFUL);
1420 } else if (signature_len == 48) {
1421 index = originality_check_verify(uid, 7, signature, signature_len, PK_MFULAES);
1423 PrintAndLogEx(NORMAL, "");
1424 return originality_check_print(signature, signature_len, index);
1427 static int ulev1_print_version(uint8_t *data) {
1428 PrintAndLogEx(NORMAL, "");
1429 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Version"));
1430 PrintAndLogEx(INFO, " Raw bytes: " _YELLOW_("%s"), sprint_hex_inrow(data, 8));
1431 PrintAndLogEx(INFO, " Vendor ID: %02X, %s", data[1], getTagInfo(data[1]));
1432 PrintAndLogEx(INFO, " Product type: %s", getProductTypeStr(data[2]));
1433 PrintAndLogEx(INFO, " Product subtype: %02X, %s", data[3], (data[3] == 1) ? "17 pF" : "50pF");
1434 PrintAndLogEx(INFO, " Major version: %02X", data[4]);
1435 PrintAndLogEx(INFO, " Minor version: %02X", data[5]);
1436 PrintAndLogEx(INFO, " Size: %s", getUlev1CardSizeStr(data[6]));
1437 PrintAndLogEx(INFO, " Protocol type: %02X%s", data[7], (data[7] == 0x3) ? ", ISO14443-3 Compliant" : "");
1438 return PM3_SUCCESS;
1441 static int ntag_print_counter(void) {
1442 // NTAG has one counter. At address 0x02. With no tearing.
1443 PrintAndLogEx(NORMAL, "");
1444 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Counter"));
1445 uint8_t counter[3] = {0, 0, 0};
1446 uint16_t len;
1447 len = ulev1_readCounter(0x02, counter, sizeof(counter));
1448 PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3));
1449 return len;
1453 static int ulc_magic_test(){
1454 // Magic Ultralight test
1455 // Magic UL-C, by observation,
1456 // 1) it seems to have a static nonce response to 0x1A command.
1457 // 2) the deskey bytes is not-zero:d out on as datasheet states.
1458 // 3) UID - changeable, not only, but pages 0-1-2-3.
1459 // 4) use the ul_magic_test ! magic tags answers specially!
1460 int returnValue = UL_ERROR;
1461 iso14a_card_select_t card;
1462 uint8_t nonce1[11] = {0x00};
1463 uint8_t nonce2[11] = {0x00};
1464 if ( !ul_select(&card) ){
1465 return MFU_TT_UL_ERROR;
1467 int status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
1468 if ( status <= 0 ) {
1469 status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
1470 returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? MFU_TT_UL_C_MAGIC : MFU_TT_UL_C;
1471 } else {
1472 returnValue = MFU_TT_UL;
1474 DropField();
1475 return returnValue;
1478 static uint64_t ul_magic_test(void) {
1479 // Magic Ultralight tests
1480 // 1) take present UID, and try to write it back. OBSOLETE
1481 // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
1483 DropField();
1485 iso14a_card_select_t card;
1486 if (ul_select_rats(&card) == false) {
1487 return MFU_TT_UL_ERROR;
1491 // iceman: how to proper identify RU based UID cards
1492 if (
1493 (memcmp(card.uid, "\xAA\x55\x39", 3) == 0) ||
1494 (memcmp(card.uid, "\xAA\x55\xC3", 3) == 0)
1496 // Ul-5 MFU Ev1 FUID,
1497 return MFU_TT_UL_EV1_MAGIC;
1500 PrintAndLogEx(DEBUG, "%u - %s", card.ats_len, sprint_hex_inrow(card.ats, card.ats_len));
1502 // USCUID-UL cards
1503 if (card.ats_len == 18) {
1505 // USCUID-UL configuration
1506 // https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md#uscuid-ul-configuration-guide
1507 // identify: ATS len 18,
1508 // First 8 bytes can vary depending on setup. next 8 bytes is GET VERSION data and finally 2 byte crc
1510 // \x85\x00\x00\xA0\x0A\x00\x0A\xC3 \x00\x04\x03\x01\x01\x00\x0B\x03 \xZZ\xZZ
1512 // 7AFF - back door enabled
1513 // 8500 -
1514 // if we ignore first 8 bytes we can identify regardless how card is configured
1516 if (compare_ul_family(card.ats + 8, 8)) {
1517 return MFU_TT_MAGIC_4 | MFU_TT_MAGIC;
1521 // Direct write alternative cards
1522 if (card.ats_len == 14) {
1524 // UL Direct Write , UL-C Direct write, NTAG 213 Direct write
1525 if (memcmp(card.ats, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
1526 return MFU_TT_MAGIC_2;
1531 int status = ul_comp_write(0, NULL, 0);
1532 DropField();
1533 if (status == PM3_SUCCESS) {
1534 PrintAndLogEx(INFO, "comp write pass");
1535 return MFU_TT_MAGIC_2 | MFU_TT_MAGIC;
1538 // check for GEN1A, GEN1B and NTAG21x
1539 PacketResponseNG resp;
1540 clearCommandBuffer();
1541 uint8_t payload[] = { 0 };
1542 SendCommandNG(CMD_HF_MIFARE_CIDENT, payload, sizeof(payload));
1544 uint16_t is_generation = MAGIC_FLAG_NONE;
1545 if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT, &resp, 1500)) {
1546 if ((resp.status == PM3_SUCCESS) && resp.length == sizeof(uint16_t)) {
1547 is_generation = resp.data.asDwords[0] & 0xFFFF;
1551 if ((is_generation & MAGIC_FLAG_GEN_1A) == MAGIC_FLAG_GEN_1A) {
1552 return MFU_TT_MAGIC_1A | MFU_TT_MAGIC;
1555 if ((is_generation & MAGIC_FLAG_GEN_1B) == MAGIC_FLAG_GEN_1B) {
1556 return MFU_TT_MAGIC_1B | MFU_TT_MAGIC;
1559 if ((is_generation & MAGIC_FLAG_NTAG21X) == MAGIC_FLAG_NTAG21X) {
1560 return MFU_TT_MAGIC_NTAG21X | MFU_TT_MAGIC;
1563 return MFU_TT_UNKNOWN;
1566 static char *mfu_generate_filename(const char *prefix, const char *suffix) {
1567 iso14a_card_select_t card;
1568 if (ul_select(&card) == false) {
1569 PrintAndLogEx(WARNING, "No tag found.");
1570 return NULL;
1573 char *fptr = calloc(sizeof(char) * (strlen(prefix) + strlen(suffix)) + sizeof(card.uid) * 2 + 1, sizeof(uint8_t));
1574 strcpy(fptr, prefix);
1575 FillFileNameByUID(fptr, card.uid, suffix, card.uidlen);
1576 return fptr;
1579 // used with the Amiibo dumps loading...
1580 // Not related to 'hf mfu dump'
1581 static int mfu_dump_tag(uint16_t pages, void **pdata, uint16_t *len) {
1583 // read uid
1584 iso14a_card_select_t card;
1585 if (ul_select(&card) == false) {
1586 return PM3_ECARDEXCHANGE;
1589 int res = PM3_SUCCESS;
1590 uint16_t maxbytes = (pages * MFU_BLOCK_SIZE);
1592 *pdata = calloc(maxbytes, sizeof(uint8_t));
1593 if (*pdata == NULL) {
1594 PrintAndLogEx(FAILED, "error, cannot allocate memory");
1595 res = PM3_EMALLOC;
1596 goto out;
1599 // UL_EV1/NTAG auth
1600 uint8_t keytype = 2;
1601 // generate PWD
1602 uint8_t key[4] = {0};
1603 num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
1605 clearCommandBuffer();
1606 SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, key, 4);
1607 PacketResponseNG resp;
1608 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
1609 PrintAndLogEx(WARNING, "command execution time out");
1610 free(*pdata);
1611 res = PM3_ETIMEOUT;
1612 goto out;
1615 if (resp.oldarg[0] != 1) {
1616 PrintAndLogEx(WARNING, "Failed reading card");
1617 free(*pdata);
1618 res = PM3_ESOFT;
1619 goto out;
1622 // read all memory
1623 uint32_t startindex = resp.oldarg[2];
1624 uint32_t buffer_size = resp.oldarg[1];
1625 if (buffer_size > maxbytes) {
1626 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
1627 buffer_size = maxbytes;
1630 if (GetFromDevice(BIG_BUF, *pdata, buffer_size, startindex, NULL, 0, NULL, 2500, false) == false) {
1631 PrintAndLogEx(WARNING, "command execution time out");
1632 free(*pdata);
1633 res = PM3_ETIMEOUT;
1634 goto out;
1637 if (len) {
1638 *len = buffer_size;
1641 out:
1642 return res;
1646 Lego Dimensions,
1647 Version: 00 04 04 02 01 00 0F 03
1649 matching bytes:
1650 index 12 ( 3 * 4 )
1651 E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E
1654 typedef struct {
1655 const char *desc;
1656 uint8_t mpos;
1657 uint8_t mlen;
1658 const char *match;
1659 uint32_t (*otp)(const uint8_t *uid);
1660 const char *hint;
1661 } mfu_otp_identify_t;
1663 static mfu_otp_identify_t mfu_otp_ident_table[] = {
1664 { "SALTO Systems card", 12, 4, "534C544F", ul_c_otpgenA, NULL },
1665 { NULL, 0, 0, NULL, NULL, NULL }
1668 static mfu_otp_identify_t *mfu_match_otp_fingerprint(uint8_t *uid, uint8_t *data) {
1669 uint8_t i = 0;
1670 do {
1671 int ml = 0;
1672 uint8_t mtmp[40] = {0};
1674 // static or dynamic created OTP to fingerprint.
1675 if (mfu_otp_ident_table[i].match) {
1676 param_gethex_to_eol(mfu_otp_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml);
1677 } else {
1678 uint32_t otp = mfu_otp_ident_table[i].otp(uid);
1679 num_to_bytes(otp, 4, mtmp);
1682 int min = MIN(mfu_otp_ident_table[i].mlen, 4);
1684 PrintAndLogEx(DEBUG, "uid.... %s", sprint_hex_inrow(uid, 7));
1685 PrintAndLogEx(DEBUG, "calc... %s", sprint_hex_inrow(mtmp, 4));
1686 PrintAndLogEx(DEBUG, "dump... %s", sprint_hex_inrow(data + mfu_otp_ident_table[i].mpos, min));
1688 bool m2 = (memcmp(mtmp, data + mfu_otp_ident_table[i].mpos, min) == 0);
1689 if (m2) {
1690 PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_otp_ident_table[i].desc);
1691 return &mfu_otp_ident_table[i];
1693 } while (mfu_otp_ident_table[++i].desc);
1694 return NULL;
1697 typedef struct {
1698 const char *desc;
1699 const char *version;
1700 uint8_t mpos;
1701 uint8_t mlen;
1702 const char *match;
1703 uint32_t (*Pwd)(const uint8_t *uid);
1704 uint16_t (*Pack)(const uint8_t *uid);
1705 const char *hint;
1706 } mfu_identify_t;
1708 static mfu_identify_t mfu_ident_table[] = {
1710 "Jooki", "0004040201000F03",
1711 12, 32, "E11012000103A00C340329D101255504732E6A6F6F6B692E726F636B732F732F",
1712 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1713 "hf mfu ndefread"
1716 "Lego Dimensions", "0004040201000F03",
1717 12, 18, "E11012000103A00C340313D1010F5402656E",
1718 ul_ev1_pwdgenC, ul_ev1_packgenC,
1719 "hf mfu dump -k %08x"
1722 "Hotwheels", "0004040201000F03",
1723 9, 9, "E110120F",
1724 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1725 "hf mfu dump -k %08x"
1728 "Minecraft Earth", "0004040201000F03",
1729 9, 26, "48F6FFE1101200037C91012C55027069642E6D617474656C2F4167",
1730 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1731 "hf mfu dump -k %08x"
1734 "Snackworld", "0004040101000B03",
1735 9, 7, "483000E1100600",
1736 NULL, NULL,
1737 "hf mfu dump -k"
1740 "Amiibo", "0004040201001103",
1741 9, 9, "480FE0F110FFEEA500",
1742 ul_ev1_pwdgenB, ul_ev1_packgenB,
1743 "hf mfu dump -k %08x"
1746 "Amiibo - Power Up band", "0004040502021303",
1747 8, 10, "44000FE0F110FFEEA500",
1748 ul_ev1_pwdgenB, ul_ev1_packgenB,
1749 "hf mfu dump -k %08x"
1753 "Xiaomi AIR Purifier", "0004040201000F03",
1754 0, 0, "",
1755 ul_ev1_pwdgenE, ul_ev1_packgenE,
1756 "hf mfu dump -k %08x"
1760 "Philips Toothbrush", "0004040201010F03",
1761 16, 20, "0310D1010C55027068696C6970732E636F6DFE00",
1762 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1763 "hf mfu pwdgen -r"
1766 "Philips Toothbrush", "0004040201010F03",
1767 16, 36, "0320D1011C55027068696C6970732E636F6D2F6E6663627275736868656164746170FE00",
1768 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1769 "hf mfu pwdgen -r"
1772 "Bank Of Archie brothers", "0004030101000B03",
1773 9, 11, "48F6FF0000000036343533",
1774 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1775 NULL
1778 "Art-Dass NFT card", "0004040201000F03",
1779 16, 16, "033ED1013A5504617274646173732E6E",
1780 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1781 NULL
1784 "Bonverde Coffe card", "0004030101000B03",
1785 18, 4, "644B05AA",
1786 ul_ev1_pwdgen_def, ul_ev1_packgen_def,
1787 NULL
1789 {NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
1792 static mfu_identify_t *mfu_match_fingerprint(const uint8_t *version, const uint8_t *data) {
1793 uint8_t i = 0;
1794 do {
1796 int vl = 0;
1797 uint8_t vtmp[10] = {0};
1798 param_gethex_to_eol(mfu_ident_table[i].version, 0, vtmp, sizeof(vtmp), &vl);
1800 bool m1 = (memcmp(vtmp, version, vl) == 0);
1801 if (m1 == false) {
1802 PrintAndLogEx(DEBUG, "(fingerprint) wrong version");
1803 continue;
1806 int ml = 0;
1807 uint8_t mtmp[40] = {0};
1808 param_gethex_to_eol(mfu_ident_table[i].match, 0, mtmp, sizeof(mtmp), &ml);
1810 bool m2 = (memcmp(mtmp, data + mfu_ident_table[i].mpos, mfu_ident_table[i].mlen) == 0);
1811 if (m2) {
1812 PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_ident_table[i].desc);
1813 return &mfu_ident_table[i];
1815 } while (mfu_ident_table[++i].desc);
1816 return NULL;
1819 static uint8_t mfu_max_len(void) {
1820 uint8_t n = 0, i = 0;
1821 do {
1822 uint8_t tmp = mfu_ident_table[i].mpos + mfu_ident_table[i].mlen;
1823 if (tmp > n) {
1824 n = tmp;
1826 } while (mfu_ident_table[++i].desc);
1827 return n;
1830 static int mfu_get_version_uid(uint8_t *version, uint8_t *uid) {
1831 iso14a_card_select_t card;
1832 if (ul_select(&card) == false) {
1833 return PM3_ESOFT;
1835 memcpy(uid, card.uid, card.uidlen);
1837 uint8_t v[10] = {0x00};
1838 int len = ulev1_getVersion(v, sizeof(v));
1839 DropField();
1840 if (len != sizeof(v)) {
1841 return PM3_ESOFT;
1844 memcpy(version, v, 8);
1845 return PM3_SUCCESS;
1848 static int mfu_fingerprint(uint64_t tagtype, bool hasAuthKey, const uint8_t *authkey, int ak_len) {
1850 uint8_t dbg_curr = DBG_NONE;
1851 uint8_t *data = NULL;
1852 int res = PM3_ESOFT;
1853 PrintAndLogEx(INFO, "");
1854 PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint"));
1855 uint8_t maxbytes = mfu_max_len();
1856 if (maxbytes == 0) {
1857 PrintAndLogEx(ERR, "fingerprint table wrong");
1858 res = PM3_ESOFT;
1859 goto out;
1862 maxbytes = ((maxbytes / MFU_BLOCK_SIZE) + 1) * MFU_BLOCK_SIZE;
1863 data = calloc(maxbytes, sizeof(uint8_t));
1864 if (data == NULL) {
1865 PrintAndLogEx(ERR, "failed to allocate memory");
1866 res = PM3_EMALLOC;
1867 goto out;
1870 uint8_t pages = (maxbytes / MFU_BLOCK_SIZE);
1871 uint8_t keytype = 0;
1873 if (hasAuthKey) {
1874 if (tagtype & MFU_TT_UL_C)
1875 keytype = 1; // UL_C auth
1876 else
1877 keytype = 2; // UL_EV1/NTAG auth
1880 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
1881 res = PM3_ESOFT;
1882 goto out;
1885 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
1886 res = PM3_ESOFT;
1887 goto out;
1890 clearCommandBuffer();
1891 SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, keytype, authkey, ak_len);
1892 PacketResponseNG resp;
1893 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
1894 PrintAndLogEx(WARNING, "command execution time out");
1895 res = PM3_ETIMEOUT;
1896 goto out;
1899 if (resp.oldarg[0] != 1) {
1900 PrintAndLogEx(WARNING, "Failed reading card");
1901 res = PM3_ESOFT;
1902 goto out;
1905 // read all memory
1906 uint32_t startindex = resp.oldarg[2];
1907 uint32_t buffer_size = resp.oldarg[1];
1909 if (buffer_size > maxbytes) {
1910 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
1911 buffer_size = maxbytes;
1914 if (GetFromDevice(BIG_BUF, data, buffer_size, startindex, NULL, 0, NULL, 2500, false) == false) {
1915 PrintAndLogEx(WARNING, "command execution time out");
1916 res = PM3_ETIMEOUT;
1917 goto out;
1920 uint8_t version[8] = {0};
1921 uint8_t uid[7] = {0};
1922 if (mfu_get_version_uid(version, uid) == PM3_SUCCESS) {
1923 mfu_identify_t *item = mfu_match_fingerprint(version, data);
1924 if (item) {
1925 PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc);
1926 res = PM3_SUCCESS;
1928 if (item->hint) {
1929 if (item->Pwd) {
1930 char s[40] = {0};
1931 snprintf(s, sizeof(s), item->hint, item->Pwd(uid));
1932 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", s);
1933 } else {
1934 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", item->hint);
1940 // OTP checks
1941 mfu_otp_identify_t *item = mfu_match_otp_fingerprint(uid, data);
1942 if (item) {
1943 PrintAndLogEx(SUCCESS, _GREEN_("%s"), item->desc);
1944 res = PM3_SUCCESS;
1946 if (item->hint) {
1947 if (item->otp) {
1948 char s[40] = {0};
1949 snprintf(s, sizeof(s), item->hint, item->otp(uid));
1950 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", s);
1951 } else {
1952 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", item->hint);
1957 out:
1959 if (res != PM3_SUCCESS) {
1960 PrintAndLogEx(INFO, "n/a");
1963 setDeviceDebugLevel(dbg_curr, false);
1964 free(data);
1965 return res;
1968 static int mfu_write_block(const uint8_t *data, uint8_t datalen, bool has_auth_key, bool has_pwd, const uint8_t *auth_key_ptr, uint8_t blockno) {
1970 // 4 or 16.
1971 uint8_t cmd[32];
1972 memcpy(cmd, data, datalen);
1974 // 0 - no pwd/key, no authentication
1975 // 1 - 3des key (16 bytes)
1976 // 2 - pwd (4 bytes)
1977 uint8_t keytype = 0;
1978 size_t cmdlen = datalen;
1979 if (has_auth_key) {
1980 keytype = 1;
1981 memcpy(cmd + datalen, auth_key_ptr, 16);
1982 cmdlen += 16;
1983 } else if (has_pwd) {
1984 keytype = 2;
1985 memcpy(cmd + datalen, auth_key_ptr, 4);
1986 cmdlen += 4;
1989 clearCommandBuffer();
1990 if (datalen == 16) {
1991 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockno, keytype, 0, cmd, cmdlen);
1992 } else {
1993 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, keytype, 0, cmd, cmdlen);
1995 PacketResponseNG resp;
1996 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
1997 return PM3_ETIMEOUT;
2000 uint8_t isOK = resp.oldarg[0] & 0xFF;
2001 if (isOK) {
2002 return PM3_SUCCESS;
2004 return PM3_ESOFT;
2007 uint64_t GetHF14AMfU_Type(void) {
2009 uint64_t tagtype = MFU_TT_UNKNOWN;
2010 iso14a_card_select_t card;
2012 if (ul_select(&card) == false)
2013 return MFU_TT_UL_ERROR;
2015 // Ultralight - ATQA / SAK
2016 if (card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00) {
2017 //PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D |ST25TN [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
2018 DropField();
2019 return MFU_TT_UL_ERROR;
2021 if (card.uid[0] == 0x02) {
2022 // ST25TN
2023 // read SYSBLOCK
2024 uint8_t data[4] = {0x00};
2025 int status = ul_read(0x02, data, sizeof(data));
2026 if (status <= 1) {
2027 tagtype = MFU_TT_UL;
2028 } else {
2029 status = ul_read(data[1] + 1, data, sizeof(data));
2030 if (status <= 1) {
2031 tagtype = MFU_TT_UL;
2032 } else {
2033 // data[3] == KID == 0x05 Key ID
2034 // data[2] == REV == 0x13 Product version
2035 if ((data[1]==0x90) && (data[0]==0x90)) {
2036 tagtype = MFU_TT_ST25TN01K;
2037 } else if ((data[1]==0x90) && (data[0]==0x91)) {
2038 tagtype = MFU_TT_ST25TN512;
2042 } else if (card.uid[0] == 0x05) {
2043 // Infineon MY-D tests Exam high nibble
2044 DropField();
2045 uint8_t nib = (card.uid[1] & 0xf0) >> 4;
2046 switch (nib) {
2047 // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
2048 case 1:
2049 tagtype = MFU_TT_MY_D;
2050 break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
2051 case 2:
2052 tagtype = MFU_TT_MY_D_NFC;
2053 break; // or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
2054 case 3:
2055 tagtype = (MFU_TT_MY_D_MOVE | MFU_TT_MY_D_MOVE_NFC);
2056 break; // or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
2057 case 7:
2058 tagtype = MFU_TT_MY_D_MOVE_LEAN;
2059 break; // or SLE 66R01L // 16 pages of 4 bytes
2061 } else {
2063 uint8_t version[10] = {0x00};
2064 int len = ulev1_getVersion(version, sizeof(version));
2065 DropField();
2066 switch (len) {
2067 case 0x0A: {
2069 MF0UL1001DUx 0004030100000B03
2070 MF0UL1101DUx 0004030101000B03
2071 MF0ULH1101DUx 0004030201000B03
2072 MF0UL1141DUF 0004030301000B03
2073 MF0UL2101Dxy 0004030101000E03
2074 MF0UL2101DUx 0004030201000E03
2075 MF0UL3101DUx 0004030101001103
2076 MF0ULH3101DUx 0004030201001103
2077 MF0UL5101DUx 0004030101001303
2078 NT2L1011F0DUx 0004040101000B03
2079 NT2H1011G0DUD 0004040201000B03
2080 NT2L1211F0DUx 0004040101000E03
2081 NT2H1311G0DUx 0004040201000F03
2082 NT2H1311F0Dxy 0004040401000F03
2083 NT2H1411G0DUx 0004040201011103
2084 NT2H1511G0DUx 0004040201001103
2085 NT2H1511F0Dxy 0004040401001103
2086 NT2H1611G0DUx 0004040201001303
2087 NT2H1611F0Dxy 0004040401001303
2088 NT2H1311C1DTL 0004040201010F03
2089 NT2H1311TTDUx 0004040203000F03
2090 NT3H1101W0FHK 0004040502001303
2091 NT3H1201W0FHK 0004040502001503
2092 NT3H1101W0FHK_Variant 0004040502011303
2093 NT3H1201 0004040502011503
2094 NT3H2111 0004040502021303
2095 NT3H2211 0004040502021503
2096 nhs 0004040600001303
2097 MF0UN0001DUx 0004030102000B03
2098 MF0UNH0001DUx 0004030202000B03
2099 MF0UN1001DUx 0004030103000B03
2100 MF0UNH1001DUx 0004030203000B03
2101 NT2L1001G0DUx 0004040102000B03
2102 NT2H1001G0DUx 0004040202000B03
2103 NT2H1311TTDUx 0004040203000F03
2104 MF0AES2001DUD 0004030104000F03
2106 Micron UL 0034210101000E03
2107 Feiju NTAG 0053040201000F03
2108 Feiju NTAG 215 0005340201001103
2111 if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { tagtype = MFU_TT_UL_EV1_48; break; }
2112 else if (memcmp(version, "\x00\x04\x03\x01\x02\x00\x0B", 7) == 0) { tagtype = MFU_TT_UL_NANO_40; break; }
2113 else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { tagtype = MFU_TT_UL_EV1_48; break; }
2114 else if (memcmp(version, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_UL_EV1_128; break; }
2115 else if (memcmp(version, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_UL_EV1_128; break; }
2116 else if (memcmp(version, "\x00\x04\x03\x01\x04\x00\x0F\x03", 8) == 0) { tagtype = MFU_TT_UL_AES; break; }
2117 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
2118 else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype = MFU_TT_NTAG_210; break; }
2119 else if (memcmp(version, "\x00\x04\x04\x01\x02\x00\x0B", 7) == 0) { tagtype = MFU_TT_NTAG_210u; break; }
2120 else if (memcmp(version, "\x00\x04\x04\x02\x02\x00\x0B", 7) == 0) { tagtype = MFU_TT_NTAG_210u; break; }
2121 else if (memcmp(version, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype = MFU_TT_NTAG_212; break; }
2122 else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213; break; }
2123 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)
2124 else if (memcmp(version, "\x00\x04\x04\x02\x01\x01\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213_C; break; }
2125 else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x11", 7) == 0) { tagtype = MFU_TT_NTAG_215; break; }
2126 else if (memcmp(version, "\x00\x05\x34\x02\x01\x00\x11", 7) == 0) { tagtype = MFU_TT_NTAG_215; break; } // Shanghai Feiju Microelectronics Co. Ltd. China
2127 else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x13", 7) == 0) { tagtype = MFU_TT_NTAG_216; break; }
2128 else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213_F; break; }
2129 else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x13", 7) == 0) { tagtype = MFU_TT_NTAG_216_F; break; }
2130 else if (memcmp(version, "\x00\x04\x04\x02\x03\x00\x0F", 7) == 0) { tagtype = MFU_TT_NTAG_213_TT; break; }
2131 else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x13", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_1K; break; }
2132 else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_2K; break; }
2133 else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_1K_PLUS; break; }
2134 else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x15", 7) == 0) { tagtype = MFU_TT_NTAG_I2C_2K_PLUS; break; }
2135 else if (version[2] == 0x04) { tagtype = MFU_TT_NTAG; break; }
2136 else if (version[2] == 0x03) { tagtype = MFU_TT_UL_EV1; }
2137 break;
2139 case 0x01:
2140 tagtype = MFU_TT_UL_C;
2141 break;
2142 case 0x00:
2143 tagtype = MFU_TT_UL;
2144 break;
2145 case PM3_ETIMEOUT:
2146 case PM3_EWRONGANSWER:
2147 tagtype = (MFU_TT_UL | MFU_TT_UL_C | MFU_TT_NTAG_203);
2148 break; // could be UL | UL_C magic tags
2149 default :
2150 tagtype = MFU_TT_UNKNOWN;
2151 break;
2153 // This is a test from cards that doesn't answer to GET_VERSION command
2154 // UL vs UL-C vs NTAG203 vs FUDAN FM11NT021 (which is NTAG213 compatiable)
2155 if (tagtype & (MFU_TT_UL | MFU_TT_UL_C | MFU_TT_NTAG_203)) {
2156 if (ul_select(&card) == false) {
2157 return MFU_TT_UL_ERROR;
2160 // do UL_C check first...
2161 uint8_t nonce[11] = {0x00};
2162 int status = ulc_requestAuthentication(nonce, sizeof(nonce));
2163 DropField();
2164 if (status > 1) {
2165 tagtype = MFU_TT_UL_C;
2166 } else {
2167 // need to re-select after authentication error
2168 if (ul_select(&card) == false) {
2169 return MFU_TT_UL_ERROR;
2172 uint8_t data[16] = {0x00};
2174 // read page 0x26-0x29 (last valid ntag203 page)
2175 // if error response, its ULTRALIGHT since doesn't have that memory block
2176 status = ul_read(0x26, data, sizeof(data));
2177 if (status <= 1) {
2178 tagtype = MFU_TT_UL;
2179 } else {
2181 // read page 44 / 0x2C
2182 // if error response, its NTAG203 since doesn't have that memory block
2183 status = ul_read(0x2C, data, sizeof(data));
2184 if (status <= 1) {
2185 tagtype = MFU_TT_NTAG_203;
2186 } else {
2188 // read page 48 / 0x30
2189 // if response, its FUDAN FM11NT021
2190 status = ul_read(0x30, data, sizeof(data));
2191 if (status == sizeof(data)) {
2192 tagtype = MFU_TT_NTAG_213;
2193 } else {
2194 tagtype = MFU_TT_UNKNOWN;
2198 DropField();
2202 if (tagtype & MFU_TT_UL) {
2203 tagtype = ul_fudan_check();
2204 DropField();
2208 tagtype |= ul_magic_test();
2209 if (tagtype == (MFU_TT_UNKNOWN | MFU_TT_MAGIC)) {
2210 tagtype = (MFU_TT_UL_MAGIC);
2213 return tagtype;
2216 // extended tag information
2218 static int CmdHF14AMfUInfo(const char *Cmd) {
2220 CLIParserContext *ctx;
2221 CLIParserInit(&ctx, "hf mfu info",
2222 "Get info about MIFARE Ultralight Family styled tag.\n"
2223 "Sometimes the tags are locked down, and you may need a key to be able to read the information",
2224 "hf mfu info\n"
2225 "hf mfu info -k AABBCCDD\n"
2226 "hf mfu info --key 00112233445566778899AABBCCDDEEFF"
2229 void *argtable[] = {
2230 arg_param_begin,
2231 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2232 arg_lit0("l", NULL, "Swap entered key's endianness"),
2233 // arg_lit0("v", "verbose", "verbose output"),
2234 arg_lit0(NULL, "force", "override `hw dbg` settings"),
2235 arg_param_end
2237 CLIExecWithReturn(ctx, Cmd, argtable, true);
2239 int ak_len = 0;
2240 uint8_t authenticationkey[16] = {0x00};
2241 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
2242 bool swap_endian = arg_get_lit(ctx, 2);
2243 // bool verbose = arg_get_lit(ctx, 3);
2244 bool override = (arg_get_lit(ctx, 3) == false);
2245 CLIParserFree(ctx);
2247 if (ak_len) {
2248 if (ak_len != 16 && ak_len != 4) {
2249 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2250 return PM3_EINVARG;
2254 bool has_auth_key = false;
2255 if (ak_len > 0)
2256 has_auth_key = true;
2258 uint8_t authlim = 0xff;
2259 uint8_t data[16] = {0x00};
2260 iso14a_card_select_t card;
2261 int status;
2262 uint8_t *authkeyptr = authenticationkey;
2263 uint8_t pwd[4] = {0, 0, 0, 0};
2264 uint8_t *key = pwd;
2265 uint8_t pack[4] = {0, 0, 0, 0};
2266 int len;
2268 uint64_t tagtype = GetHF14AMfU_Type();
2269 if (tagtype == MFU_TT_UL_ERROR) {
2270 return PM3_ESOFT;
2273 PrintAndLogEx(NORMAL, "");
2274 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
2275 ul_print_type(tagtype, 6);
2277 // Swap endianness
2278 if (swap_endian && has_auth_key) {
2279 authkeyptr = SwapEndian64(authenticationkey, ak_len, (ak_len == 16) ? 8 : 4);
2282 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2283 return PM3_ESOFT;
2286 bool locked = false;
2287 // read pages 0,1,2,3 (should read 4 pages)
2288 status = ul_read(0, data, sizeof(data));
2289 if (status <= 0) {
2290 DropField();
2291 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
2292 return PM3_ESOFT;
2293 } else if (status == 16) {
2294 ul_print_default(data, card.uid);
2295 ndef_print_CC(data + 12);
2296 } else {
2297 locked = true;
2300 // UL_C Specific
2301 if ((tagtype & MFU_TT_UL_C)) {
2303 // read pages 0x28, 0x29, 0x2A, 0x2B
2304 uint8_t ulc_conf[16] = {0x00};
2305 status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
2306 if (status <= 0) {
2307 PrintAndLogEx(ERR, "Error: tag didn't answer to READ UL-C");
2308 PrintAndLogEx(HINT, "Hint: tag is likely fully read protected");
2309 DropField();
2310 return PM3_ESOFT;
2313 if (status == 16) {
2314 ulc_print_configuration(ulc_conf);
2315 } else {
2316 locked = true;
2319 mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
2321 DropField();
2323 if ((tagtype & MFU_TT_MAGIC) == MFU_TT_MAGIC) {
2324 //just read key
2325 uint8_t ulc_deskey[16] = {0x00};
2326 status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
2327 if (status <= 0) {
2328 DropField();
2329 PrintAndLogEx(ERR, "Error: tag didn't answer to READ magic");
2330 return PM3_ESOFT;
2333 if (status == 16) {
2334 ulc_print_3deskey(ulc_deskey);
2337 PrintAndLogEx(NORMAL, "");
2338 return PM3_SUCCESS;
2340 } else {
2341 // if we called info with key, just return
2342 if (has_auth_key) {
2343 PrintAndLogEx(NORMAL, "");
2344 return PM3_SUCCESS;
2347 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
2348 if (try_default_3des_keys(override, &key) == PM3_SUCCESS) {
2349 PrintAndLogEx(SUCCESS, "Found default 3des key: ");
2350 uint8_t keySwap[16];
2351 memcpy(keySwap, SwapEndian64(key, 16, 8), 16);
2352 ulc_print_3deskey(keySwap);
2353 } else {
2354 PrintAndLogEx(INFO, "n/a");
2357 PrintAndLogEx(NORMAL, "");
2358 return PM3_SUCCESS;
2362 // Specific UL-AES
2363 if (tagtype & MFU_TT_UL_AES) {
2365 // read pages 0x28, 0x29, 0x2A, 0x2B
2366 uint8_t ulaes_conf[16] = {0x00};
2367 status = ul_read(0x29, ulaes_conf, sizeof(ulaes_conf));
2368 if (status <= 0) {
2369 PrintAndLogEx(ERR, "Error: tag didn't answer to READ UL-AES");
2370 DropField();
2371 return PM3_ESOFT;
2374 if (status == 16) {
2375 ulaes_print_configuration(ulaes_conf, 0x29);
2376 } else {
2377 locked = true;
2380 DropField();
2382 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
2383 if (try_default_aes_keys(override) != PM3_SUCCESS) {
2384 PrintAndLogEx(INFO, "n/a");
2386 DropField();
2388 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2389 return PM3_ESOFT;
2393 // do counters and signature first (don't neet auth)
2395 // ul counters are different than ntag counters
2396 if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1))) {
2397 if (ulev1_print_counters() != 3) {
2398 // failed - re-select
2399 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2400 return PM3_ESOFT;
2405 // NTAG counters?
2406 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))) {
2407 if (ntag_print_counter()) {
2408 // failed - re-select
2409 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2410 return PM3_ESOFT;
2415 // ST25TN info & signature
2416 if (tagtype & (MFU_TT_ST25TN512 | MFU_TT_ST25TN01K)) {
2417 status = ul_read(0x02, data, sizeof(data));
2418 if (status <= 1) {
2419 PrintAndLogEx(ERR, "Error: tag didn't answer to READ SYSBLOCK");
2420 DropField();
2421 return PM3_ESOFT;
2423 status = ul_read(data[1] + 1, data, sizeof(data));
2424 if (status <= 1) {
2425 PrintAndLogEx(ERR, "Error: tag didn't answer to READ SYSBLOCK");
2426 DropField();
2427 return PM3_ESOFT;
2429 PrintAndLogEx(INFO, "--- " _CYAN_("Tag System Information"));
2430 PrintAndLogEx(INFO, " Key ID: %02x", data[3]);
2431 PrintAndLogEx(INFO, " Product Version: %02x", data[2]);
2432 PrintAndLogEx(INFO, " Product Code: %02x%02x", data[1], data[0]);
2433 uint8_t signature[32] = {0};
2434 for (int blkoff=0; blkoff<8; blkoff++) {
2435 status = ul_read(0x34 + blkoff, signature + (blkoff * 4), 4);
2436 if (status <= 1) {
2437 PrintAndLogEx(ERR, "Error: tag didn't answer to READ SYSBLOCK");
2438 DropField();
2439 return PM3_ESOFT;
2442 // check signature
2443 int index = originality_check_verify_ex(card.uid, 7, signature, sizeof(signature), PK_ST25TN, false, true);
2444 PrintAndLogEx(NORMAL, "");
2445 originality_check_print(signature, sizeof(signature), index);
2448 // Read signature
2449 if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
2450 MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
2451 MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216 | MFU_TT_NTAG_216_F |
2452 MFU_TT_NTAG_I2C_1K | MFU_TT_NTAG_I2C_2K | MFU_TT_NTAG_I2C_1K_PLUS | MFU_TT_NTAG_I2C_2K_PLUS |
2453 MFU_TT_UL_AES))) {
2454 uint8_t ulev1_signature[48] = {0x00};
2455 status = ulev1_readSignature(ulev1_signature, sizeof(ulev1_signature));
2456 if (status < 0) {
2457 PrintAndLogEx(ERR, "Error: tag didn't answer to READ SIGNATURE");
2458 DropField();
2459 return PM3_ESOFT;
2461 if (status == 32 || status == 34) {
2462 ulev1_print_signature(tagtype, card.uid, ulev1_signature, 32);
2463 } else if (status == 48) {
2464 ulev1_print_signature(tagtype, card.uid, ulev1_signature, 48);
2465 } else {
2466 // re-select
2467 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2468 return PM3_ESOFT;
2472 // print silicon info
2473 ul_print_nxp_silicon_info(card.uid);
2475 // Get Version
2476 uint8_t version[10] = {0x00};
2477 status = ulev1_getVersion(version, sizeof(version));
2478 if (status < 0) {
2479 PrintAndLogEx(ERR, "Error: tag didn't answer to GETVERSION");
2480 DropField();
2481 return PM3_ESOFT;
2482 } else if (status == 10) {
2483 ulev1_print_version(version);
2484 } else {
2485 locked = true;
2486 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2487 return PM3_ESOFT;
2491 // Don't check config / passwords for Ul AES :)
2492 if (tagtype == MFU_TT_UL_AES) {
2493 goto out;
2496 uint8_t startconfigblock = 0;
2497 uint8_t ulev1_conf[16] = {0x00};
2499 for (uint8_t i = 1; i < ARRAYLEN(UL_TYPES_ARRAY); i++) {
2500 if ((tagtype & UL_TYPES_ARRAY[i]) == UL_TYPES_ARRAY[i]) {
2501 startconfigblock = UL_MEMORY_ARRAY[i] - 3;
2502 break;
2506 if (startconfigblock) { // if we know where the config block is...
2507 status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
2508 if (status <= 0) {
2509 PrintAndLogEx(ERR, "Error: tag didn't answer to READ EV1");
2510 DropField();
2511 return PM3_ESOFT;
2512 } else if (status == 16) {
2513 // save AUTHENTICATION LIMITS for later:
2514 authlim = (ulev1_conf[4] & 0x07);
2515 // add pwd / pack if used from cli
2516 if (has_auth_key) {
2517 memcpy(ulev1_conf + 8, authkeyptr, 4);
2518 memcpy(ulev1_conf + 12, pack, 2);
2520 ulev1_print_configuration(tagtype, ulev1_conf, startconfigblock);
2524 // AUTHLIMIT, (number of failed authentications)
2525 // 0 = limitless.
2526 // 1-7 = limit. No automatic tries then.
2527 // hasAuthKey, if we was called with key, skip test.
2528 if (!authlim && (has_auth_key == false)) {
2529 PrintAndLogEx(NORMAL, "");
2530 PrintAndLogEx(SUCCESS, "--- " _CYAN_("Known EV1/NTAG passwords"));
2532 // test pwd gen A
2533 num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key);
2534 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2535 if (len > -1) {
2536 has_auth_key = true;
2537 ak_len = 4;
2538 memcpy(authenticationkey, key, 4);
2539 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2540 goto out;
2543 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2544 return PM3_ESOFT;
2547 // test pwd gen B
2548 num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
2549 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2550 if (len > -1) {
2551 has_auth_key = true;
2552 ak_len = 4;
2553 memcpy(authenticationkey, key, 4);
2554 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2555 goto out;
2558 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2559 return PM3_ESOFT;
2562 // test pwd gen C
2563 num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key);
2564 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2565 if (len > -1) {
2566 has_auth_key = true;
2567 ak_len = 4;
2568 memcpy(authenticationkey, key, 4);
2569 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2570 goto out;
2573 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2574 return PM3_ESOFT;
2577 // test pwd gen D
2578 num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key);
2579 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2580 if (len > -1) {
2581 has_auth_key = true;
2582 ak_len = 4;
2583 memcpy(authenticationkey, key, 4);
2584 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2585 goto out;
2588 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2589 return PM3_ESOFT;
2592 for (uint8_t i = 0; i < ARRAYLEN(default_pwd_pack); ++i) {
2593 key = default_pwd_pack[i];
2594 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
2595 if (len > -1) {
2596 has_auth_key = true;
2597 ak_len = 4;
2598 memcpy(authenticationkey, key, 4);
2599 PrintAndLogEx(SUCCESS, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key, 4), pack[0], pack[1]);
2600 break;
2601 } else {
2602 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
2603 return PM3_ESOFT;
2607 if (len < 1) {
2608 PrintAndLogEx(WARNING, _YELLOW_("password not known"));
2609 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2611 } else {
2612 if (locked) {
2613 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2618 out:
2619 DropField();
2621 mfu_fingerprint(tagtype, has_auth_key, authkeyptr, ak_len);
2623 if (locked) {
2624 PrintAndLogEx(INFO, "\nTag appears to be locked, try using a key to get more info");
2625 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2628 if (tagtype & (MFU_TT_MAGIC_1A | MFU_TT_MAGIC_1B | MFU_TT_MAGIC_2)) {
2629 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`script run hf_mfu_setuid -h`") " to set UID");
2632 PrintAndLogEx(NORMAL, "");
2633 return PM3_SUCCESS;
2637 // Write Single Block
2639 static int CmdHF14AMfUWrBl(const char *Cmd) {
2641 CLIParserContext *ctx;
2642 CLIParserInit(&ctx, "hf mfu wrbl",
2643 "Write a block. It autodetects card type.",
2644 "hf mfu wrbl -b 0 -d 01234567\n"
2645 "hf mfu wrbl -b 0 -d 01234567 -k AABBCCDD\n"
2646 "hf mfu wrbl -b 0 -d 01234567 -k 00112233445566778899AABBCCDDEEFF"
2649 void *argtable[] = {
2650 arg_param_begin,
2651 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2652 arg_lit0("l", NULL, "Swap entered key's endianness"),
2653 arg_int1("b", "block", "<dec>", "Block number to write"),
2654 arg_str1("d", "data", "<hex>", "Block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"),
2655 arg_lit0(NULL, "force", "Force operation even if address is out of range"),
2656 arg_param_end
2658 CLIExecWithReturn(ctx, Cmd, argtable, false);
2660 int ak_len = 0;
2661 uint8_t authenticationkey[16] = {0x00};
2662 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
2663 bool swap_endian = arg_get_lit(ctx, 2);
2665 int blockno = arg_get_int_def(ctx, 3, -1);
2667 int datalen = 0;
2668 uint8_t data[16] = {0x00};
2669 CLIGetHexWithReturn(ctx, 4, data, &datalen);
2670 bool force = arg_get_lit(ctx, 5);
2671 CLIParserFree(ctx);
2673 bool has_auth_key = false;
2674 bool has_pwd = false;
2675 if (ak_len == 16) {
2676 has_auth_key = true;
2677 } else if (ak_len == 4) {
2678 has_pwd = true;
2679 } else if (ak_len != 0) {
2680 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2681 return PM3_EINVARG;
2684 if (blockno < 0) {
2685 PrintAndLogEx(WARNING, "Wrong block number");
2686 return PM3_EINVARG;
2689 if (datalen != 16 && datalen != 4) {
2690 PrintAndLogEx(WARNING, "Wrong data length. Expect 16 or 4, got %d", datalen);
2691 return PM3_EINVARG;
2694 uint8_t *auth_key_ptr = authenticationkey;
2696 // starting with getting tagtype
2697 uint64_t tagtype = GetHF14AMfU_Type();
2698 if (tagtype == MFU_TT_UL_ERROR)
2699 return PM3_ESOFT;
2701 uint8_t maxblockno = 0;
2702 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
2703 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
2704 maxblockno = UL_MEMORY_ARRAY[idx];
2705 break;
2708 if ((blockno > maxblockno) && (!force)) {
2709 PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
2710 return PM3_EINVARG;
2713 // Swap endianness
2714 if (swap_endian) {
2715 if (has_auth_key)
2716 auth_key_ptr = SwapEndian64(authenticationkey, 16, 8);
2718 if (has_pwd)
2719 auth_key_ptr = SwapEndian64(authenticationkey, 4, 4);
2722 if (blockno <= 3)
2723 PrintAndLogEx(INFO, "Special block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen));
2724 else
2725 PrintAndLogEx(INFO, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen));
2727 if (ak_len) {
2728 PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
2732 // Send write Block.
2733 uint8_t *d = data;
2734 int res = 0;
2735 if (datalen == 16) {
2736 // Comp write may take 16bytes, but only write 4bytes. See UL-C datasheet
2737 for (uint8_t i = 0; i < 4; i++) {
2739 res = mfu_write_block(d, 4, has_auth_key, has_pwd, auth_key_ptr, blockno + i);
2740 if (res == PM3_SUCCESS) {
2741 d += 4;
2742 } else {
2743 PrintAndLogEx(INFO, "Write ( %s )", _RED_("fail"));
2744 return PM3_ESOFT;
2748 if (res == PM3_SUCCESS) {
2749 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
2750 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno);
2753 } else {
2754 res = mfu_write_block(data, datalen, has_auth_key, has_pwd, auth_key_ptr, blockno);
2755 switch (res) {
2756 case PM3_SUCCESS: {
2757 PrintAndLogEx(SUCCESS, "Write ( " _GREEN_("ok") " )");
2758 PrintAndLogEx(HINT, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno);
2759 break;
2761 case PM3_ESOFT: {
2762 PrintAndLogEx(FAILED, "Write ( " _RED_("fail") " )");
2763 PrintAndLogEx(HINT, "Check password / key!");
2764 break;
2766 case PM3_ETIMEOUT:
2767 default: {
2768 PrintAndLogEx(WARNING, "command execution time out");
2769 break;
2774 return res;
2777 // Read Single Block
2779 static int CmdHF14AMfURdBl(const char *Cmd) {
2781 CLIParserContext *ctx;
2782 CLIParserInit(&ctx, "hf mfu rdbl",
2783 "Read a block and print. It autodetects card type.",
2784 "hf mfu rdbl -b 0\n"
2785 "hf mfu rdbl -b 0 -k AABBCCDD\n"
2786 "hf mfu rdbl -b 0 --key 00112233445566778899AABBCCDDEEFF"
2789 void *argtable[] = {
2790 arg_param_begin,
2791 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2792 arg_lit0("l", NULL, "Swap entered key's endianness"),
2793 arg_int1("b", "block", "<dec>", "Block number to read"),
2794 arg_lit0(NULL, "force", "Force operation even if address is out of range"),
2795 arg_param_end
2797 CLIExecWithReturn(ctx, Cmd, argtable, false);
2799 int ak_len = 0;
2800 uint8_t authenticationkey[16] = {0x00};
2801 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
2802 bool swap_endian = arg_get_lit(ctx, 2);
2803 int blockno = arg_get_int_def(ctx, 3, -1);
2804 bool force = arg_get_lit(ctx, 4);
2805 CLIParserFree(ctx);
2807 bool has_auth_key = false;
2808 bool has_pwd = false;
2809 if (ak_len == 16) {
2810 has_auth_key = true;
2811 } else if (ak_len == 4) {
2812 has_pwd = true;
2813 } else if (ak_len != 0) {
2814 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2815 return PM3_EINVARG;
2818 if (blockno < 0) {
2819 PrintAndLogEx(WARNING, "Wrong block number");
2820 return PM3_EINVARG;
2823 uint8_t *authKeyPtr = authenticationkey;
2825 // start with getting tagtype
2826 uint64_t tagtype = GetHF14AMfU_Type();
2827 if (tagtype == MFU_TT_UL_ERROR)
2828 return PM3_ESOFT;
2830 uint8_t maxblockno = 0;
2831 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
2832 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
2833 maxblockno = UL_MEMORY_ARRAY[idx];
2834 break;
2837 if ((blockno > maxblockno) && (!force)) {
2838 PrintAndLogEx(WARNING, "block number to large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
2839 return PM3_EINVARG;
2842 // Swap endianness
2843 if (swap_endian) {
2844 if (has_auth_key)
2845 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
2847 if (has_pwd)
2848 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
2851 if (ak_len) {
2852 PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
2855 //Read Block
2856 uint8_t keytype = 0;
2857 uint8_t datalen = 0;
2858 if (has_auth_key) {
2859 keytype = 1;
2860 datalen = 16;
2861 } else if (has_pwd) {
2862 keytype = 2;
2863 datalen = 4;
2866 clearCommandBuffer();
2867 SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, keytype, 0, authKeyPtr, datalen);
2868 PacketResponseNG resp;
2869 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
2870 uint8_t isOK = resp.oldarg[0] & 0xff;
2871 if (isOK) {
2872 uint8_t *d = resp.data.asBytes;
2873 PrintAndLogEx(NORMAL, "");
2874 PrintAndLogEx(INFO, "Block# | Data | Ascii");
2875 PrintAndLogEx(INFO, "-----------------------------");
2876 PrintAndLogEx(INFO, "%02d/0x%02X | %s| %s\n", blockno, blockno, sprint_hex(d, 4), sprint_ascii(d, 4));
2877 } else {
2878 PrintAndLogEx(WARNING, "Failed reading block: ( %02x )", isOK);
2880 } else {
2881 PrintAndLogEx(WARNING, "command execution time out");
2883 return PM3_SUCCESS;
2886 void mfu_print_dump(mfu_dump_t *card, uint16_t pages, uint8_t startpage, bool dense_output) {
2888 PrintAndLogEx(NORMAL, "");
2889 PrintAndLogEx(INFO, _CYAN_("MFU dump file information"));
2890 PrintAndLogEx(INFO, "-------------------------------------------------------------");
2891 PrintAndLogEx(INFO, "Version..... " _YELLOW_("%s"), sprint_hex(card->version, sizeof(card->version)));
2892 PrintAndLogEx(INFO, "TBD 0....... %s", sprint_hex(card->tbo, sizeof(card->tbo)));
2893 PrintAndLogEx(INFO, "TBD 1....... %s", sprint_hex(card->tbo1, sizeof(card->tbo1)));
2894 PrintAndLogEx(INFO, "Signature... %s", sprint_hex(card->signature, 16));
2895 PrintAndLogEx(INFO, " %s", sprint_hex(card->signature + 16, sizeof(card->signature) - 16));
2896 for (uint8_t i = 0; i < 3; i ++) {
2897 PrintAndLogEx(INFO, "Counter %d... %s", i, sprint_hex(card->counter_tearing[i], 3));
2898 PrintAndLogEx(INFO, "Tearing %d... %s", i, sprint_hex(card->counter_tearing[i] + 3, 1));
2901 // 0-bases index, to get total bytes, its +1 page.
2902 // UL-C,
2903 // Max index page is 47.
2904 // total pages is 48
2905 // total bytes is 192
2906 PrintAndLogEx(INFO, "Max data page... " _YELLOW_("%d") " ( " _YELLOW_("%d") " bytes )", card->pages, (card->pages + 1) * MFU_BLOCK_SIZE);
2907 PrintAndLogEx(INFO, "Header size..... %d bytes", MFU_DUMP_PREFIX_LENGTH);
2909 uint8_t j = 0;
2910 bool lckbit = false;
2911 uint8_t *data = card->data;
2913 uint8_t lockbytes_sta[] = {0, 0};
2914 uint8_t lockbytes_dyn[] = {0, 0, 0};
2915 bool bit_stat[16] = {0};
2916 bool bit_dyn[16] = {0};
2918 // Load static lock bytes.
2919 memcpy(lockbytes_sta, data + 10, sizeof(lockbytes_sta));
2920 for (j = 0; j < 16; j++) {
2921 bit_stat[j] = lockbytes_sta[j / 8] & (1 << (7 - j % 8));
2924 // Load dynamic lockbytes if available
2925 // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG
2926 if (pages == 44) {
2928 memcpy(lockbytes_dyn, data + (40 * 4), sizeof(lockbytes_dyn));
2930 for (j = 0; j < 16; j++) {
2931 bit_dyn[j] = lockbytes_dyn[j / 8] & (1 << (7 - j % 8));
2933 PrintAndLogEx(INFO, "Dynamic lock.... %s", sprint_hex(lockbytes_dyn, 3));
2936 PrintAndLogEx(NORMAL, "");
2937 PrintAndLogEx(INFO, "-------------------------------------------------------------");
2938 PrintAndLogEx(INFO, "block# | data |lck| ascii");
2939 PrintAndLogEx(INFO, "---------+-------------+---+------");
2941 bool in_repeated_block = false;
2943 for (uint16_t i = 0; i < pages; ++i) {
2944 if (i < 3) {
2945 PrintAndLogEx(INFO, "%3d/0x%02X | " _RED_("%s")"| | %s",
2946 i + startpage,
2947 i + startpage,
2948 sprint_hex(data + i * 4, 4),
2949 sprint_ascii(data + i * 4, 4)
2951 continue;
2953 switch (i) {
2954 case 3:
2955 lckbit = bit_stat[4];
2956 break;
2957 case 4:
2958 lckbit = bit_stat[3];
2959 break;
2960 case 5:
2961 lckbit = bit_stat[2];
2962 break;
2963 case 6:
2964 lckbit = bit_stat[1];
2965 break;
2966 case 7:
2967 lckbit = bit_stat[0];
2968 break;
2969 case 8:
2970 lckbit = bit_stat[15];
2971 break;
2972 case 9:
2973 lckbit = bit_stat[14];
2974 break;
2975 case 10:
2976 lckbit = bit_stat[13];
2977 break;
2978 case 11:
2979 lckbit = bit_stat[12];
2980 break;
2981 case 12:
2982 lckbit = bit_stat[11];
2983 break;
2984 case 13:
2985 lckbit = bit_stat[10];
2986 break;
2987 case 14:
2988 lckbit = bit_stat[9];
2989 break;
2990 case 15:
2991 lckbit = bit_stat[8];
2992 break;
2993 case 16:
2994 case 17:
2995 case 18:
2996 case 19:
2997 lckbit = bit_dyn[6];
2998 break;
2999 case 20:
3000 case 21:
3001 case 22:
3002 case 23:
3003 lckbit = bit_dyn[5];
3004 break;
3005 case 24:
3006 case 25:
3007 case 26:
3008 case 27:
3009 lckbit = bit_dyn[4];
3010 break;
3011 case 28:
3012 case 29:
3013 case 30:
3014 case 31:
3015 lckbit = bit_dyn[2];
3016 break;
3017 case 32:
3018 case 33:
3019 case 34:
3020 case 35:
3021 lckbit = bit_dyn[1];
3022 break;
3023 case 36:
3024 case 37:
3025 case 38:
3026 case 39:
3027 lckbit = bit_dyn[0];
3028 break;
3029 case 40:
3030 lckbit = bit_dyn[12];
3031 break;
3032 case 41:
3033 lckbit = bit_dyn[11];
3034 break;
3035 case 42:
3036 lckbit = bit_dyn[10];
3037 break; //auth0
3038 case 43:
3039 lckbit = bit_dyn[9];
3040 break; //auth1
3041 default:
3042 break;
3046 // suppress repeating blocks, truncate as such that the first and last block with the same data is shown
3047 // but the blocks in between are replaced with a single line of "......" if dense_output is enabled
3048 const uint8_t *blk = data + (i * MFU_BLOCK_SIZE);
3049 if (dense_output &&
3050 (i > 3) &&
3051 (i < pages) &&
3052 (in_repeated_block == false) &&
3053 (memcmp(blk, blk - MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) == 0) &&
3054 (memcmp(blk, blk + MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) == 0) &&
3055 (memcmp(blk, blk + (MFU_BLOCK_SIZE * 2), MFU_BLOCK_SIZE) == 0)
3057 // we're in a user block that isn't the first user block nor last two user blocks,
3058 // and the current block data is the same as the previous and next two block
3059 in_repeated_block = true;
3060 PrintAndLogEx(INFO, " ......");
3061 } else if (in_repeated_block &&
3062 (memcmp(blk, blk + MFU_BLOCK_SIZE, MFU_BLOCK_SIZE) || i == pages)
3064 // in a repeating block, but the next block doesn't match anymore, or we're at the end block
3065 in_repeated_block = false;
3069 if (in_repeated_block == false) {
3070 PrintAndLogEx(INFO, "%3d/0x%02X | %s| %s | %s"
3071 , i + startpage
3072 , i + startpage
3073 , sprint_hex(data + i * 4, 4)
3074 , (lckbit) ? _RED_("1") : "0"
3075 , sprint_ascii(data + i * 4, 4)
3079 PrintAndLogEx(INFO, "---------------------------------");
3083 // Mifare Ultralight / Ultralight-C / Ultralight-EV1
3084 // Read and Dump Card Contents, using auto detection of tag size.
3085 static int CmdHF14AMfUDump(const char *Cmd) {
3087 CLIParserContext *ctx;
3088 CLIParserInit(&ctx, "hf mfu dump",
3089 "Dump MIFARE Ultralight/NTAG tag to files (bin/json)\n"
3090 "It autodetects card type."
3091 "Supports:\n"
3092 "Ultralight, Ultralight-C, Ultralight EV1\n"
3093 "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216\n",
3094 "hf mfu dump -f myfile\n"
3095 "hf mfu dump -k AABBCCDD -> dump whole tag using pwd AABBCCDD\n"
3096 "hf mfu dump -p 10 -> start at page 10 and dump rest of blocks\n"
3097 "hf mfu dump -p 10 -q 2 -> start at page 10 and dump two blocks\n"
3098 "hf mfu dump --key 00112233445566778899AABBCCDDEEFF"
3101 void *argtable[] = {
3102 arg_param_begin,
3103 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
3104 arg_str0("k", "key", "<hex>", "Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
3105 arg_lit0("l", NULL, "Swap entered key's endianness"),
3106 arg_int0("p", "page", "<dec>", "Manually set start page number to start from"),
3107 arg_int0("q", "qty", "<dec>", "Manually set number of pages to dump"),
3108 arg_lit0(NULL, "ns", "no save to file"),
3109 arg_lit0("z", "dense", "dense dump output style"),
3110 arg_param_end
3112 CLIExecWithReturn(ctx, Cmd, argtable, true);
3114 int fnlen = 0;
3115 char filename[FILE_PATH_SIZE] = {0};
3116 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3118 int ak_len = 0;
3119 uint8_t authenticationkey[16] = {0x00};
3120 uint8_t *authKeyPtr = authenticationkey;
3121 CLIGetHexWithReturn(ctx, 2, authenticationkey, &ak_len);
3122 bool swap_endian = arg_get_lit(ctx, 3);
3123 int start_page = arg_get_int_def(ctx, 4, 0);
3124 int pages = arg_get_int_def(ctx, 5, 16);
3125 bool nosave = arg_get_lit(ctx, 6);
3126 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 7));
3127 CLIParserFree(ctx);
3129 bool has_auth_key = false;
3130 bool has_pwd = false;
3131 if (ak_len == 16) {
3132 has_auth_key = true;
3133 } else if (ak_len == 4) {
3134 has_pwd = true;
3135 } else if (ak_len != 0) {
3136 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
3137 return PM3_EINVARG;
3140 bool manual_pages = false;
3141 if (start_page > 0) {
3142 manual_pages = true;
3145 if (pages != 16) {
3146 manual_pages = true;
3149 uint8_t card_mem_size = 0;
3151 // Swap endianness
3152 if (swap_endian) {
3153 if (has_auth_key) {
3154 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
3157 if (has_pwd) {
3158 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
3162 uint64_t tagtype = GetHF14AMfU_Type();
3163 if (tagtype == MFU_TT_UL_ERROR) {
3164 return PM3_ESOFT;
3167 //get number of pages to read
3168 if (manual_pages == false) {
3169 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
3170 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
3171 //add one as maxblks starts at 0
3172 card_mem_size = pages = UL_MEMORY_ARRAY[idx] + 1;
3173 break;
3178 ul_print_type(tagtype, 0);
3179 PrintAndLogEx(SUCCESS, "Reading tag memory...");
3180 uint8_t keytype = 0;
3181 if (has_auth_key || has_pwd) {
3182 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C)
3183 keytype = 1; // UL_C auth
3184 else
3185 keytype = 2; // UL_EV1/NTAG auth
3188 uint8_t dbg_curr = DBG_NONE;
3189 if (getDeviceDebugLevel(&dbg_curr) != PM3_SUCCESS) {
3190 return PM3_ESOFT;
3193 if (setDeviceDebugLevel(DBG_NONE, false) != PM3_SUCCESS) {
3194 return PM3_ESOFT;
3197 clearCommandBuffer();
3198 SendCommandMIX(CMD_HF_MIFAREU_READCARD, start_page, pages, keytype, authKeyPtr, ak_len);
3199 PacketResponseNG resp;
3200 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
3201 PrintAndLogEx(WARNING, "command execution time out");
3202 return PM3_ETIMEOUT;
3205 if (resp.oldarg[0] != 1) {
3206 PrintAndLogEx(WARNING, "Failed dumping card");
3207 return PM3_ESOFT;
3210 setDeviceDebugLevel(dbg_curr, false);
3212 // read all memory
3213 uint8_t data[1024] = {0x00};
3214 memset(data, 0x00, sizeof(data));
3216 uint32_t startindex = resp.oldarg[2];
3217 uint32_t buffer_size = resp.oldarg[1];
3218 if (buffer_size > sizeof(data)) {
3219 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
3220 buffer_size = sizeof(data);
3223 if (GetFromDevice(BIG_BUF, data, buffer_size, startindex, NULL, 0, NULL, 2500, false) == false) {
3224 PrintAndLogEx(WARNING, "command execution time out");
3225 return PM3_ETIMEOUT;
3228 bool is_partial = (pages != buffer_size / MFU_BLOCK_SIZE);
3230 pages = buffer_size / MFU_BLOCK_SIZE;
3232 if (is_partial) {
3234 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
3235 if (card_mem_size != (pages + 4)) {
3236 PrintAndLogEx(INFO, "Partial dump, got " _RED_("%d") " bytes - card mem size is %u bytes", pages * MFU_BLOCK_SIZE, card_mem_size * MFU_BLOCK_SIZE);
3237 PrintAndLogEx(HINT, "Try using a key");
3239 } else {
3240 PrintAndLogEx(HINT, "Try using a pwd");
3244 iso14a_card_select_t card;
3245 mfu_dump_t dump_file_data;
3246 memset(&dump_file_data, 0, sizeof(dump_file_data));
3247 uint8_t get_version[] = {0, 0, 0, 0, 0, 0, 0, 0};
3248 uint8_t get_counter_tearing[][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
3249 uint8_t get_signature[32];
3250 memset(get_signature, 0, sizeof(get_signature));
3252 // not ul_c and not std ul then attempt to collect info like
3253 // VERSION, SIGNATURE, COUNTERS, TEARING, PACK,
3254 if (!(tagtype & MFU_TT_UL_C || tagtype & MFU_TT_UL || tagtype & MFU_TT_MY_D_MOVE || tagtype & MFU_TT_MY_D_MOVE_LEAN)) {
3255 // attempt to read pack
3256 bool has_key = (has_auth_key || has_pwd);
3257 uint8_t get_pack[] = {0, 0};
3258 if (ul_auth_select(&card, tagtype, has_key, authKeyPtr, get_pack, sizeof(get_pack)) != PM3_SUCCESS) {
3259 //reset pack
3260 get_pack[0] = 0;
3261 get_pack[1] = 0;
3263 DropField();
3265 // only add pack if not partial read, and complete pages read.
3266 if (!is_partial && pages == card_mem_size) {
3268 // add pack to block read
3269 memcpy(data + (pages * 4) - 4, get_pack, sizeof(get_pack));
3272 if (has_auth_key) {
3273 uint8_t dummy_pack[] = {0, 0};
3274 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3275 } else {
3276 ul_select(&card);
3279 ulev1_getVersion(get_version, sizeof(get_version));
3281 // ULEV-1 has 3 counters
3282 uint8_t n = 0;
3284 // NTAG has 1 counter, at 0x02
3285 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))) {
3286 n = 2;
3289 // NTAG can have nfc counter pwd protection enabled
3290 for (; n < 3; n++) {
3292 if (has_auth_key) {
3293 uint8_t dummy_pack[] = {0, 0};
3294 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3295 } else {
3296 ul_select(&card);
3298 ulev1_readCounter(n, &get_counter_tearing[n][0], 3);
3300 if (has_auth_key) {
3301 uint8_t dummy_pack[] = {0, 0};
3302 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3303 } else {
3304 ul_select(&card);
3306 ulev1_readTearing(n, &get_counter_tearing[n][3], 1);
3309 DropField();
3311 if (has_auth_key) {
3312 uint8_t dummy_pack[] = {0, 0};
3313 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
3314 } else {
3315 ul_select(&card);
3318 ulev1_readSignature(get_signature, sizeof(get_signature));
3319 DropField();
3323 // format and add keys to block dump output
3324 // only add keys if not partial read, and complete pages read
3326 // UL-C add a working known key
3327 if (has_auth_key && (tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) { // add 4 pages of key
3329 // if we didn't swapendian before - do it now for the sprint_hex call
3330 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
3331 // need to swap to keep it the same
3332 if (swap_endian == false) {
3333 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
3334 } else {
3335 authKeyPtr = authenticationkey;
3338 memcpy(data + pages * MFU_BLOCK_SIZE, authKeyPtr, ak_len);
3339 pages += ak_len / MFU_BLOCK_SIZE;
3341 // fix
3342 if (is_partial && pages == card_mem_size) {
3343 is_partial = false;
3347 if (!is_partial && pages == card_mem_size && has_pwd) {
3348 // if we didn't swapendian before - do it now for the sprint_hex call
3349 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
3350 // need to swap to keep it the same
3351 if (swap_endian == false) {
3352 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
3353 } else {
3354 authKeyPtr = authenticationkey;
3357 memcpy(data + (pages * MFU_BLOCK_SIZE) - 8, authenticationkey, ak_len);
3360 //add *special* blocks to dump
3361 // pack and pwd saved into last pages of dump, if was not partial read
3362 dump_file_data.pages = pages - 1;
3363 memcpy(dump_file_data.version, get_version, sizeof(dump_file_data.version));
3364 memcpy(dump_file_data.signature, get_signature, sizeof(dump_file_data.signature));
3365 memcpy(dump_file_data.counter_tearing, get_counter_tearing, sizeof(dump_file_data.counter_tearing));
3366 memcpy(dump_file_data.data, data, pages * MFU_BLOCK_SIZE);
3368 mfu_print_dump(&dump_file_data, pages, start_page, dense_output);
3370 if (nosave) {
3371 PrintAndLogEx(INFO, "Called with no save option");
3372 PrintAndLogEx(NORMAL, "");
3373 return PM3_SUCCESS;
3376 // user supplied filename?
3377 if (fnlen < 1) {
3378 PrintAndLogEx(INFO, "Using UID as filename");
3379 uint8_t uid[7] = {0};
3380 memcpy(uid, (uint8_t *)&dump_file_data.data, 3);
3381 memcpy(uid + 3, (uint8_t *)&dump_file_data.data + 4, 4);
3382 strcat(filename, "hf-mfu-");
3383 FillFileNameByUID(filename, uid, "-dump", sizeof(uid));
3386 uint16_t datalen = MFU_DUMP_PREFIX_LENGTH + (pages * MFU_BLOCK_SIZE);
3387 pm3_save_dump(filename, (uint8_t *)&dump_file_data, datalen, jsfMfuMemory);
3389 if (is_partial) {
3390 PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
3392 return PM3_SUCCESS;
3395 static void wait4response(uint8_t b) {
3396 PacketResponseNG resp;
3397 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
3398 uint8_t isOK = resp.oldarg[0] & 0xff;
3399 if (isOK == 0) {
3400 PrintAndLogEx(WARNING, "failed to write block %d", b);
3402 } else {
3403 PrintAndLogEx(WARNING, "command execution time out");
3408 //Configure tamper feature of NTAG 213TT
3410 int CmdHF14MfUTamper(const char *Cmd) {
3411 CLIParserContext *ctx;
3412 CLIParserInit(&ctx, "hf mfu tamper",
3413 "Set the configuration of the NTAG 213TT tamper feature\n"
3414 "Supports:\n"
3415 "NTAG 213TT\n",
3416 "hf mfu tamper -e -> enable tamper feature\n"
3417 "hf mfu tamper -d -> disable tamper feature\n"
3418 "hf mfu tamper -m 0A0A0A0A -> set the tamper message to 0A0A0A0A\n"
3419 "hf mfu tamper --lockmessage -> permanently lock the tamper message and mask it from memory\n"
3422 void *argtable[] = {
3423 arg_param_begin,
3424 arg_lit0("e", "enable", "Enable the tamper feature"),
3425 arg_lit0("d", "disable", "Disable the tamper feature"),
3426 arg_str0("m", "message", "<hex>", "Set the tamper message (4 bytes)"),
3427 arg_lit0(NULL, "lockmessage", "Permanently lock the tamper message and mask it from memory (does not lock tamper feature itself)"),
3428 arg_param_end
3430 CLIExecWithReturn(ctx, Cmd, argtable, false);
3432 int tt_cfg_page = 41;
3433 int tt_msg_page = 45;
3434 int msg_len = 0;
3435 uint8_t msg_data[4] = {0x00};
3436 CLIGetHexWithReturn(ctx, 3, msg_data, &msg_len);
3437 bool use_msg = (msg_len > 0);
3439 if (use_msg && msg_len != 4) {
3440 PrintAndLogEx(WARNING, "The tamper message must be 4 hex bytes if provided");
3441 DropField();
3442 CLIParserFree(ctx);
3443 return PM3_ESOFT;
3446 bool lock_msg = arg_get_lit(ctx, 4);
3447 bool enable = arg_get_lit(ctx, 1);
3448 bool disable = arg_get_lit(ctx, 2);
3449 CLIParserFree(ctx);
3451 uint64_t tagtype = GetHF14AMfU_Type();
3452 if (tagtype == MFU_TT_UL_ERROR) {
3453 PrintAndLogEx(WARNING, "Tag type not detected");
3454 DropField();
3455 return PM3_ESOFT;
3457 if (tagtype != MFU_TT_NTAG_213_TT) {
3458 PrintAndLogEx(WARNING, "Tag type not NTAG 213TT");
3459 DropField();
3460 return PM3_ESOFT;
3463 DropField();
3464 iso14a_card_select_t card;
3466 if (enable && disable) {
3467 PrintAndLogEx(WARNING, "You can only select one of the options enable/disable tamper feature");
3468 DropField();
3469 return PM3_ESOFT;
3472 if (use_msg) {
3473 if (ul_select(&card) == false) {
3474 DropField();
3475 return MFU_TT_UL_ERROR;
3477 PrintAndLogEx(INFO, "Trying to write tamper message");
3478 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_msg_page, 0, 0, msg_data, 4);
3480 PacketResponseNG resp;
3482 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
3483 uint8_t isOK = resp.oldarg[0] & 0xff;
3484 if (!isOK)
3485 PrintAndLogEx(WARNING, "Failed to write tamper message");
3486 else
3487 PrintAndLogEx(SUCCESS, "Tamper message written successfully");
3488 } else {
3489 PrintAndLogEx(WARNING, "command execution time out");
3493 if (enable || disable || lock_msg) {
3495 if (ul_select(&card) == false) {
3496 PrintAndLogEx(ERR, "Unable to select tag");
3497 DropField();
3498 return MFU_TT_UL_ERROR;
3501 uint8_t cfg_page[4] = {0x00};
3502 uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, tt_cfg_page};
3503 int status = ul_send_cmd_raw(cmd, sizeof(cmd), cfg_page, 4);
3504 DropField();
3506 if (status <= 0) {
3507 PrintAndLogEx(WARNING, "Problem reading current config from tag");
3508 DropField();
3509 return PM3_ESOFT;
3512 if (enable) {
3513 cfg_page[1] = cfg_page[1] | 0x02;
3514 PrintAndLogEx(INFO, "Enabling tamper feature");
3516 if (disable) {
3517 cfg_page[1] = cfg_page[1] & 0xFD;
3518 PrintAndLogEx(INFO, "Disabling tamper feature");
3520 if (lock_msg) {
3521 cfg_page[1] = cfg_page[1] | 0x04;
3522 PrintAndLogEx(INFO, "Locking tamper message");
3525 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, tt_cfg_page, 0, 0, cfg_page, 4);
3526 PacketResponseNG resp;
3528 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
3529 uint8_t isOK = resp.oldarg[0] & 0xff;
3530 if (!isOK)
3531 PrintAndLogEx(WARNING, "Failed to write tamper configuration");
3532 else
3533 PrintAndLogEx(SUCCESS, "Tamper configuration written successfully");
3534 } else {
3535 PrintAndLogEx(WARNING, "command execution time out");
3539 DropField();
3540 return PM3_SUCCESS;
3544 // Restore dump file onto tag
3546 static int CmdHF14AMfURestore(const char *Cmd) {
3547 CLIParserContext *ctx;
3548 CLIParserInit(&ctx, "hf mfu restore",
3549 "Restore MIFARE Ultralight/NTAG dump file (bin/eml/json) to tag.\n",
3550 "hf mfu restore -f myfile -s -> special write\n"
3551 "hf mfu restore -f myfile -k AABBCCDD -s -> special write, use key\n"
3552 "hf mfu restore -f myfile -k AABBCCDD -ser -> special write, use key, write dump pwd, ..."
3555 void *argtable[] = {
3556 arg_param_begin,
3557 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
3558 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
3559 arg_lit0("l", NULL, "swap entered key's endianness"),
3560 arg_lit0("s", NULL, "enable special write UID -MAGIC TAG ONLY-"),
3561 arg_lit0("e", NULL, "enable special write version/signature -MAGIC NTAG 21* ONLY-"),
3562 arg_lit0("r", NULL, "use password found in dumpfile to configure tag. Requires " _YELLOW_("'-e'") " parameter to work"),
3563 arg_lit0("v", "verbose", "verbose output"),
3564 arg_lit0("z", "dense", "dense dump output style"),
3565 arg_param_end
3567 CLIExecWithReturn(ctx, Cmd, argtable, false);
3569 int fnlen = 0;
3570 char filename[FILE_PATH_SIZE] = {0};
3571 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
3573 int ak_len = 0;
3574 uint8_t authkey[16] = {0x00};
3575 uint8_t *p_authkey = authkey;
3576 CLIGetHexWithReturn(ctx, 2, authkey, &ak_len);
3578 bool swap_endian = arg_get_lit(ctx, 3);
3579 bool write_special = arg_get_lit(ctx, 4);
3580 bool write_extra = arg_get_lit(ctx, 5);
3581 bool read_key = arg_get_lit(ctx, 6);
3582 bool verbose = arg_get_lit(ctx, 7);
3583 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 8));
3584 CLIParserFree(ctx);
3586 bool has_key = false;
3587 if (ak_len > 0) {
3588 if (ak_len != 4 && ak_len != 16) {
3589 PrintAndLogEx(ERR, "Wrong key length. expected 4 or 16, got %d", ak_len);
3590 return PM3_EINVARG;
3591 } else {
3592 has_key = true;
3596 if (fnlen == 0) {
3597 char *fptr = mfu_generate_filename("hf-mfu-", "-dump.bin");
3598 if (fptr != NULL) {
3599 strncpy(filename, fptr, sizeof(filename) - 1);
3600 } else {
3601 snprintf(filename, sizeof(filename), "dumpdata.bin");
3603 free(fptr);
3606 // read dump file
3607 uint8_t *dump = NULL;
3608 size_t bytes_read = 0;
3609 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (MFU_MAX_BYTES + MFU_DUMP_PREFIX_LENGTH));
3610 if (res != PM3_SUCCESS) {
3611 return res;
3614 if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
3615 PrintAndLogEx(ERR, "Error, dump file is too small");
3616 free(dump);
3617 return PM3_ESOFT;
3620 res = convert_mfu_dump_format(&dump, &bytes_read, verbose);
3621 if (res != PM3_SUCCESS) {
3622 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
3623 free(dump);
3624 return res;
3627 mfu_dump_t *mem = (mfu_dump_t *)dump;
3628 uint8_t pages = (bytes_read - MFU_DUMP_PREFIX_LENGTH) / MFU_BLOCK_SIZE;
3630 if (pages - 1 != mem->pages) {
3631 PrintAndLogEx(ERR, "Error, invalid dump, wrong page count");
3632 PrintAndLogEx(INFO, " %u vs mempg %u", pages - 1, mem->pages);
3633 free(dump);
3634 return PM3_ESOFT;
3637 PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", filename);
3639 mfu_print_dump(mem, pages, 0, dense_output);
3641 // Swap endianness
3642 if (swap_endian && has_key) {
3643 if (ak_len == 16)
3644 p_authkey = SwapEndian64(authkey, ak_len, 8);
3645 else
3646 p_authkey = SwapEndian64(authkey, ak_len, 4);
3649 uint8_t data[20] = {0};
3650 uint8_t keytype = 0;
3651 // set key - only once
3652 if (has_key) {
3653 keytype = (ak_len == 16) ? 1 : 2;
3654 memcpy(data + 4, p_authkey, ak_len);
3657 // write version, signature, pack
3658 // only magic NTAG cards
3659 if (write_extra) {
3661 #define MFU_NTAG_SPECIAL_PWD 0xF0
3662 #define MFU_NTAG_SPECIAL_PACK 0xF1
3663 #define MFU_NTAG_SPECIAL_VERSION 0xFA
3664 #define MFU_NTAG_SPECIAL_SIGNATURE 0xF2
3665 // pwd
3666 if (has_key || read_key) {
3668 memcpy(data, p_authkey, 4);
3669 if (read_key) {
3670 // try reading key from dump and use.
3671 memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 8), 4);
3674 PrintAndLogEx(INFO, "special PWD block written 0x%X - %s", MFU_NTAG_SPECIAL_PWD, sprint_hex(data, 4));
3675 clearCommandBuffer();
3676 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data));
3678 wait4response(MFU_NTAG_SPECIAL_PWD);
3680 // copy the new key
3681 keytype = 2;
3682 memcpy(authkey, data, 4);
3683 memcpy(data + 4, authkey, 4);
3686 // pack
3687 memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2);
3688 data[2] = 0;
3689 data[3] = 0;
3690 PrintAndLogEx(INFO, "special PACK block written 0x%X - %s", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4));
3691 clearCommandBuffer();
3692 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data));
3693 wait4response(MFU_NTAG_SPECIAL_PACK);
3695 // Signature
3696 for (uint8_t s = MFU_NTAG_SPECIAL_SIGNATURE, i = 0; s < MFU_NTAG_SPECIAL_SIGNATURE + 8; s++, i += 4) {
3697 memcpy(data, mem->signature + i, 4);
3698 PrintAndLogEx(INFO, "special SIG block written 0x%X - %s", s, sprint_hex(data, 4));
3699 clearCommandBuffer();
3700 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data));
3701 wait4response(s);
3704 // Version
3705 for (uint8_t s = MFU_NTAG_SPECIAL_VERSION, i = 0; s < MFU_NTAG_SPECIAL_VERSION + 2; s++, i += 4) {
3706 memcpy(data, mem->version + i, 4);
3707 PrintAndLogEx(INFO, "special VERSION block written 0x%X - %s", s, sprint_hex(data, 4));
3708 clearCommandBuffer();
3709 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data));
3710 wait4response(s);
3714 PrintAndLogEx(INFO, "Restoring data blocks.");
3715 PrintAndLogEx(INFO, "." NOLF);
3716 // write all other data
3717 // Skip block 0,1,2,3 (only magic tags can write to them)
3718 // Skip last 5 blocks usually is configuration
3719 for (uint8_t b = 4; b < pages - 5; b++) {
3721 //Send write Block
3722 memcpy(data, mem->data + (b * 4), 4);
3723 clearCommandBuffer();
3724 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
3725 wait4response(b);
3726 PrintAndLogEx(NORMAL, "." NOLF);
3727 fflush(stdout);
3729 PrintAndLogEx(NORMAL, "");
3731 // write special data last
3732 if (write_special) {
3734 PrintAndLogEx(INFO, "Restoring configuration blocks");
3736 PrintAndLogEx(INFO, "Authentication with keytype[%x] %s\n", (uint8_t)(keytype & 0xff), sprint_hex(p_authkey, 4));
3738 #if defined ICOPYX
3739 // otp, uid, lock, dynlockbits, cfg0, cfg1, pwd, pack
3740 uint8_t blocks[] = {3, 0, 1, 2, pages - 5, pages - 4, pages - 3, pages - 2, pages - 1};
3741 #else
3742 // otp, uid, lock, dynlockbits, cfg0, cfg1
3743 uint8_t blocks[] = {3, 0, 1, 2, pages - 5, pages - 4, pages - 3};
3744 #endif
3745 for (uint8_t i = 0; i < ARRAYLEN(blocks); i++) {
3746 uint8_t b = blocks[i];
3747 memcpy(data, mem->data + (b * 4), 4);
3748 clearCommandBuffer();
3749 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
3750 wait4response(b);
3751 PrintAndLogEx(INFO, "special block written " _YELLOW_("%u") " - %s", b, sprint_hex(data, 4));
3755 DropField();
3756 free(dump);
3757 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mfu dump --ns") "` to verify");
3758 PrintAndLogEx(INFO, "Done!");
3759 return PM3_SUCCESS;
3762 // Load emulator with dump file
3764 static int CmdHF14AMfUeLoad(const char *Cmd) {
3766 CLIParserContext *ctx;
3767 CLIParserInit(&ctx, "hf mfu eload",
3768 "Load emulator memory with data from (bin/eml/json) dump file\n",
3769 "hf mfu eload -f hf-mfu-04010203040506.bin\n"
3770 "hf mfu eload -f hf-mfu-04010203040506.bin -q 57 -> load 57 blocks from myfile"
3773 void *argtable[] = {
3774 arg_param_begin,
3775 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
3776 arg_int0("q", "qty", "<dec>", "Number of blocks to load from eml file"),
3777 arg_lit0("v", "verbose", "verbose output"),
3778 arg_param_end
3780 CLIExecWithReturn(ctx, Cmd, argtable, false);
3781 CLIParserFree(ctx);
3783 size_t nc_len = strlen(Cmd) + 6;
3784 char *nc = calloc(nc_len, 1);
3785 if (nc == NULL) {
3786 return CmdHF14AMfELoad(Cmd);
3789 snprintf(nc, nc_len, "%s --ul", Cmd);
3790 int res = CmdHF14AMfELoad(nc);
3791 free(nc);
3793 PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfu sim -t 7`") " to simulate an Amiibo.");
3794 PrintAndLogEx(INFO, "Done!");
3795 return res;
3799 // Simulate tag
3801 static int CmdHF14AMfUSim(const char *Cmd) {
3802 CLIParserContext *ctx;
3803 CLIParserInit(&ctx, "hf mfu sim",
3804 "Simulate MIFARE Ultralight family type based upon\n"
3805 "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
3806 "from emulator memory. See `hf mfu eload` first. \n"
3807 "The UID from emulator memory will be used if not specified.\n"
3808 "See `hf 14a sim -h` to see available types. You want 2 or 7 usually.",
3809 "hf mfu sim -t 2 --uid 11223344556677 -> MIFARE Ultralight\n"
3810 "hf mfu sim -t 7 --uid 11223344556677 -n 5 -> MFU EV1 / NTAG 215 Amiibo\n"
3811 "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo"
3814 void *argtable[] = {
3815 arg_param_begin,
3816 arg_int1("t", "type", "<1..12> ", "Simulation type to use"),
3817 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
3818 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks. 0 = infinite"),
3819 arg_lit0("v", "verbose", "Verbose output"),
3820 arg_param_end
3822 CLIExecWithReturn(ctx, Cmd, argtable, false);
3823 CLIParserFree(ctx);
3824 return CmdHF14ASim(Cmd);
3827 //-------------------------------------------------------------------------------
3828 // Ultralight C Methods
3829 //-------------------------------------------------------------------------------
3831 // Ultralight C Authentication
3833 static int CmdHF14AMfUCAuth(const char *Cmd) {
3834 CLIParserContext *ctx;
3835 CLIParserInit(&ctx, "hf mfu cauth",
3836 "Tests 3DES password on Mifare Ultralight-C tag.\n"
3837 "If password is not specified, a set of known defaults will be tested.",
3838 "hf mfu cauth\n"
3839 "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f"
3842 void *argtable[] = {
3843 arg_param_begin,
3844 arg_str0(NULL, "key", "<hex>", "Authentication key (UL-C 16 hex bytes)"),
3845 arg_lit0("l", NULL, "Swap entered key's endianness"),
3846 arg_lit0("k", NULL, "Keep field on (only if a password is provided)"),
3847 arg_param_end
3849 CLIExecWithReturn(ctx, Cmd, argtable, true);
3851 int ak_len = 0;
3852 uint8_t authenticationkey[16] = {0x00};
3853 uint8_t *authKeyPtr = authenticationkey;
3854 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
3855 bool swap_endian = arg_get_lit(ctx, 2);
3856 bool keep_field_on = arg_get_lit(ctx, 3);
3857 CLIParserFree(ctx);
3859 if (ak_len != 16 && ak_len != 0) {
3860 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length");
3861 return PM3_EINVARG;
3864 // Swap endianness
3865 if (swap_endian && ak_len) {
3866 authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
3869 int isok;
3871 // If no hex key is specified, try default keys
3872 if (ak_len == 0) {
3873 isok = try_default_3des_keys(false, &authKeyPtr);
3874 } else {
3875 // try user-supplied
3876 isok = ulc_authentication(authKeyPtr, !keep_field_on);
3879 if (isok == PM3_SUCCESS) {
3880 PrintAndLogEx(SUCCESS, "Authentication 3DES key... " _GREEN_("%s") " ( " _GREEN_("ok")" )", sprint_hex_inrow(authKeyPtr, 16));
3881 } else {
3882 PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " )");
3884 return PM3_SUCCESS;
3888 A test function to validate that the polarssl-function works the same
3889 was as the openssl-implementation.
3890 Commented out, since it requires openssl
3892 static int CmdTestDES(const char * cmd)
3894 uint8_t key[16] = {0x00};
3896 memcpy(key,key3_3des_data,16);
3897 DES_cblock RndA, RndB;
3899 PrintAndLogEx(NORMAL, "----------OpenSSL DES implementation----------");
3901 uint8_t e_RndB[8] = {0x00};
3902 unsigned char RndARndB[16] = {0x00};
3904 DES_cblock iv = { 0 };
3905 DES_key_schedule ks1,ks2;
3906 DES_cblock key1,key2;
3908 memcpy(key,key3_3des_data,16);
3909 memcpy(key1,key,8);
3910 memcpy(key2,key+8,8);
3913 DES_set_key((DES_cblock *)key1,&ks1);
3914 DES_set_key((DES_cblock *)key2,&ks2);
3916 DES_random_key(&RndA);
3917 PrintAndLogEx(NORMAL, " RndA:%s",sprint_hex(RndA, 8));
3918 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(e_RndB, 8));
3919 //void DES_ede2_cbc_encrypt(const unsigned char *input,
3920 // unsigned char *output, long length, DES_key_schedule *ks1,
3921 // DES_key_schedule *ks2, DES_cblock *ivec, int enc);
3922 DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
3924 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(RndB, 8));
3925 rol(RndB,8);
3926 memcpy(RndARndB,RndA,8);
3927 memcpy(RndARndB+8,RndB,8);
3928 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(RndARndB, 16));
3929 DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
3930 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(RndARndB, 16));
3933 PrintAndLogEx(NORMAL, "----------PolarSSL implementation----------");
3935 uint8_t random_a[8] = { 0 };
3936 uint8_t enc_random_a[8] = { 0 };
3937 uint8_t random_b[8] = { 0 };
3938 uint8_t enc_random_b[8] = { 0 };
3939 uint8_t random_a_and_b[16] = { 0 };
3940 des3_context ctx = { 0 };
3942 memcpy(random_a, RndA,8);
3944 uint8_t output[8] = { 0 };
3945 uint8_t iv[8] = { 0 };
3947 PrintAndLogEx(NORMAL, " RndA :%s",sprint_hex(random_a, 8));
3948 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(enc_random_b, 8));
3950 des3_set2key_dec(&ctx, key);
3952 des3_crypt_cbc(&ctx // des3_context *ctx
3953 , DES_DECRYPT // int mode
3954 , sizeof(random_b) // size_t length
3955 , iv // unsigned char iv[8]
3956 , enc_random_b // const unsigned char *input
3957 , random_b // unsigned char *output
3960 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(random_b, 8));
3962 rol(random_b,8);
3963 memcpy(random_a_and_b ,random_a,8);
3964 memcpy(random_a_and_b+8,random_b,8);
3966 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(random_a_and_b, 16));
3968 des3_set2key_enc(&ctx, key);
3970 des3_crypt_cbc(&ctx // des3_context *ctx
3971 , DES_ENCRYPT // int mode
3972 , sizeof(random_a_and_b) // size_t length
3973 , enc_random_b // unsigned char iv[8]
3974 , random_a_and_b // const unsigned char *input
3975 , random_a_and_b // unsigned char *output
3978 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
3980 return 0;
3985 // Mifare Ultralight C - Set password
3987 static int CmdHF14AMfUCSetPwd(const char *Cmd) {
3988 CLIParserContext *ctx;
3989 CLIParserInit(&ctx, "hf mfu setpwd",
3990 "Set the 3DES key on MIFARE Ultralight-C tag. ",
3991 "hf mfu setpwd --key 000102030405060708090a0b0c0d0e0f"
3994 void *argtable[] = {
3995 arg_param_begin,
3996 arg_str0("k", "key", "<hex>", "New key (16 hex bytes)"),
3997 arg_param_end
3999 CLIExecWithReturn(ctx, Cmd, argtable, true);
4001 int k_len = 0;
4002 uint8_t key[16] = {0x00};
4003 CLIGetHexWithReturn(ctx, 1, key, &k_len);
4004 CLIParserFree(ctx);
4006 if (k_len != 16) {
4007 PrintAndLogEx(WARNING, "Key must be 16 hex bytes");
4008 return PM3_EINVARG;
4011 clearCommandBuffer();
4012 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, key, sizeof(key));
4014 PacketResponseNG resp;
4015 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4016 if ((resp.oldarg[0] & 0xff) == 1) {
4017 PrintAndLogEx(INFO, "Ultralight-C new key... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key)));
4018 } else {
4019 PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
4020 return PM3_ESOFT;
4022 } else {
4023 PrintAndLogEx(WARNING, "command execution time out");
4024 return PM3_ETIMEOUT;
4026 return PM3_SUCCESS;
4030 // Magic UL / UL-C tags - Set UID
4032 static int CmdHF14AMfUCSetUid(const char *Cmd) {
4034 CLIParserContext *ctx;
4035 CLIParserInit(&ctx, "hf mfu setuid",
4036 "Set UID on MIFARE Ultralight tag.\n"
4037 "This only works for `magic Ultralight` tags.",
4038 "hf mfu setuid --uid 11223344556677"
4041 void *argtable[] = {
4042 arg_param_begin,
4043 arg_str0("u", "uid", "<hex>", "New UID (7 hex bytes)"),
4044 arg_param_end
4046 CLIExecWithReturn(ctx, Cmd, argtable, true);
4048 int u_len = 0;
4049 uint8_t uid[7] = {0x00};
4050 CLIGetHexWithReturn(ctx, 1, uid, &u_len);
4051 CLIParserFree(ctx);
4053 if (u_len != 7) {
4054 PrintAndLogEx(WARNING, "UID must be 7 hex bytes");
4055 return PM3_EINVARG;
4058 PrintAndLogEx(INFO, "Please ignore possible transient BCC warnings");
4060 // read block2.
4061 PacketResponseNG resp;
4062 clearCommandBuffer();
4063 SendCommandMIX(CMD_HF_MIFAREU_READBL, 2, 0, 0, NULL, 0);
4064 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4065 PrintAndLogEx(WARNING, "command execution time out");
4066 return PM3_ETIMEOUT;
4069 // save old block2.
4070 uint8_t oldblock2[4] = {0x00};
4071 memcpy(oldblock2, resp.data.asBytes, 4);
4073 // Enforce bad BCC handling temporarily as BCC will be wrong between
4074 // block 1 write and block2 write
4075 hf14a_config config;
4076 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG, NULL, 0);
4077 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG, &resp, 2000)) {
4078 PrintAndLogEx(WARNING, "command execution time out");
4079 return PM3_ETIMEOUT;
4081 memcpy(&config, resp.data.asBytes, sizeof(hf14a_config));
4082 int8_t oldconfig_bcc = config.forcebcc;
4083 if (oldconfig_bcc != 2) {
4084 config.forcebcc = 2;
4085 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)&config, sizeof(hf14a_config));
4088 // block 0.
4089 uint8_t data[4];
4090 data[0] = uid[0];
4091 data[1] = uid[1];
4092 data[2] = uid[2];
4093 data[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2];
4094 clearCommandBuffer();
4095 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 0, 0, 0, data, sizeof(data));
4096 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4097 PrintAndLogEx(WARNING, "command execution time out");
4098 return PM3_ETIMEOUT;
4101 // block 1.
4102 data[0] = uid[3];
4103 data[1] = uid[4];
4104 data[2] = uid[5];
4105 data[3] = uid[6];
4106 clearCommandBuffer();
4107 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 1, 0, 0, data, sizeof(data));
4108 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4109 PrintAndLogEx(WARNING, "command execution time out");
4110 return PM3_ETIMEOUT;
4113 // block 2.
4114 data[0] = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
4115 data[1] = oldblock2[1];
4116 data[2] = oldblock2[2];
4117 data[3] = oldblock2[3];
4118 clearCommandBuffer();
4119 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 2, 0, 0, data, sizeof(data));
4120 if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4121 PrintAndLogEx(WARNING, "command execution time out");
4122 return PM3_ETIMEOUT;
4125 // restore BCC config
4126 if (oldconfig_bcc != 2) {
4127 config.forcebcc = oldconfig_bcc;
4128 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)&config, sizeof(hf14a_config));
4130 return PM3_SUCCESS;
4133 static int CmdHF14AMfUKeyGen(const char *Cmd) {
4134 CLIParserContext *ctx;
4135 CLIParserInit(&ctx, "hf mfu keygen",
4136 "Calculate MFC keys based ",
4137 "hf mfu keygen -r\n"
4138 "hf mfu keygen --uid 11223344556677"
4141 void *argtable[] = {
4142 arg_param_begin,
4143 arg_str0("u", "uid", "<hex>", "<4|7> hex byte UID"),
4144 arg_lit0("r", NULL, "Read UID from tag"),
4145 arg_u64_0("b", "blk", "<dec>", "Block number"),
4146 arg_param_end
4148 CLIExecWithReturn(ctx, Cmd, argtable, true);
4150 int ulen = 0;
4151 uint8_t uid[7];
4152 CLIGetHexWithReturn(ctx, 1, uid, &ulen);
4153 bool read_tag = arg_get_lit(ctx, 2);
4154 uint8_t block = arg_get_u64_def(ctx, 3, 1) & 0xFF;
4155 CLIParserFree(ctx);
4157 if (read_tag) {
4158 // read uid from tag
4159 clearCommandBuffer();
4160 SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0);
4161 PacketResponseNG resp;
4162 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
4163 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
4164 return PM3_ETIMEOUT;
4167 iso14a_card_select_t card;
4168 memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
4170 uint64_t select_status = resp.oldarg[0];
4171 // 0: couldn't read,
4172 // 1: OK, with ATS
4173 // 2: OK, no ATS
4174 // 3: proprietary Anticollision
4176 if (select_status == 0) {
4177 PrintAndLogEx(WARNING, "iso14443a card select failed");
4178 return PM3_ESOFT;
4181 if (card.uidlen != 4 && card.uidlen != 7) {
4182 PrintAndLogEx(WARNING, "Wrong sized UID, expected 4|7 bytes got %d", card.uidlen);
4183 return PM3_ESOFT;
4185 ulen = card.uidlen;
4186 memcpy(uid, card.uid, card.uidlen);
4187 } else {
4188 if (ulen != 4 && ulen != 7) {
4189 PrintAndLogEx(ERR, "Must supply 4 or 7 hex byte uid");
4190 return PM3_EINVARG;
4194 uint8_t iv[8] = { 0x00 };
4196 uint8_t mifarekeyA[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
4197 uint8_t mifarekeyB[] = { 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5 };
4198 uint8_t dkeyA[8] = { 0x00 };
4199 uint8_t dkeyB[8] = { 0x00 };
4201 uint8_t masterkey[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
4202 uint8_t mix[8] = { 0x00 };
4203 uint8_t divkey[8] = { 0x00 };
4205 memcpy(mix, mifarekeyA, 4);
4207 mix[4] = mifarekeyA[4] ^ uid[0];
4208 mix[5] = mifarekeyA[5] ^ uid[1];
4209 mix[6] = block ^ uid[2];
4210 mix[7] = uid[3];
4212 mbedtls_des3_context ctx_des3;
4213 mbedtls_des3_set2key_enc(&ctx_des3, masterkey);
4215 mbedtls_des3_crypt_cbc(&ctx_des3 // des3_context
4216 , MBEDTLS_DES_ENCRYPT // int mode
4217 , sizeof(mix) // length
4218 , iv // iv[8]
4219 , mix // input
4220 , divkey // output
4223 PrintAndLogEx(SUCCESS, "-- 3DES version");
4224 PrintAndLogEx(SUCCESS, "Masterkey......... %s", sprint_hex(masterkey, sizeof(masterkey)));
4225 PrintAndLogEx(SUCCESS, "UID............... %s", sprint_hex(uid, ulen));
4226 PrintAndLogEx(SUCCESS, "block............. %0d", block);
4227 PrintAndLogEx(SUCCESS, "Mifare key........ %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA)));
4228 PrintAndLogEx(SUCCESS, "Message........... %s", sprint_hex(mix, sizeof(mix)));
4229 PrintAndLogEx(SUCCESS, "Diversified key... %s", sprint_hex(divkey + 1, 6));
4231 for (int i = 0; i < ARRAYLEN(mifarekeyA); ++i) {
4232 dkeyA[i] = (mifarekeyA[i] << 1) & 0xff;
4233 dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i + 1);
4236 for (int i = 0; i < ARRAYLEN(mifarekeyB); ++i) {
4237 dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i + 1);
4238 dkeyB[2 + i] = (mifarekeyB[i] << 1) & 0xff;
4241 uint8_t zeros[8] = {0x00};
4242 uint8_t newpwd[8] = {0x00};
4243 uint8_t dmkey[24] = {0x00};
4244 memcpy(dmkey, dkeyA, 8);
4245 memcpy(dmkey + 8, dkeyB, 8);
4246 memcpy(dmkey + 16, dkeyA, 8);
4247 memset(iv, 0x00, 8);
4249 mbedtls_des3_set3key_enc(&ctx_des3, dmkey);
4251 mbedtls_des3_crypt_cbc(&ctx_des3 // des3_context
4252 , MBEDTLS_DES_ENCRYPT // int mode
4253 , sizeof(newpwd) // length
4254 , iv // iv[8]
4255 , zeros // input
4256 , newpwd // output
4259 PrintAndLogEx(SUCCESS, "\n-- DES version");
4260 PrintAndLogEx(SUCCESS, "MIFARE dkeyA...... %s", sprint_hex(dkeyA, sizeof(dkeyA)));
4261 PrintAndLogEx(SUCCESS, "MIFARE dkeyB...... %s", sprint_hex(dkeyB, sizeof(dkeyB)));
4262 PrintAndLogEx(SUCCESS, "MIFARE ABA........ %s", sprint_hex(dmkey, sizeof(dmkey)));
4263 PrintAndLogEx(SUCCESS, "MIFARE PWD........ %s", sprint_hex(newpwd, sizeof(newpwd)));
4265 mbedtls_des3_free(&ctx_des3);
4267 mbedtls_aes_context ctx_aes;
4268 uint8_t aes_iv[16] = { 0x00 };
4269 uint8_t aes_masterkey[] = { 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
4270 uint8_t aes_input[16] = {0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80, 0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80};
4271 uint8_t aes_output[16] = {0x00};
4272 mbedtls_aes_setkey_enc(&ctx_aes, aes_masterkey, 128);
4273 mbedtls_aes_crypt_cbc(&ctx_aes, MBEDTLS_AES_ENCRYPT, 16, aes_iv, aes_input, aes_output);
4274 mbedtls_aes_free(&ctx_aes);
4276 PrintAndLogEx(SUCCESS, "\n-- AES version");
4277 PrintAndLogEx(SUCCESS, "MIFARE AES mk..... %s", sprint_hex(aes_masterkey, sizeof(aes_masterkey)));
4278 PrintAndLogEx(SUCCESS, "MIFARE Div........ %s", sprint_hex(aes_output, sizeof(aes_output)));
4280 // next. from the diversify_key method.
4281 return PM3_SUCCESS;
4284 static int CmdHF14AMfUPwdGen(const char *Cmd) {
4285 CLIParserContext *ctx;
4286 CLIParserInit(&ctx, "hf mfu pwdgen",
4287 "Generate different passwords from known pwdgen algos",
4288 "hf mfu pwdgen -r\n"
4289 "hf mfu pwdgen --uid 11223344556677\n"
4290 "hf mfu pwdgen --test"
4293 void *argtable[] = {
4294 arg_param_begin,
4295 arg_str0("u", "uid", "<hex>", "UID (7 hex bytes)"),
4296 arg_lit0("r", NULL, "Read UID from tag"),
4297 arg_lit0(NULL, "test", "self test"),
4298 arg_param_end
4300 CLIExecWithReturn(ctx, Cmd, argtable, true);
4302 int u_len = 0;
4303 uint8_t uid[7] = {0x00};
4304 CLIGetHexWithReturn(ctx, 1, uid, &u_len);
4305 bool use_tag = arg_get_lit(ctx, 2);
4306 bool selftest = arg_get_lit(ctx, 3);
4307 CLIParserFree(ctx);
4309 if (selftest) {
4310 return generator_selftest();
4313 uint8_t philips_mfg[10] = {0};
4315 if (use_tag) {
4316 // read uid from tag
4317 int res = ul_read_uid(uid);
4318 if (res == PM3_ELENGTH) {
4319 // got 4 byte UID, lets adapt to 7 bytes :)
4320 memset(uid + 4, 0x00, 3);
4321 u_len = 7;
4322 } else {
4324 if (res != PM3_SUCCESS) {
4325 return res;
4328 iso14a_card_select_t card;
4329 if (ul_select(&card)) {
4330 // Philips toothbrush needs page 0x21-0x23
4331 uint8_t data[16] = {0x00};
4332 int status = ul_read(0x21, data, sizeof(data));
4333 if (status <= 0) {
4334 PrintAndLogEx(DEBUG, "Error: tag didn't answer to READ");
4335 } else if (status == 16) {
4336 memcpy(philips_mfg, data + 2, sizeof(philips_mfg));
4338 DropField();
4341 } else {
4342 if (u_len != 7 && u_len != 4) {
4343 PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
4344 return PM3_EINVARG;
4345 } else if (u_len == 4) {
4346 // adapt to 7 bytes :)
4347 memset(uid + 4, 0x00, 3);
4348 u_len = 7;
4352 PrintAndLogEx(INFO, "-----------------------------------");
4353 PrintAndLogEx(INFO, " UID 4b... " _YELLOW_("%s"), sprint_hex(uid, 4));
4354 PrintAndLogEx(INFO, " UID 7b... " _YELLOW_("%s"), sprint_hex(uid, 7));
4355 PrintAndLogEx(INFO, "-----------------------------------");
4356 PrintAndLogEx(INFO, " algo pwd pack");
4357 PrintAndLogEx(INFO, "-----------------------------+-----");
4358 PrintAndLogEx(INFO, " Transport EV1..... %08X | %04X", ul_ev1_pwdgenA(uid), ul_ev1_packgenA(uid));
4359 PrintAndLogEx(INFO, " Amiibo............ %08X | %04X", ul_ev1_pwdgenB(uid), ul_ev1_packgenB(uid));
4360 PrintAndLogEx(INFO, " Lego Dimension.... %08X | %04X", ul_ev1_pwdgenC(uid), ul_ev1_packgenC(uid));
4361 PrintAndLogEx(INFO, " XYZ 3D printer.... %08X | %04X", ul_ev1_pwdgenD(uid), ul_ev1_packgenD(uid));
4362 PrintAndLogEx(INFO, " Xiaomi purifier... %08X | %04X", ul_ev1_pwdgenE(uid), ul_ev1_packgenE(uid));
4363 PrintAndLogEx(INFO, " NTAG tools........ %08X | %04X", ul_ev1_pwdgenF(uid), ul_ev1_packgen_def(uid));
4364 if (philips_mfg[0] != 0) {
4365 PrintAndLogEx(INFO, " Philips Toothbrush | %08X | %04X", ul_ev1_pwdgenG(uid, philips_mfg), ul_ev1_packgenG(uid, philips_mfg));
4367 PrintAndLogEx(INFO, "-----------------------------+-----");
4368 PrintAndLogEx(INFO, _CYAN_("Vingcard"));
4369 uint64_t key = 0;
4370 mfc_algo_saflok_one(uid, 0, 0, &key);
4371 PrintAndLogEx(INFO, " Saflok algo | %012" PRIX64, key);
4372 PrintAndLogEx(INFO, " SALTO algo");
4373 PrintAndLogEx(INFO, " Dorma Kaba algo");
4374 PrintAndLogEx(INFO, " STiD algo");
4375 PrintAndLogEx(INFO, "-------------------------------------");
4376 key = 0;
4377 mfc_algo_bambu_one(uid, 0, MF_KEY_A, &key);
4378 PrintAndLogEx(INFO, " Bambu........ %012" PRIX64, key);
4379 return PM3_SUCCESS;
4383 // MFU TearOff against OTP
4384 // Moebius et al
4386 static int CmdHF14AMfuOtpTearoff(const char *Cmd) {
4387 CLIParserContext *ctx;
4388 CLIParserInit(&ctx, "hf mfu otptear",
4389 "Tear-off test against OTP block",
4390 "hf mfu otptear -b 3\n"
4391 "hf mfu otptear -b 3 -i 100 -s 1000\n"
4392 "hf mfu otptear -b 3 -i 1 -e 200\n"
4393 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE\n"
4394 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quit when OTP is reset"
4397 void *argtable[] = {
4398 arg_param_begin,
4399 arg_u64_0("b", "blk", "<dec>", "target block (def 8)"),
4400 arg_u64_0("i", "inc", "<dec>", "increase time steps (def 500 us)"),
4401 arg_u64_0("e", "end", "<dec>", "end time (def 3000 us)"),
4402 arg_u64_0("s", "start", "<dec>", "start time (def 0 us)"),
4403 arg_str0("d", "data", "<hex>", "initialise data before run (4 bytes)"),
4404 arg_str0("t", "test", "<hex>", "test write data (4 bytes, 00000000 by default)"),
4405 arg_str0("m", "match", "<hex>", "exit criteria, if block matches this value (4 bytes)"),
4406 arg_param_end
4408 CLIExecWithReturn(ctx, Cmd, argtable, true);
4410 uint8_t blockno = arg_get_u32_def(ctx, 1, 8);
4411 uint32_t steps = arg_get_u32_def(ctx, 2, 500);
4412 uint32_t end = arg_get_u32_def(ctx, 3, 3000);
4413 uint32_t start = arg_get_u32_def(ctx, 4, 0);
4415 int d_len = 0;
4416 uint8_t data[4] = {0x00};
4417 CLIGetHexWithReturn(ctx, 5, data, &d_len);
4418 bool use_data = (d_len > 0);
4420 int t_len = 0;
4421 uint8_t test[4] = {0x00};
4422 CLIGetHexWithReturn(ctx, 6, test, &t_len);
4424 int m_len = 0;
4425 uint8_t match[4] = {0x00};
4426 CLIGetHexWithReturn(ctx, 7, match, &m_len);
4427 bool use_match = (m_len > 0);
4428 CLIParserFree(ctx);
4430 if (blockno < 2) {
4431 PrintAndLogEx(WARNING, "Block number must be larger than 2.");
4432 return PM3_EINVARG;
4434 if (end < steps) {
4435 PrintAndLogEx(WARNING, "end time smaller than increase value");
4436 return PM3_EINVARG;
4438 if (end > 43000) {
4439 PrintAndLogEx(WARNING, "end time - out of 1 .. 43000 range");
4440 return PM3_EINVARG;
4442 if (start > (end - steps)) {
4443 PrintAndLogEx(WARNING, "Start time larger than (end time + steps)");
4444 return PM3_EINVARG;
4447 if (d_len && d_len != 4) {
4448 PrintAndLogEx(WARNING, "data must be 4 hex bytes");
4449 return PM3_EINVARG;
4452 if (t_len && t_len != 4) {
4453 PrintAndLogEx(WARNING, "test data must be 4 hex bytes");
4454 return PM3_EINVARG;
4457 if (m_len && m_len != 4) {
4458 PrintAndLogEx(WARNING, "match data must be 4 hex bytes");
4459 return PM3_EINVARG;
4462 uint8_t teardata[4] = {0x00};
4463 memcpy(teardata, test, sizeof(test));
4465 PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Tear off") " ---------------------");
4466 PrintAndLogEx(INFO, "Starting Tear-off test");
4467 PrintAndLogEx(INFO, "Target block no: %u", blockno);
4468 if (use_data) {
4469 PrintAndLogEx(INFO, "Target initial block data : %s", sprint_hex_inrow(data, 4));
4471 PrintAndLogEx(INFO, "Target write block data : %s", sprint_hex_inrow(teardata, 4));
4472 if (use_match) {
4473 PrintAndLogEx(INFO, "Target match block data : %s", sprint_hex_inrow(match, 4));
4475 PrintAndLogEx(INFO, "----------------------------------------------------");
4476 uint8_t isOK;
4477 bool lock_on = false;
4478 uint8_t pre[4] = {0};
4479 uint8_t post[4] = {0};
4480 uint32_t current = start;
4481 int phase_begin_clear = -1;
4482 int phase_end_clear = -1;
4483 int phase_begin_newwr = -1;
4484 int phase_end_newwr = -1;
4485 bool skip_phase1 = false;
4486 uint8_t retries = 0;
4487 uint8_t error_retries = 0;
4489 while ((current <= (end - steps)) && (error_retries < 10)) {
4491 if (kbd_enter_pressed()) {
4492 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
4493 break;
4496 PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", current);
4498 clearCommandBuffer();
4499 PacketResponseNG resp;
4501 if (use_data) {
4502 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, blockno, 0, 0, data, d_len);
4503 bool got_written = false;
4504 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4505 isOK = resp.oldarg[0] & 0xff;
4506 if (isOK) {
4507 got_written = true;
4510 if (! got_written) {
4511 PrintAndLogEx(FAILED, "Failed to write block BEFORE");
4512 error_retries++;
4513 continue; // try again
4517 SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0);
4519 bool got_pre = false;
4520 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4521 isOK = resp.oldarg[0] & 0xFF;
4522 if (isOK) {
4523 memcpy(pre, resp.data.asBytes, sizeof(pre));
4524 got_pre = true;
4527 if (! got_pre) {
4528 PrintAndLogEx(FAILED, "Failed to read block BEFORE");
4529 error_retries++;
4530 continue; // try again
4532 clearCommandBuffer();
4533 SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF, blockno, current, 0, teardata, sizeof(teardata));
4535 // we be getting ACK that we are silently ignoring here..
4537 if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF, &resp, 2000)) {
4538 PrintAndLogEx(WARNING, "Failed");
4539 return PM3_ESOFT;
4542 if (resp.status != PM3_SUCCESS) {
4543 PrintAndLogEx(WARNING, "Tear off reporting failure to select tag");
4544 error_retries++;
4545 continue;
4548 bool got_post = false;
4549 clearCommandBuffer();
4550 SendCommandMIX(CMD_HF_MIFAREU_READBL, blockno, 0, 0, NULL, 0);
4551 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
4552 isOK = resp.oldarg[0] & 0xFF;
4553 if (isOK) {
4554 memcpy(post, resp.data.asBytes, sizeof(post));
4555 got_post = true;
4558 if (! got_post) {
4559 PrintAndLogEx(FAILED, "Failed to read block BEFORE");
4560 error_retries++;
4561 continue; // try again
4563 error_retries = 0;
4564 char prestr[20] = {0};
4565 snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
4566 char poststr[20] = {0};
4567 snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
4569 if (memcmp(pre, post, sizeof(pre)) == 0) {
4571 PrintAndLogEx(INFO, "Current : %02d (0x%02X) %s"
4572 , blockno
4573 , blockno
4574 , poststr
4576 } else {
4577 PrintAndLogEx(INFO, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s")
4578 , blockno
4579 , blockno
4580 , prestr
4581 , poststr
4584 lock_on = true;
4586 uint32_t post32 = bytes_to_num(post, 4);
4587 uint32_t pre32 = bytes_to_num(pre, 4);
4589 if ((phase_begin_clear == -1) && (bitcount32(pre32) > bitcount32(post32)))
4590 phase_begin_clear = current;
4592 if ((phase_begin_clear > -1) && (phase_end_clear == -1) && (bitcount32(post32) == 0))
4593 phase_end_clear = current;
4595 if ((current == start) && (phase_end_clear > -1))
4596 skip_phase1 = true;
4597 // new write phase must be atleast 100us later..
4598 if (((bitcount32(pre32) == 0) || (phase_end_clear > -1)) && (phase_begin_newwr == -1) && (bitcount32(post32) != 0) && (skip_phase1 || (current > (phase_end_clear + 100))))
4599 phase_begin_newwr = current;
4601 if ((phase_begin_newwr > -1) && (phase_end_newwr == -1) && (memcmp(post, teardata, sizeof(teardata)) == 0))
4602 phase_end_newwr = current;
4605 if (use_match && memcmp(post, match, sizeof(post)) == 0) {
4606 PrintAndLogEx(SUCCESS, "Block matches stop condition!\n");
4607 break;
4610 /* TEMPORALLY DISABLED
4611 uint8_t d0, d1, d2, d3;
4612 d0 = *resp.data.asBytes;
4613 d1 = *(resp.data.asBytes + 1);
4614 d2 = *(resp.data.asBytes + 2);
4615 d3 = *(resp.data.asBytes + 3);
4616 if ((d0 != 0xFF) || (d1 != 0xFF) || (d2 != 0xFF) || (d3 = ! 0xFF)) {
4617 PrintAndLogEx(NORMAL, "---------------------------------");
4618 PrintAndLogEx(NORMAL, " EFFECT AT: %d us", actualTime);
4619 PrintAndLogEx(NORMAL, "---------------------------------\n");
4622 if (start != end) {
4623 current += steps;
4624 } else {
4625 if (lock_on == false) {
4626 if (++retries == 20) {
4627 current++;
4628 end++;
4629 start++;
4630 retries = 0;
4631 PrintAndLogEx(INFO, _CYAN_("Retried %u times, increased delay with 1us"), retries);
4637 PrintAndLogEx(INFO, "----------------------------------------------------");
4638 if ((phase_begin_clear > - 1) && (phase_begin_clear != start)) {
4639 PrintAndLogEx(INFO, "Erase phase start boundary around " _YELLOW_("%5d") " us", phase_begin_clear);
4641 if ((phase_end_clear > - 1) && (phase_end_clear != start)) {
4642 PrintAndLogEx(INFO, "Erase phase end boundary around " _YELLOW_("%5d") " us", phase_end_clear);
4644 if (phase_begin_newwr > - 1) {
4645 PrintAndLogEx(INFO, "Write phase start boundary around " _YELLOW_("%5d") " us", phase_begin_newwr);
4647 if (phase_end_newwr > - 1) {
4648 PrintAndLogEx(INFO, "Write phase end boundary around " _YELLOW_("%5d") " us", phase_end_newwr);
4650 PrintAndLogEx(NORMAL, "");
4651 return PM3_SUCCESS;
4655 static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
4657 PrintAndLogEx(INFO, "Reset tear check");
4659 uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00};
4660 uint8_t ct[1] = {0};
4661 uint8_t resp[10] = {0};
4663 if (ul_select(card) == false) {
4664 PrintAndLogEx(FAILED, "failed to select card, exiting...");
4665 return PM3_ESOFT;
4667 if (ul_send_cmd_raw(cw, sizeof(cw), resp, sizeof(resp)) < 0) {
4668 PrintAndLogEx(FAILED, "failed to write all ZEROS");
4669 return PM3_ESOFT;
4671 if (ulev1_readTearing(cnt_no, ct, sizeof(ct)) < 0) {
4672 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
4673 return PM3_ESOFT;
4675 DropField();
4677 if (ct[0] != 0xBD) {
4678 PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
4679 return PM3_ESOFT;
4681 return PM3_SUCCESS;
4686 static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
4688 CLIParserContext *ctx;
4689 CLIParserInit(&ctx, "hf mfu countertear",
4690 "Tear-off test against a Ev1 counter",
4691 "hf mfu countertear\n"
4692 "hf mfu countertear -s 200 -l 2500 -> target counter 0, start delay 200\n"
4693 "hf mfu countertear -i 2 -s 200 -l 400 -> target counter 0, start delay 200\n"
4696 void *argtable[] = {
4697 arg_param_begin,
4698 arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
4699 arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
4700 arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
4701 arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
4702 arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"),
4703 arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"),
4704 arg_param_end
4706 CLIExecWithReturn(ctx, Cmd, argtable, false);
4708 int interval = 0;
4709 int time_limit, start_time = 0;
4710 int counter = arg_get_int_def(ctx, 1, 0);
4711 int fixed = arg_get_int_def(ctx, 5, -1);
4713 if ( fixed == -1 ) {
4714 interval = arg_get_int_def(ctx, 2, 10);
4715 time_limit = arg_get_int_def(ctx, 3, 3000);
4716 start_time = arg_get_int_def(ctx, 4, 0);
4717 } else {
4718 start_time = fixed;
4719 interval = 0;
4720 time_limit = fixed;
4723 uint8_t newvalue[5] = {0};
4724 int newvaluelen = 0;
4725 CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
4726 CLIParserFree(ctx);
4728 // Validations
4729 if (start_time > (time_limit - interval)) {
4730 PrintAndLogEx(WARNING, "Wrong start time number");
4731 return PM3_EINVARG;
4733 if (time_limit < interval) {
4734 PrintAndLogEx(WARNING, "Wrong time limit number");
4735 return PM3_EINVARG;
4737 if (time_limit > 43000) {
4738 PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
4739 return PM3_EINVARG;
4741 uint8_t cnt_no = 0;
4742 if (counter < 0 || counter > 2) {
4743 PrintAndLogEx(WARNING, "Counter must 0, 1 or 2");
4744 return PM3_EINVARG;
4747 cnt_no = (uint8_t)counter;
4749 iso14a_card_select_t card;
4751 // reset counter tear
4752 counter_reset_tear(&card, cnt_no);
4754 if (ul_select(&card) == false) {
4755 PrintAndLogEx(INFO, "failed to select card, exiting...");
4756 return PM3_ESOFT;
4759 uint8_t initial_cnt[3] = {0, 0, 0};
4760 int len = ulev1_readCounter(cnt_no, initial_cnt, sizeof(initial_cnt));
4761 if ( len != sizeof(initial_cnt) ) {
4762 PrintAndLogEx(WARNING, "failed to read counter");
4763 return PM3_ESOFT;
4766 uint8_t initial_tear[1] = {0};
4767 len = ulev1_readTearing(cnt_no, initial_tear, sizeof(initial_tear));
4768 DropField();
4769 if ( len != sizeof(initial_tear) ) {
4770 PrintAndLogEx(WARNING, "failed to read ANTITEAR, exiting... %d", len);
4771 return PM3_ESOFT;
4774 uint32_t wr_value = ( newvalue[0] | newvalue[1] << 8 | newvalue[2] << 16 );
4775 uint32_t initial_value = ( initial_cnt[0] | initial_cnt[1] << 8 | initial_cnt[2] << 16 );;
4777 PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
4778 PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter);
4779 PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(initial_cnt, sizeof(initial_cnt)));
4780 PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", initial_tear[0]);
4781 PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen));
4782 PrintAndLogEx(INFO, "----------------------------------------------------");
4784 uint8_t pre_tear = 0, post_tear = 0;
4785 uint8_t pre[3] = {0};
4786 uint8_t post[3] = {0};
4787 uint32_t actual_time = start_time;
4788 uint32_t a = 0, b = 0;
4789 uint32_t loop = 0;
4791 uint16_t late = 0;
4793 while (actual_time <= (time_limit - interval)) {
4795 DropField();
4797 loop++;
4799 if (kbd_enter_pressed()) {
4800 PrintAndLogEx(INFO, "\naborted via keyboard!\n");
4801 break;
4804 PrintAndLogEx(INPLACE, "Using tear-off delay " _GREEN_("%" PRIu32) " µs (attempt %u)", actual_time, loop);
4806 if (ul_select(&card) == false) {
4807 PrintAndLogEx(FAILED, "BEFORE, failed to select card, looping...");
4808 continue;
4811 uint8_t cntresp[3] = {0, 0, 0};
4812 int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
4813 if ( rlen == sizeof(cntresp) ) {
4814 memcpy(pre, cntresp, sizeof(pre));
4815 } else {
4816 PrintAndLogEx(NORMAL, "");
4817 PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
4818 break;
4821 uint8_t tear[1] = {0};
4822 int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
4823 if ( tlen == sizeof(tear) ) {
4824 pre_tear = tear[0];
4825 } else {
4826 PrintAndLogEx(NORMAL, "");
4827 PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
4828 break;
4831 DropField();
4833 struct p {
4834 uint8_t counter;
4835 uint32_t tearoff_time;
4836 uint8_t value[3];
4837 } PACKED payload;
4838 payload.counter = cnt_no;
4839 payload.tearoff_time = actual_time;
4840 memcpy(payload.value, newvalue, sizeof(payload.value));
4842 clearCommandBuffer();
4843 PacketResponseNG resp;
4844 SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
4845 if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
4846 PrintAndLogEx(WARNING, "\ntear off command failed");
4847 continue;
4850 if (ul_select(&card) == false) {
4851 PrintAndLogEx(FAILED, "AFTER, failed to select card, exiting...");
4852 break;
4855 rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
4856 if ( rlen == sizeof(cntresp) ) {
4857 memcpy(post, cntresp, sizeof(post));
4858 } else {
4859 PrintAndLogEx(NORMAL, "");
4860 PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
4861 break;
4864 tear[0] = 0;
4865 tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
4866 if ( tlen == sizeof(tear) ) {
4867 post_tear = tear[0];
4868 } else {
4869 PrintAndLogEx(NORMAL, "");
4870 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
4871 break;
4874 DropField();
4876 char prestr[20] = {0};
4877 snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
4878 char poststr[20] = {0};
4879 snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
4881 bool post_tear_check = (post_tear == 0xBD);
4882 a = (pre[0] | pre[1] << 8 | pre[2] << 16);
4883 b = (post[0] | post[1] << 8 | post[2] << 16);
4885 // A != B
4886 if (memcmp(pre, post, sizeof(pre)) != 0) {
4889 PrintAndLogEx(NORMAL, "");
4891 if (initial_value != a ) {
4893 if ( initial_value != b )
4894 PrintAndLogEx(INFO, "pre %08x, post %08x != initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4895 else
4896 PrintAndLogEx(INFO, "pre %08x != initial and post %08x == initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4897 } else {
4899 if ( initial_value != b )
4900 PrintAndLogEx(INFO, "pre %08x == initial and post %08x != initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4903 if ( b == 0 ) {
4904 PrintAndLogEx(INFO, _CYAN_("Tear off occurred (ZEROS value!) -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
4905 , prestr
4906 , poststr
4907 , pre_tear
4908 , post_tear
4909 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4911 break;
4914 if ( a > b ) {
4915 PrintAndLogEx(INFO, _CYAN_("Tear off occurred " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
4916 , prestr
4917 , poststr
4918 , pre_tear
4919 , post_tear
4920 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4924 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
4925 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
4926 break;
4929 uint32_t bar = (0x1000000 - b) + 2;
4930 // wr_value = bar;
4931 // newvalue[0] = (bar) & 0xFF;
4932 // newvalue[1] = ((bar >> 8) & 0xFF);
4933 // newvalue[2] = ((bar >> 16) & 0xFF);
4935 wr_value = 0;
4936 newvalue[0] = 0;
4937 newvalue[1] = 0;
4938 newvalue[2] = 0;
4940 PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar);
4941 PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value);
4942 PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b);
4944 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
4945 continue;
4946 } else {
4948 PrintAndLogEx(NORMAL, "");
4949 PrintAndLogEx(INFO, _CYAN_("Tear off occurred (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
4950 , prestr
4951 , poststr
4952 , pre_tear
4953 , post_tear
4954 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4957 if ( post_tear_check && b == initial_value) {
4958 PrintAndLogEx(INFO, "Reverted to previous value");
4959 break;
4961 if ( wr_value != 0 ) {
4963 //uint32_t bar = (0x1000000 - b) + 2;
4964 wr_value = 0;
4965 newvalue[0] = 0;
4966 newvalue[1] = 0;
4967 newvalue[2] = 0;
4969 if ( b >= (initial_value + (2 * wr_value))) {
4970 PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
4973 // wr_value = bar;
4974 // newvalue[0] = (bar) & 0xFF;
4975 // newvalue[1] = ((bar >> 8) & 0xFF);
4976 // newvalue[2] = ((bar >> 16) & 0xFF);
4977 } else {
4979 // wr_value = bar;
4980 // newvalue[0] = (bar) & 0xFF;
4981 // newvalue[1] = ((bar >> 8) & 0xFF);
4982 // newvalue[2] = ((bar >> 16) & 0xFF);
4983 // wr_value = 0;
4984 // newvalue[0] = 0;
4985 // newvalue[1] = 0;
4986 // newvalue[2] = 0;
4990 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
4992 //actual_time--;
4993 late++;
4995 } else {
4996 PrintAndLogEx(NORMAL, "");
4997 PrintAndLogEx(INFO, _CYAN_("Status: same value! -> ") "%s == %s Tear: 0x%02X == 0x%02X ( %s )"
4998 , prestr
4999 , poststr
5000 , pre_tear
5001 , post_tear
5002 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
5005 if ( post_tear_check ) {
5006 if ( a == b ) {
5007 //actual_time--;
5008 continue;
5011 if ( b == initial_value ) {
5012 PrintAndLogEx(INFO, "Reverted to previous value");
5013 break;
5015 } else {
5017 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
5018 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
5019 break;
5025 actual_time += interval;
5028 DropField();
5030 PrintAndLogEx(INFO, " Sent %u tear offs ", loop);
5032 counter_reset_tear(&card, cnt_no);
5034 PrintAndLogEx(INFO, "hf 14a raw -s -c 3900 --> read counter 0");
5035 PrintAndLogEx(INFO, "hf 14a raw -s -c 3e00 --> read tearing 0");
5036 PrintAndLogEx(NORMAL, "");
5037 char read_cnt_str[30];
5038 snprintf(read_cnt_str, sizeof(read_cnt_str), "hf 14a raw -s -c 39%02x", counter);
5039 CommandReceived(read_cnt_str);
5040 char read_tear_str[30];
5041 snprintf(read_tear_str, sizeof(read_tear_str), "hf 14a raw -s -c 3e%02x", counter);
5042 CommandReceived(read_tear_str);
5043 return PM3_SUCCESS;
5049 // name, identifying bytes, decode function, hints text
5050 // identifying bits
5051 // 1. getversion data must match.
5052 // 2. magic bytes in the readable payload
5055 int CmdHF14MfuNDEFRead(const char *Cmd) {
5057 int keylen;
5058 int maxsize = 16, status;
5059 bool hasAuthKey = false;
5060 bool swapEndian = false;
5062 iso14a_card_select_t card;
5063 uint8_t data[16] = {0x00};
5064 uint8_t key[16] = {0x00};
5065 uint8_t *p_key = key;
5066 uint8_t pack[4] = {0, 0, 0, 0};
5068 CLIParserContext *ctx;
5069 CLIParserInit(&ctx, "hf mfu ndefread",
5070 "Prints NFC Data Exchange Format (NDEF)",
5071 "hf mfu ndefread -> shows NDEF data\n"
5072 "hf mfu ndefread -k ffffffff -> shows NDEF data with key\n"
5073 "hf mfu ndefread -f myfilename -> save raw NDEF to file"
5076 void *argtable[] = {
5077 arg_param_begin,
5078 arg_str0("k", "key", "Replace default key for NDEF", NULL),
5079 arg_lit0("l", NULL, "Swap entered key's endianness"),
5080 arg_str0("f", "file", "<fn>", "Save raw NDEF to file"),
5081 arg_lit0("v", "verbose", "Verbose output"),
5082 arg_param_end
5084 CLIExecWithReturn(ctx, Cmd, argtable, true);
5085 CLIGetHexWithReturn(ctx, 1, key, &keylen);
5086 swapEndian = arg_get_lit(ctx, 2);
5087 int fnlen = 0;
5088 char filename[FILE_PATH_SIZE] = {0};
5089 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5090 bool verbose = arg_get_lit(ctx, 4);
5091 CLIParserFree(ctx);
5093 switch (keylen) {
5094 case 0:
5095 break;
5096 case 4:
5097 case 16:
5098 hasAuthKey = true;
5099 break;
5100 default:
5101 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
5102 return PM3_EINVARG;
5105 // Get tag type
5106 uint64_t tagtype = GetHF14AMfU_Type();
5107 if (tagtype == MFU_TT_UL_ERROR) {
5108 PrintAndLogEx(WARNING, "No Ultralight / NTAG based tag found");
5109 return PM3_ESOFT;
5112 // Is tag UL/NTAG?
5114 // Swap endianness
5115 if (swapEndian && hasAuthKey) p_key = SwapEndian64(key, keylen, (keylen == 16) ? 8 : 4);
5117 // Select and Auth
5118 if (ul_auth_select(&card, tagtype, hasAuthKey, p_key, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT;
5120 // read pages 0,1,2,3 (should read 4pages)
5121 status = ul_read(0, data, sizeof(data));
5122 if (status <= 0) {
5123 DropField();
5124 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
5125 return PM3_ESOFT;
5126 } else if (status == 16) {
5128 status = ndef_print_CC(data + 12);
5129 if (status == PM3_ESOFT) {
5130 DropField();
5131 PrintAndLogEx(ERR, "Error: tag didn't contain a NDEF Container");
5132 return PM3_ESOFT;
5135 // max datasize;
5136 maxsize = ndef_get_maxsize(data + 12);
5139 // iceman: maybe always take MIN of tag identified size vs NDEF reported size?
5140 // fix: UL_EV1 48bytes != NDEF reported size
5141 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
5142 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
5144 if (maxsize != (UL_MEMORY_ARRAY[idx] * 4)) {
5145 PrintAndLogEx(INFO, "Tag reported size vs NDEF reported size mismatch. Using smallest value");
5147 maxsize = MIN(maxsize, (UL_MEMORY_ARRAY[idx] * 4));
5148 break;
5152 // The following read will read in blocks of 16 bytes.
5153 // ensure maxsize is rounded up to a multiple of 16
5154 maxsize = maxsize + (16 - (maxsize % 16));
5155 // allocate mem
5156 uint8_t *records = calloc(maxsize, sizeof(uint8_t));
5157 if (records == NULL) {
5158 DropField();
5159 return PM3_EMALLOC;
5162 // read NDEF records.
5163 for (uint32_t i = 0, j = 0; i < maxsize; i += 16, j += 4) {
5164 status = ul_read(4 + j, records + i, 16);
5165 if (status <= 0) {
5166 DropField();
5167 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
5168 free(records);
5169 return PM3_ESOFT;
5173 DropField();
5175 status = NDEFRecordsDecodeAndPrint(records, (size_t)maxsize, verbose);
5176 if (status != PM3_SUCCESS) {
5177 status = NDEFDecodeAndPrint(records, (size_t)maxsize, verbose);
5180 // get total NDEF length before save. If fails, we save it all
5181 size_t n = 0;
5182 if (NDEFGetTotalLength(records, maxsize, &n) != PM3_SUCCESS)
5183 n = maxsize;
5185 pm3_save_dump(filename, records, n, jsfNDEF);
5188 char *jooki = strstr((char *)records, "s.jooki.rocks/s/?s=");
5189 if (jooki) {
5190 jooki += 17;
5191 while (jooki) {
5192 if ((*jooki) != '=')
5193 jooki++;
5194 else {
5195 jooki++;
5196 char s[17] = {0};
5197 strncpy(s, jooki, 16);
5198 PrintAndLogEx(HINT, "Use `" _YELLOW_("hf jooki decode -d %s") "` to decode", s);
5199 break;
5203 char *mattel = strstr((char *)records, ".pid.mattel/");
5204 if (mattel) {
5205 mattel += 12;
5206 while (mattel) {
5207 if ((*mattel) != '/')
5208 mattel++;
5209 else {
5210 mattel++;
5211 char b64[33] = {0};
5212 strncpy(b64, mattel, 32);
5213 uint8_t arr[24] = {0};
5214 size_t arrlen = 0;
5215 mbedtls_base64_decode(arr, sizeof(arr), &arrlen, (const unsigned char *)b64, 32);
5217 PrintAndLogEx(INFO, "decoded... %s", sprint_hex(arr, arrlen));
5218 break;
5223 free(records);
5224 return status;
5227 // utility function. Retrieves emulator memory
5228 static int GetMfuDumpFromEMul(mfu_dump_t **buf) {
5230 mfu_dump_t *dump = calloc(1, sizeof(mfu_dump_t));
5231 if (dump == NULL) {
5232 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
5233 return PM3_EMALLOC;
5236 PrintAndLogEx(INFO, "downloading from emulator memory");
5237 if (!GetFromDevice(BIG_BUF_EML, (uint8_t *)dump, MFU_MAX_BYTES + MFU_DUMP_PREFIX_LENGTH, 0, NULL, 0, NULL, 2500, false)) {
5238 PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
5239 free(dump);
5240 return PM3_ETIMEOUT;
5243 *buf = dump ;
5244 return PM3_SUCCESS ;
5247 static int CmdHF14AMfuEView(const char *Cmd) {
5248 CLIParserContext *ctx;
5249 CLIParserInit(&ctx, "hf mfu eview",
5250 "Displays emulator memory\n"
5251 "By default number of pages shown depends on defined tag type.\n"
5252 "You can override this with option --end.",
5253 "hf mfu eview\n"
5254 "hf mfu eview --end 255 -> dumps whole memory"
5257 void *argtable[] = {
5258 arg_param_begin,
5259 arg_int0("e", "end", "<dec>", "index of last block"),
5260 arg_lit0("z", "dense", "dense dump output style"),
5261 arg_param_end
5264 CLIExecWithReturn(ctx, Cmd, argtable, true);
5265 int end = arg_get_int_def(ctx, 1, -1);
5266 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 2));
5267 CLIParserFree(ctx);
5269 bool override_end = (end != -1) ;
5271 if (override_end && (end < 0 || end > MFU_MAX_BLOCKS)) {
5272 PrintAndLogEx(WARNING, "Invalid value for end: %d Must be be positive integer < %d", end, MFU_MAX_BLOCKS);
5273 return PM3_EINVARG ;
5276 mfu_dump_t *dump ;
5277 int res = GetMfuDumpFromEMul(&dump) ;
5278 if (res != PM3_SUCCESS) {
5279 return res ;
5282 if (override_end) {
5283 ++end ;
5284 } else {
5285 end = dump->pages + 1;
5288 mfu_print_dump(dump, end, 0, dense_output);
5289 free(dump);
5290 return PM3_SUCCESS;
5293 static int CmdHF14AMfuESave(const char *Cmd) {
5294 CLIParserContext *ctx;
5295 CLIParserInit(&ctx, "hf mfu esave",
5296 "Saves emulator memory to a MIFARE Ultralight/NTAG dump file (bin/json)\n"
5297 "By default number of pages saved depends on defined tag type.\n"
5298 "You can override this with option --end.",
5299 "hf mfu esave\n"
5300 "hf mfu esave --end 255 -> saves whole memory\n"
5301 "hf mfu esave -f hf-mfu-04010203040506-dump"
5304 void *argtable[] = {
5305 arg_param_begin,
5306 arg_int0("e", "end", "<dec>", "index of last block"),
5307 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5308 arg_param_end
5311 CLIExecWithReturn(ctx, Cmd, argtable, true);
5312 int end = arg_get_int_def(ctx, 1, -1);
5314 char filename[FILE_PATH_SIZE];
5315 int fnlen = 0 ;
5316 CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5318 CLIParserFree(ctx);
5320 bool override_end = (end != -1) ;
5322 if (override_end && (end < 0 || end > MFU_MAX_BLOCKS)) {
5323 PrintAndLogEx(WARNING, "Invalid value for end:%d. Must be be positive integer <= %d.", end, MFU_MAX_BLOCKS);
5324 return PM3_EINVARG ;
5327 // get dump from memory
5328 mfu_dump_t *dump ;
5329 int res = GetMfuDumpFromEMul(&dump) ;
5330 if (res != PM3_SUCCESS) {
5331 return res ;
5334 // initialize filename
5335 if (fnlen < 1) {
5336 PrintAndLogEx(INFO, "Using UID as filename");
5337 uint8_t uid[7] = {0};
5338 memcpy(uid, (uint8_t *) & (dump->data), 3);
5339 memcpy(uid + 3, (uint8_t *) & (dump->data) + 4, 4);
5340 strcat(filename, "hf-mfu-");
5341 FillFileNameByUID(filename, uid, "-dump", sizeof(uid));
5344 if (override_end) {
5345 end ++ ;
5346 } else {
5347 end = dump->pages ;
5350 // save dump. Last block contains PACK + RFU
5351 uint16_t datalen = (end + 1) * MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
5352 res = pm3_save_dump(filename, (uint8_t *)dump, datalen, jsfMfuMemory);
5354 free(dump);
5355 return res;
5358 static int CmdHF14AMfuView(const char *Cmd) {
5360 CLIParserContext *ctx;
5361 CLIParserInit(&ctx, "hf mfu view",
5362 "Print a MIFARE Ultralight/NTAG dump file (bin/eml/json)",
5363 "hf mfu view -f hf-mfu-01020304-dump.bin"
5365 void *argtable[] = {
5366 arg_param_begin,
5367 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
5368 arg_lit0("v", "verbose", "Verbose output"),
5369 arg_lit0("z", "dense", "dense dump output style"),
5370 arg_param_end
5372 CLIExecWithReturn(ctx, Cmd, argtable, false);
5373 int fnlen = 0;
5374 char filename[FILE_PATH_SIZE];
5375 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
5376 bool verbose = arg_get_lit(ctx, 2);
5377 bool dense_output = (g_session.dense_output || arg_get_lit(ctx, 3));
5378 CLIParserFree(ctx);
5380 // read dump file
5381 uint8_t *dump = NULL;
5382 size_t bytes_read = 0;
5383 int res = pm3_load_dump(filename, (void **)&dump, &bytes_read, (MFU_MAX_BYTES + MFU_DUMP_PREFIX_LENGTH));
5384 if (res != PM3_SUCCESS) {
5385 return res;
5388 if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
5389 PrintAndLogEx(ERR, "Error, dump file is too small");
5390 free(dump);
5391 return PM3_ESOFT;
5394 res = convert_mfu_dump_format(&dump, &bytes_read, verbose);
5395 if (res != PM3_SUCCESS) {
5396 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
5397 free(dump);
5398 return res;
5401 uint16_t block_cnt = ((bytes_read - MFU_DUMP_PREFIX_LENGTH) / MFU_BLOCK_SIZE);
5403 if (verbose) {
5404 PrintAndLogEx(INFO, "File: " _YELLOW_("%s"), filename);
5405 PrintAndLogEx(INFO, "File size %zu bytes, file blocks %d (0x%x)", bytes_read, block_cnt, block_cnt);
5408 mfu_print_dump((mfu_dump_t *)dump, block_cnt, 0, dense_output);
5409 free(dump);
5410 return PM3_SUCCESS;
5413 static int CmdHF14AMfuList(const char *Cmd) {
5414 return CmdTraceListAlias(Cmd, "hf 14a", "14a -c");
5417 static int CmdHF14AAmiibo(const char *Cmd) {
5419 CLIParserContext *ctx;
5420 CLIParserInit(&ctx, "hf mfu amiibo",
5421 "Tries to read all memory from amiibo tag and decrypt it",
5422 "hf mfu amiiboo --dec -f hf-mfu-04579DB27C4880-dump.bin --> decrypt file\n"
5423 "hf mfu amiiboo -v --dec --> decrypt tag"
5426 void *argtable[] = {
5427 arg_param_begin,
5428 arg_lit0(NULL, "dec", "Decrypt memory"),
5429 arg_lit0(NULL, "enc", "Encrypt memory"),
5430 arg_str0("i", "in", "<fn>", "Specify a filename for input dump file"),
5431 arg_str0("o", "out", "<fn>", "Specify a filename for output dump file"),
5432 arg_lit0("v", "verbose", "Verbose output"),
5433 arg_param_end
5435 CLIExecWithReturn(ctx, Cmd, argtable, true);
5437 bool shall_decrypt = arg_get_lit(ctx, 1);
5438 bool shall_encrypt = arg_get_lit(ctx, 2);
5440 int infnlen = 0;
5441 char infilename[FILE_PATH_SIZE];
5442 CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)infilename, FILE_PATH_SIZE, &infnlen);
5444 int outfnlen = 0;
5445 char outfilename[FILE_PATH_SIZE];
5446 CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)outfilename, FILE_PATH_SIZE, &outfnlen);
5448 bool verbose = arg_get_lit(ctx, 5);
5449 CLIParserFree(ctx);
5451 // sanity checks
5452 if ((shall_decrypt + shall_encrypt) > 1) {
5453 PrintAndLogEx(WARNING, "Only specify decrypt or encrypt");
5454 return PM3_EINVARG;
5457 // load keys
5458 nfc3d_amiibo_keys_t amiibo_keys;
5459 if (nfc3d_amiibo_load_keys(&amiibo_keys) == false) {
5460 PrintAndLogEx(INFO, "loading key file ( " _RED_("fail") " )");
5461 return PM3_EFILE;
5464 int res = PM3_ESOFT;
5466 uint8_t original[NFC3D_AMIIBO_SIZE] = {0};
5468 // load dump file if available
5469 if (infnlen > 0) {
5470 uint8_t *dump = NULL;
5471 size_t dumplen = 0;
5472 res = loadFile_safe(infilename, "", (void **)&dump, &dumplen);
5473 if (res != PM3_SUCCESS) {
5474 free(dump);
5475 return PM3_EFILE;
5478 if (dumplen < MFU_DUMP_PREFIX_LENGTH) {
5479 PrintAndLogEx(ERR, "Error, dump file is too small");
5480 free(dump);
5481 return PM3_ESOFT;
5484 res = convert_mfu_dump_format(&dump, &dumplen, verbose);
5485 if (res != PM3_SUCCESS) {
5486 PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format");
5487 free(dump);
5488 return res;
5491 const mfu_dump_t *d = (mfu_dump_t *)dump;
5492 memcpy(original, d->data, sizeof(original));
5493 free(dump);
5494 } else {
5495 uint16_t dlen = 0;
5496 uint8_t *dump = NULL;
5497 res = mfu_dump_tag(MAX_NTAG_215, (void **)&dump, &dlen);
5498 if (res != PM3_SUCCESS) {
5499 PrintAndLogEx(FAILED, "Failed to dump memory from tag");
5500 free(dump);
5501 return res;
5503 memcpy(original, dump, sizeof(original));
5504 free(dump);
5508 uint8_t decrypted[NFC3D_AMIIBO_SIZE] = {0};
5509 if (shall_decrypt) {
5510 if (nfc3d_amiibo_unpack(&amiibo_keys, original, decrypted) == false) {
5511 PrintAndLogEx(INFO, "Tag signature ( " _RED_("fail") " )");
5512 return PM3_ESOFT;
5514 // print
5515 if (verbose) {
5516 for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++) {
5517 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(decrypted + (i * 16), 16));
5522 if (shall_encrypt) {
5523 uint8_t encrypted[NFC3D_AMIIBO_SIZE] = {0};
5524 nfc3d_amiibo_pack(&amiibo_keys, decrypted, encrypted);
5525 // print
5526 if (verbose) {
5527 for (uint8_t i = 0; i < (NFC3D_AMIIBO_SIZE / 16); i++) {
5528 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(encrypted + (i * 16), 16));
5533 if (outfnlen) {
5534 // save dump. Last block contains PACK + RFU
5535 // uint16_t datalen = MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
5536 // res = pm3_save_dump(outfilename, (uint8_t *)dump, datalen, jsfMfuMemory);
5539 return PM3_SUCCESS;
5542 static int CmdHF14AMfuWipe(const char *Cmd) {
5543 CLIParserContext *ctx;
5544 CLIParserInit(&ctx, "hf mfu wipe",
5545 "Wipe card to zeros. It will ignore block0,1,2,3\n"
5546 "you will need to call it with password in order to wipe the config and sett default pwd/pack\n"
5547 "Abort by pressing a key\n"
5548 "New password.... FFFFFFFF\n"
5549 "New 3-DES key... 49454D4B41455242214E4143554F5946\n",
5550 "hf mfu wipe\n"
5551 "hf mfu wipe -k 49454D4B41455242214E4143554F5946\n"
5553 void *argtable[] = {
5554 arg_param_begin,
5555 arg_str0("k", "key", "<hex>", "Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
5556 arg_lit0("l", NULL, "Swap entered key's endianness"),
5557 arg_param_end
5559 CLIExecWithReturn(ctx, Cmd, argtable, true);
5561 int ak_len = 0;
5562 uint8_t authenticationkey[16] = {0x00};
5563 uint8_t *auth_key_ptr = authenticationkey;
5564 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
5565 bool swap_endian = arg_get_lit(ctx, 2);
5567 CLIParserFree(ctx);
5569 bool has_auth_key = false;
5570 bool has_pwd = false;
5571 if (ak_len == 16) {
5572 has_auth_key = true;
5573 } else if (ak_len == 4) {
5574 has_pwd = true;
5575 } else if (ak_len != 0) {
5576 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
5577 return PM3_EINVARG;
5580 uint8_t card_mem_size = 0;
5582 // Swap endianness
5583 if (swap_endian) {
5584 if (has_auth_key) {
5585 auth_key_ptr = SwapEndian64(authenticationkey, ak_len, 8);
5588 if (has_pwd) {
5589 auth_key_ptr = SwapEndian64(authenticationkey, ak_len, 4);
5593 uint64_t tagtype = GetHF14AMfU_Type();
5594 if (tagtype == MFU_TT_UL_ERROR) {
5595 return PM3_ESOFT;
5598 // number of pages to WRITE
5599 for (uint8_t idx = 1; idx < ARRAYLEN(UL_TYPES_ARRAY); idx++) {
5600 if ((tagtype & UL_TYPES_ARRAY[idx]) == UL_TYPES_ARRAY[idx]) {
5601 //add one as maxblks starts at 0
5602 card_mem_size = UL_MEMORY_ARRAY[idx] + 1;
5603 break;
5607 ul_print_type(tagtype, 0);
5609 // GDM / GEN1A / GEN4 / NTAG21x read the key
5610 if (ak_len == 0) {
5612 DropField();
5614 int res = get_ulc_3des_key_magic(tagtype, auth_key_ptr);
5615 if (res != PM3_SUCCESS) {
5616 return res;
5618 PrintAndLogEx(SUCCESS, "Using 3DES key... %s", sprint_hex_inrow(auth_key_ptr, 16));
5619 has_auth_key = true;
5622 DropField();
5624 PrintAndLogEx(INFO, "Start wiping...");
5625 PrintAndLogEx(INFO, "-----+-----------------------------");
5626 // time to wipe card
5627 // We skip the first four blocks.
5628 // block 0,1 - UID
5629 // block 2 - lock
5630 // block 3 - OTP
5631 for (uint8_t i = 4; i < card_mem_size; i++) {
5633 if (kbd_enter_pressed()) {
5634 PrintAndLogEx(WARNING, "\naborted via keyboard!\n");
5635 goto out;
5638 uint8_t data[MFU_BLOCK_SIZE];
5639 memset(data, 0x00, sizeof(data));
5641 // UL_C specific
5642 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
5643 // default config?
5645 switch (i) {
5646 case 4:
5647 memcpy(data, "\x02\x00\x00\x10", 4);
5648 break;
5649 case 5:
5650 memcpy(data, "\x00\x06\x01\x10", 4);
5651 break;
5652 case 6:
5653 memcpy(data, "\x11\xFF\x00\x00", 4);
5654 break;
5655 case 42:
5656 memcpy(data, "\x30\x00\x00\x00", 4);
5657 break;
5658 case 44:
5659 goto ulc;
5663 // UL_AES specific
5664 if ((tagtype & MFU_TT_UL_AES)) {
5665 // default config?
5668 // UL / NTAG with PWD/PACK
5669 if ((tagtype & (MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1 | MFU_TT_UL_NANO_40 |
5670 MFU_TT_NTAG_210u | MFU_TT_NTAG_213 | MFU_TT_NTAG_213_F | MFU_TT_NTAG_213_C |
5671 MFU_TT_NTAG_213_TT | MFU_TT_NTAG_215 | MFU_TT_NTAG_216 | MFU_TT_NTAG_216_F |
5672 MFU_TT_NTAG_I2C_1K | MFU_TT_NTAG_I2C_2K | MFU_TT_NTAG_I2C_1K_PLUS | MFU_TT_NTAG_I2C_2K_PLUS
5673 ))) {
5676 // cfg 1
5677 if (i == card_mem_size - 4) {
5678 // strong modulation mode disabled
5679 // pages don't need authentication
5680 uint8_t cfg1[MFU_BLOCK_SIZE] = {0x00, 0x00, 0x00, 0xFF};
5681 memcpy(data, cfg1, sizeof(cfg1));
5684 // cfg 2
5685 if (i == card_mem_size - 3) {
5686 // Unlimited password attempts
5687 // NFC counter disabled
5688 // NFC counter not protected
5689 // user configuration writeable
5690 // write access is protected with password
5691 // 05, Virtual Card Type Identifier is default
5692 uint8_t cfg2[MFU_BLOCK_SIZE] = {0x00, 0x05, 0x00, 0x00};
5693 memcpy(data, cfg2, sizeof(cfg2));
5696 // Set PWD blocks 0xFF FF FF FF
5697 if (i == card_mem_size - 2) {
5698 memset(data, 0xFF, sizeof(data));
5701 // Since we changed PWD before, we need to use new PWD to set PACK
5702 // Pack will be all zeros,
5703 if (i == card_mem_size - 1) {
5704 memset(auth_key_ptr, 0xFF, ak_len);
5709 int res = PM3_SUCCESS;
5710 if (res == PM3_ESOFT) {
5711 res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
5715 int res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
5717 PrintAndLogEx(INFO, " %3d | %s" NOLF, i, sprint_hex(data, MFU_BLOCK_SIZE));
5718 switch (res) {
5719 case PM3_SUCCESS: {
5720 PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )");
5721 break;
5723 case PM3_ESOFT: {
5724 PrintAndLogEx(NORMAL, "( " _RED_("fail") " )");
5725 break;
5727 case PM3_ETIMEOUT:
5728 default: {
5729 PrintAndLogEx(NORMAL, "");
5730 PrintAndLogEx(WARNING, "command execution time out");
5731 goto out;
5736 PrintAndLogEx(INFO, "-----+-----------------------------");
5738 ulc:
5740 // UL-C - set 3-DES key
5741 if ((tagtype & MFU_TT_UL_C) == MFU_TT_UL_C) {
5743 uint8_t key[16] = {
5744 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42,
5745 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46
5748 clearCommandBuffer();
5749 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, key, sizeof(key));
5750 PacketResponseNG resp;
5751 if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
5752 if ((resp.oldarg[0] & 0xff) == 1) {
5753 PrintAndLogEx(INFO, "Ultralight-C new key... " _GREEN_("%s"), sprint_hex_inrow(key, sizeof(key)));
5754 } else {
5755 PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
5756 return PM3_ESOFT;
5758 } else {
5759 PrintAndLogEx(WARNING, "command execution time out");
5760 return PM3_ETIMEOUT;
5764 // UL_AES specific
5765 if ((tagtype & MFU_TT_UL_AES)) {
5766 // Set AES key
5770 PrintAndLogEx(HINT, "try `" _YELLOW_("hf mfu dump --ns") "` to verify");
5771 PrintAndLogEx(NORMAL, "");
5772 PrintAndLogEx(INFO, "Done!");
5774 out:
5775 return PM3_SUCCESS;
5778 static int CmdHF14AMfUIncr(const char *Cmd) {
5779 CLIParserContext *ctx;
5780 CLIParserInit(&ctx, "hf mfu incr",
5781 "Increment a MIFARE Ultralight Ev1 counter\n"
5782 "Will read but not increment counter if NTAG is detected",
5783 "hf mfu incr -c 0 -v 1337\n"
5784 "hf mfu incr -c 2 -v 0 -p FFFFFFFF");
5785 void *argtable[] = {
5786 arg_param_begin,
5787 arg_int1("c", "cnt", "<dec>", "Counter index from 0"),
5788 arg_int1("v", "val", "<dec>", "Value to increment by (0-16777215)"),
5789 arg_str0("p", "pwd", "<hex>", "PWD to authenticate with"),
5790 arg_param_end
5792 CLIExecWithReturn(ctx, Cmd, argtable, true);
5794 uint8_t counter = arg_get_int_def(ctx, 1, 3);
5795 uint32_t value = arg_get_u32_def(ctx, 2, 16777216);
5797 int pwd_len;
5798 uint8_t pwd[4] = { 0x00 };
5799 CLIGetHexWithReturn(ctx, 3, pwd, &pwd_len);
5800 bool has_key = false;
5801 if (pwd_len) {
5802 has_key = true;
5803 if (pwd_len != 4) {
5804 PrintAndLogEx(WARNING, "incorrect PWD length");
5805 return PM3_EINVARG;
5809 CLIParserFree(ctx);
5811 if (counter > 2) {
5812 PrintAndLogEx(WARNING, "Counter index must be in range 0-2");
5813 return PM3_EINVARG;
5815 if (value > 16777215) {
5816 PrintAndLogEx(WARNING, "Value to increment must be in range 0-16777215");
5817 return PM3_EINVARG;
5820 uint8_t increment_cmd[6] = { MIFARE_ULEV1_INCR_CNT, counter, 0x00, 0x00, 0x00, 0x00 };
5822 for (uint8_t i = 0; i < 3; i++) {
5823 increment_cmd[i + 2] = (value >> (8 * i)) & 0xff;
5826 iso14a_card_select_t card;
5827 if (ul_select(&card) == false) {
5828 PrintAndLogEx(FAILED, "failed to select card, exiting...");
5829 return PM3_ESOFT;
5832 uint64_t tagtype = GetHF14AMfU_Type();
5833 uint64_t tags_with_counter_ul = MFU_TT_UL_EV1_48 | MFU_TT_UL_EV1_128 | MFU_TT_UL_EV1;
5834 uint64_t tags_with_counter_ntag = 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;
5835 if ((tagtype & (tags_with_counter_ul | tags_with_counter_ntag)) == 0) {
5836 PrintAndLogEx(WARNING, "tag type does not have counters");
5837 DropField();
5838 return PM3_ESOFT;
5841 bool is_ntag = (tagtype & tags_with_counter_ntag) != 0;
5842 if (is_ntag && (counter != 2)) {
5843 PrintAndLogEx(WARNING, "NTAG only has one counter at index 2");
5844 DropField();
5845 return PM3_EINVARG;
5848 uint8_t pack[4] = { 0, 0, 0, 0 };
5849 if (has_key) {
5850 if (ulev1_requestAuthentication(pwd, pack, sizeof(pack)) == PM3_EWRONGANSWER) {
5851 PrintAndLogEx(FAILED, "authentication failed UL-EV1/NTAG");
5852 DropField();
5853 return PM3_ESOFT;
5857 uint8_t current_counter[3] = { 0, 0, 0 };
5858 int len = ulev1_readCounter(counter, current_counter, sizeof(current_counter));
5859 if (len != sizeof(current_counter)) {
5860 PrintAndLogEx(FAILED, "failed to read old counter");
5861 if (is_ntag) {
5862 PrintAndLogEx(HINT, "NTAG detected, try reading with PWD");
5864 DropField();
5865 return PM3_ESOFT;
5868 uint32_t current_counter_num = current_counter[0] | (current_counter[1] << 8) | (current_counter[2] << 16);
5869 PrintAndLogEx(INFO, "Current counter... " _GREEN_("%8d") " - " _GREEN_("%s"), current_counter_num, sprint_hex(current_counter, 3));
5871 if ((tagtype & tags_with_counter_ntag) != 0) {
5872 PrintAndLogEx(WARNING, "NTAG detected, unable to manually increment counter");
5873 DropField();
5874 return PM3_ESOFT;
5877 uint8_t resp[1] = { 0x00 };
5878 if (ul_send_cmd_raw(increment_cmd, sizeof(increment_cmd), resp, sizeof(resp)) < 0) {
5879 PrintAndLogEx(FAILED, "failed to increment counter");
5880 DropField();
5881 return PM3_ESOFT;
5884 uint8_t new_counter[3] = { 0, 0, 0 };
5885 int new_len = ulev1_readCounter(counter, new_counter, sizeof(new_counter));
5886 if (new_len != sizeof(current_counter)) {
5887 PrintAndLogEx(FAILED, "failed to read new counter");
5888 DropField();
5889 return PM3_ESOFT;
5892 uint32_t new_counter_num = new_counter[0] | (new_counter[1] << 8) | (new_counter[2] << 16);
5893 PrintAndLogEx(INFO, "New counter....... " _GREEN_("%8d") " - " _GREEN_("%s"), new_counter_num, sprint_hex(new_counter, 3));
5895 DropField();
5896 return PM3_SUCCESS;
5899 static command_t CommandTable[] = {
5900 {"help", CmdHelp, AlwaysAvailable, "This help"},
5901 {"list", CmdHF14AMfuList, AlwaysAvailable, "List MIFARE Ultralight / NTAG history"},
5902 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("recovery") " -------------------------"},
5903 {"keygen", CmdHF14AMfUKeyGen, AlwaysAvailable, "Generate DES/3DES/AES MIFARE diversified keys"},
5904 {"pwdgen", CmdHF14AMfUPwdGen, AlwaysAvailable, "Generate pwd from known algos"},
5905 {"otptear", CmdHF14AMfuOtpTearoff, IfPm3Iso14443a, "Tear-off test on OTP bits"},
5906 // {"tear_cnt", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1/NTAG Counter bits"},
5907 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("operations") " -----------------------"},
5908 {"cauth", CmdHF14AMfUCAuth, IfPm3Iso14443a, "Ultralight-C - Authentication"},
5909 {"setpwd", CmdHF14AMfUCSetPwd, IfPm3Iso14443a, "Ultralight-C - Set 3DES key"},
5910 {"dump", CmdHF14AMfUDump, IfPm3Iso14443a, "Dump MIFARE Ultralight family tag to binary file"},
5911 {"incr", CmdHF14AMfUIncr, IfPm3Iso14443a, "Increments Ev1/NTAG counter"},
5912 {"info", CmdHF14AMfUInfo, IfPm3Iso14443a, "Tag information"},
5913 {"ndefread", CmdHF14MfuNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"},
5914 {"rdbl", CmdHF14AMfURdBl, IfPm3Iso14443a, "Read block"},
5915 {"restore", CmdHF14AMfURestore, IfPm3Iso14443a, "Restore a dump file onto a tag"},
5916 {"tamper", CmdHF14MfUTamper, IfPm3Iso14443a, "NTAG 213TT - Configure the tamper feature"},
5917 {"view", CmdHF14AMfuView, AlwaysAvailable, "Display content from tag dump file"},
5918 {"wipe", CmdHF14AMfuWipe, IfPm3Iso14443a, "Wipe card to zeros and default key"},
5919 {"wrbl", CmdHF14AMfUWrBl, IfPm3Iso14443a, "Write block"},
5920 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("simulation") " -----------------------"},
5921 {"eload", CmdHF14AMfUeLoad, IfPm3Iso14443a, "Upload file into emulator memory"},
5922 {"esave", CmdHF14AMfuESave, IfPm3Iso14443a, "Save emulator memory to file"},
5923 {"eview", CmdHF14AMfuEView, IfPm3Iso14443a, "View emulator memory"},
5924 {"sim", CmdHF14AMfUSim, IfPm3Iso14443a, "Simulate MIFARE Ultralight from emulator memory"},
5925 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " ----------------------------"},
5926 {"setuid", CmdHF14AMfUCSetUid, IfPm3Iso14443a, "Set UID - MAGIC tags only"},
5927 {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("amiibo") " ----------------------------"},
5928 {"amiibo", CmdHF14AAmiibo, IfPm3Iso14443a, "Amiibo tag operations"},
5929 {NULL, NULL, NULL, NULL}
5932 static int CmdHelp(const char *Cmd) {
5933 (void)Cmd; // Cmd is not used so far
5934 CmdsHelp(CommandTable);
5935 return PM3_SUCCESS;
5938 int CmdHFMFUltra(const char *Cmd) {
5939 clearCommandBuffer();
5940 return CmdsParse(CommandTable, Cmd);