1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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 //-----------------------------------------------------------------------------
20 #include "cmdparser.h"
21 #include "commonutil.h"
22 #include "crypto/libpcrypto.h"
28 #include "protocols.h"
29 #include "generator.h"
31 #include "cliparser.h"
33 #include "amiibo.h" // amiiboo fcts
35 #include "fileutils.h" // saveFile
36 #include "cmdtrace.h" // trace list
37 #include "preferences.h" // setDeviceDebugLevel
39 #define MAX_UL_BLOCKS 0x0F
40 #define MAX_ULC_BLOCKS 0x2F
41 #define MAX_ULEV1a_BLOCKS 0x13
42 #define MAX_ULEV1b_BLOCKS 0x28
43 #define MAX_NTAG_203 0x29
44 #define MAX_NTAG_210 0x13
45 #define MAX_NTAG_212 0x28
46 #define MAX_NTAG_213 0x2C
47 #define MAX_NTAG_215 0x86
48 #define MAX_NTAG_216 0xE6
49 #define MAX_NTAG_I2C_1K 0xE9
50 #define MAX_NTAG_I2C_2K 0xE9
51 #define MAX_MY_D_NFC 0xFF
52 #define MAX_MY_D_MOVE 0x25
53 #define MAX_MY_D_MOVE_LEAN 0x0F
54 #define MAX_UL_NANO_40 0x0A
55 #define MAX_UL_AES 0x37
57 static int CmdHelp(const char *Cmd
);
59 static uint8_t default_aes_keys
[][16] = {
60 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
61 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
62 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
63 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
64 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
65 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
66 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33
67 { 0x47, 0x45, 0x4D, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x4F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45 }, // gemalto
68 { 0x56, 0x4c, 0x67, 0x56, 0x99, 0x69, 0x64, 0x9f, 0x17, 0xC6, 0xC6, 0x16, 0x01, 0x10, 0x4D, 0xCA } // Virtual Dorma Kaba
71 static uint8_t default_3des_keys
[][16] = {
72 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
73 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
74 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
75 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
76 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
77 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
78 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }, // 11 22 33
79 { 0x47, 0x45, 0x4D, 0x58, 0x50, 0x52, 0x45, 0x53, 0x53, 0x4F, 0x53, 0x41, 0x4D, 0x50, 0x4C, 0x45 } // gemalto
82 static uint8_t default_pwd_pack
[][4] = {
83 {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default
84 {0x4E, 0x45, 0x78, 0x54}, // NExT
87 static uint64_t UL_TYPES_ARRAY
[] = {
88 MFU_TT_UNKNOWN
, MFU_TT_UL
,
89 MFU_TT_UL_C
, MFU_TT_UL_EV1_48
,
90 MFU_TT_UL_EV1_128
, MFU_TT_NTAG
,
91 MFU_TT_NTAG_203
, MFU_TT_NTAG_210
,
92 MFU_TT_NTAG_212
, MFU_TT_NTAG_213
,
93 MFU_TT_NTAG_215
, MFU_TT_NTAG_216
,
94 MFU_TT_MY_D
, MFU_TT_MY_D_NFC
,
95 MFU_TT_MY_D_MOVE
, MFU_TT_MY_D_MOVE_NFC
,
96 MFU_TT_MY_D_MOVE_LEAN
, MFU_TT_NTAG_I2C_1K
,
97 MFU_TT_NTAG_I2C_2K
, MFU_TT_NTAG_I2C_1K_PLUS
,
98 MFU_TT_NTAG_I2C_2K_PLUS
, MFU_TT_FUDAN_UL
,
99 MFU_TT_NTAG_213_F
, MFU_TT_NTAG_216_F
,
100 MFU_TT_UL_EV1
, MFU_TT_UL_NANO_40
,
101 MFU_TT_NTAG_213_TT
, MFU_TT_NTAG_213_C
,
102 MFU_TT_MAGIC_1A
, MFU_TT_MAGIC_1B
,
103 MFU_TT_MAGIC_NTAG
, MFU_TT_NTAG_210u
,
104 MFU_TT_UL_MAGIC
, MFU_TT_UL_C_MAGIC
,
108 static uint8_t UL_MEMORY_ARRAY
[ARRAYLEN(UL_TYPES_ARRAY
)] = {
109 // UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128,
110 MAX_UL_BLOCKS
, MAX_UL_BLOCKS
, MAX_ULC_BLOCKS
, MAX_ULEV1a_BLOCKS
, MAX_ULEV1b_BLOCKS
,
111 // NTAG, NTAG_203, NTAG_210, NTAG_212,
112 MAX_NTAG_203
, MAX_NTAG_203
, MAX_NTAG_210
, MAX_NTAG_212
,
113 // NTAG_213, NTAG_215, NTAG_216,
114 MAX_NTAG_213
, MAX_NTAG_215
, MAX_NTAG_216
,
115 // MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN,
116 MAX_UL_BLOCKS
, MAX_MY_D_NFC
, MAX_MY_D_MOVE
, MAX_MY_D_MOVE
, MAX_MY_D_MOVE_LEAN
,
117 // NTAG_I2C_1K, NTAG_I2C_2K, NTAG_I2C_1K_PLUS, NTAG_I2C_2K_PLUS,
118 MAX_NTAG_I2C_1K
, MAX_NTAG_I2C_2K
, MAX_NTAG_I2C_1K
, MAX_NTAG_I2C_2K
,
119 // FUDAN_UL, NTAG_213_F, NTAG_216_F, UL_EV1, UL_NANO_40,
120 MAX_UL_BLOCKS
, MAX_NTAG_213
, MAX_NTAG_216
, MAX_ULEV1a_BLOCKS
, MAX_UL_NANO_40
,
121 // NTAG_213_TT, NTAG_213_C,
122 MAX_NTAG_213
, MAX_NTAG_213
,
123 // MAGIC_1A, MAGIC_1B, MAGIC_NTAG,
124 MAX_UL_BLOCKS
, MAX_UL_BLOCKS
, MAX_NTAG_216
,
125 // NTAG_210u, UL_MAGIC, UL_C_MAGIC
126 MAX_NTAG_210
, MAX_UL_BLOCKS
, MAX_ULC_BLOCKS
, MAX_UL_AES
129 static const ul_family_t ul_family
[] = {
130 {"UL-C", "UL-C", "\x00\x00\x00\x00\x00\x00\x00\x00"},
131 {"UL", "MF0UL1001DUx", "\x00\x04\x03\x01\x00\x00\x0B\x03"},
132 {"UL EV1 48", "MF0UL1101DUx", "\x00\x04\x03\x01\x01\x00\x0B\x03"},
133 {"UL EV1 48", "MF0ULH1101DUx", "\x00\x04\x03\x02\x01\x00\x0B\x03"},
134 {"UL EV1 48", "MF0UL1141DUF", "\x00\x04\x03\x03\x01\x00\x0B\x03"},
135 {"UL EV1 128", "MF0UL2101Dxy", "\x00\x04\x03\x01\x01\x00\x0E\x03"},
136 {"UL EV1 128", "MF0UL2101DUx", "\x00\x04\x03\x02\x01\x00\x0E\x03"},
137 {"UL Ev1 n/a ", "MF0UL3101DUx", "\x00\x04\x03\x01\x01\x00\x11\x03"},
138 {"UL Ev1 n/a", "MF0ULH3101DUx", "\x00\x04\x03\x02\x01\x00\x11\x03"},
139 {"UL Ev1 n/a", "MF0UL5101DUx", "\x00\x04\x03\x01\x01\x00\x13\x03"},
140 {"NTAG 210", "NT2L1011F0DUx", "\x00\x04\x04\x01\x01\x00\x0B\x03"},
141 {"NTAG 210", "NT2H1011G0DUD", "\x00\x04\x04\x02\x01\x00\x0B\x03"},
142 {"NTAG 212", "NT2L1211F0DUx", "\x00\x04\x04\x01\x01\x00\x0E\x03"},
143 {"NTAG 213", "NT2H1311G0DUx", "\x00\x04\x04\x02\x01\x00\x0F\x03"},
144 {"NTAG", "NT2H1411G0DUx", "\x00\x04\x04\x02\x01\x01\x11\x03"},
145 {"NTAG 215", "NT2H1511G0DUx", "\x00\x04\x04\x02\x01\x00\x11\x03"},
146 {"NTAG 215", "NT2H1511F0Dxy", "\x00\x04\x04\x04\x01\x00\x11\x03"},
147 {"NTAG 216", "NT2H1611G0DUx", "\x00\x04\x04\x02\x01\x00\x13\x03"},
148 {"NTAG 213F", "NT2H1311F0Dxy", "\x00\x04\x04\x04\x01\x00\x0F\x03"},
149 {"NTAG 216F", "NT2H1611F0Dxy", "\x00\x04\x04\x04\x01\x00\x13\x03"},
150 {"NTAG 213C", "NT2H1311C1DTL", "\x00\x04\x04\x02\x01\x01\x0F\x03"},
151 {"NTAG 213TT", "NT2H1311TTDUx", "\x00\x04\x04\x02\x03\x00\x0F\x03"},
152 {"NTAG I2C 1k", "NT3H1101W0FHK", "\x00\x04\x04\x05\x02\x00\x13\x03"},
153 {"NTAG I2C 1k", "NT3H1101W0FHK_Variant", "\x00\x04\x04\x05\x02\x01\x13\x03"},
154 {"NTAG I2C 2k", "NT3H1201W0FHK", "\x00\x04\x04\x05\x02\x00\x15\x03"},
155 {"NTAG I2C 2k", "NT3H1201", "\x00\x04\x04\x05\x02\x01\x15\x03"},
156 {"NTAG I2C 1k Plus", "NT3H2111", "\x00\x04\x04\x05\x02\x02\x13\x03"},
157 {"NTAG I2C 2k Plus", "NT3H2211", "\x00\x04\x04\x05\x02\x02\x15\x03"},
158 {"NTAG unk", "nhs", "\x00\x04\x04\x06\x00\x00\x13\x03"},
159 {"UL NANO 40", "MF0UN0001DUx 17pF", "\x00\x04\x03\x01\x02\x00\x0B\x03"},
160 {"UL NANO", "MF0UN1001DUx 17pF", "\x00\x04\x03\x01\x03\x00\x0B\x03"},
161 {"UL NANO 40", "MF0UNH0001DUx 50pF", "\x00\x04\x03\x02\x02\x00\x0B\x03"},
162 {"UL NANO", "MF0UNH1001DUx 50pF", "\x00\x04\x03\x02\x03\x00\x0B\x03"},
163 {"NTAG 210u", "NT2L1001G0DUx", "\x00\x04\x04\x01\x02\x00\x0B\x03"},
164 {"NTAG 210u", "NT2H1001G0DUx", "\x00\x04\x04\x02\x02\x00\x0B\x03"},
165 {"UL EV1 128", "Mikron JSC Russia EV1", "\x00\x34\x21\x01\x01\x00\x0E\x03"},
166 {"NTAG 213", "Shanghai Feiju NTAG", "\x00\x53\x04\x02\x01\x00\x0F\x03"},
167 {"UL AES", "MF0AES2001DUD", "\x00\x04\x03\x01\x04\x00\x0F\x03"},
170 static bool compare_ul_family(uint8_t *d
, uint8_t n
) {
179 for (int i
= 0; i
< ARRAYLEN(ul_family
); ++i
) {
180 if (memcmp(d
, ul_family
[i
].version
, n
) == 0) {
187 //------------------------------------
188 // get version nxp product type
189 static const char *getProductTypeStr(uint8_t id
) {
191 memset(buf
, 0, sizeof(buf
));
199 snprintf(buf
, sizeof(buf
), "%02X, unknown", id
);
204 static int ul_print_nxp_silicon_info(uint8_t *card_uid
) {
206 if (card_uid
[0] != 0x04) {
211 memcpy(&uid
, card_uid
, 7);
213 uint16_t waferCoordX
= ((uid
[6] & 3) << 8) | uid
[1];
214 uint16_t waferCoordY
= ((uid
[6] & 12) << 6) | uid
[2];
215 uint32_t waferCounter
= (
217 ((uid
[6] & 0xF0) << 17) |
221 uint8_t testSite
= uid
[3] & 7;
223 PrintAndLogEx(NORMAL
, "");
224 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Silicon Information"));
225 PrintAndLogEx(INFO
, " Wafer Counter: %" PRId32
" ( 0x%02" PRIX32
" )", waferCounter
, waferCounter
);
226 PrintAndLogEx(INFO
, " Wafer Coordinates: x %" PRId16
", y %" PRId16
" (0x%02" PRIX16
", 0x%02" PRIX16
")"
232 PrintAndLogEx(INFO
, " Test Site: %u", testSite
);
236 static int get_ulc_3des_key_magic(uint64_t magic_type
, uint8_t *key
) {
238 mf_readblock_ex_t payload
= {
239 .read_cmd
= ISO14443A_CMD_READBLOCK
,
243 if ((magic_type
& MFU_TT_MAGIC_1A
) == MFU_TT_MAGIC_1A
) {
244 payload
.wakeup
= MF_WAKE_GEN1A
;
245 payload
.auth_cmd
= 0;
246 } else if ((magic_type
& MFU_TT_MAGIC_1B
) == MFU_TT_MAGIC_1B
) {
247 payload
.wakeup
= MF_WAKE_GEN1B
;
248 payload
.auth_cmd
= 0;
249 } else if ((magic_type
& MFU_TT_MAGIC_4
) == MFU_TT_MAGIC_4
) {
250 payload
.wakeup
= MF_WAKE_GDM_ALT
;
251 payload
.auth_cmd
= 0;
252 } else if ((magic_type
& MFU_TT_MAGIC_NTAG21X
) == MFU_TT_MAGIC_NTAG21X
) {
253 payload
.wakeup
= MF_WAKE_WUPA
;
254 payload
.auth_cmd
= 0;
256 payload
.wakeup
= MF_WAKE_WUPA
;
257 payload
.auth_cmd
= MIFARE_MAGIC_GDM_AUTH_KEY
;
260 clearCommandBuffer();
261 SendCommandNG(CMD_HF_MIFARE_READBL_EX
, (uint8_t *)&payload
, sizeof(payload
));
262 PacketResponseNG resp
;
263 if (WaitForResponseTimeout(CMD_HF_MIFARE_READBL_EX
, &resp
, 1500) == false) {
264 PrintAndLogEx(WARNING
, "command execute timeout");
268 if (resp
.status
== PM3_SUCCESS
&& resp
.length
== MFBLOCK_SIZE
) {
269 uint8_t *d
= resp
.data
.asBytes
;
271 reverse_array(d
+ 8, 8);
272 memcpy(key
, d
, MFBLOCK_SIZE
);
279 The 7 MSBits (=n) code the storage size itself based on 2^n,
280 the LSBit is set to '0' if the size is exactly 2^n
281 and set to '1' if the storage size is between 2^n and 2^(n+1).
283 static const char *getUlev1CardSizeStr(uint8_t fsize
) {
286 memset(buf
, 0, sizeof(buf
));
288 uint16_t usize
= 1 << ((fsize
>> 1) + 1);
289 uint16_t lsize
= 1 << (fsize
>> 1);
293 snprintf(buf
, sizeof(buf
), "%02X, (%u <-> %u bytes)", fsize
, usize
, lsize
);
295 snprintf(buf
, sizeof(buf
), "%02X, (%u bytes)", fsize
, lsize
);
299 int ul_read_uid(uint8_t *uid
) {
301 PrintAndLogEx(WARNING
, "NUll parameter UID");
305 clearCommandBuffer();
306 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
307 PacketResponseNG resp
;
308 WaitForResponse(CMD_ACK
, &resp
);
309 iso14a_card_select_t card
;
310 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
312 uint64_t select_status
= resp
.oldarg
[0];
316 // 3: proprietary Anticollision
317 if (select_status
== 0) {
318 PrintAndLogEx(DEBUG
, "iso14443a card select failed");
321 memcpy(uid
, card
.uid
, 7);
323 if (card
.uidlen
!= 7) {
324 PrintAndLogEx(WARNING
, "Wrong sized UID, expected 7 bytes, got " _RED_("%d"), card
.uidlen
);
330 static void ul_switch_on_field(void) {
331 clearCommandBuffer();
332 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
335 static int ul_send_cmd_raw(uint8_t *cmd
, uint8_t cmdlen
, uint8_t *response
, uint16_t responseLength
) {
336 clearCommandBuffer();
337 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_NO_DISCONNECT
| ISO14A_APPEND_CRC
| ISO14A_NO_RATS
, cmdlen
, 0, cmd
, cmdlen
);
338 PacketResponseNG resp
;
339 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
343 if (!resp
.oldarg
[0] && responseLength
) {
344 return PM3_EWRONGANSWER
;
347 uint16_t resplen
= (resp
.oldarg
[0] < responseLength
) ? resp
.oldarg
[0] : responseLength
;
348 memcpy(response
, resp
.data
.asBytes
, resplen
);
352 static bool ul_select(iso14a_card_select_t
*card
) {
354 ul_switch_on_field();
356 PacketResponseNG resp
;
357 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
358 PrintAndLogEx(DEBUG
, "iso14443a card select timeout");
363 uint16_t len
= (resp
.oldarg
[1] & 0xFFFF);
365 PrintAndLogEx(DEBUG
, "iso14443a card select failed");
371 memcpy(card
, resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
377 static bool ul_select_rats(iso14a_card_select_t
*card
) {
379 ul_switch_on_field();
381 PacketResponseNG resp
;
382 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
383 PrintAndLogEx(DEBUG
, "iso14443a card select timeout");
388 uint16_t len
= (resp
.oldarg
[1] & 0xFFFF);
390 PrintAndLogEx(DEBUG
, "iso14443a card select failed");
396 memcpy(card
, resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
399 if (resp
.oldarg
[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
401 uint8_t rats
[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
402 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_APPEND_CRC
| ISO14A_NO_DISCONNECT
, sizeof(rats
), 0, rats
, sizeof(rats
));
403 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
404 PrintAndLogEx(WARNING
, "Command execute timeout");
410 card
->ats_len
= resp
.oldarg
[0];
411 memcpy(card
->ats
, resp
.data
.asBytes
, card
->ats_len
);
418 // This read command will at least return 16bytes.
419 static int ul_read(uint8_t page
, uint8_t *response
, uint16_t responseLength
) {
421 uint8_t cmd
[] = {ISO14443A_CMD_READBLOCK
, page
};
422 return ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
425 static int ul_comp_write(uint8_t page
, uint8_t *data
, uint8_t datalen
) {
432 memset(cmd
, 0x00, sizeof(cmd
));
433 datalen
= (datalen
> 16) ? 16 : datalen
;
435 cmd
[0] = ISO14443A_CMD_WRITEBLOCK
;
437 memcpy(cmd
+ 2, data
, datalen
);
439 uint8_t response
[1] = {0xFF};
440 ul_send_cmd_raw(cmd
, 2 + datalen
, response
, sizeof(response
));
442 if (response
[0] == 0x0a) {
446 return PM3_EWRONGANSWER
;
449 static int ulc_requestAuthentication(uint8_t *nonce
, uint16_t nonceLength
) {
451 uint8_t cmd
[] = {MIFARE_ULC_AUTH_1
, 0x00};
452 return ul_send_cmd_raw(cmd
, sizeof(cmd
), nonce
, nonceLength
);
455 static int ulev1_requestAuthentication(uint8_t *pwd
, uint8_t *pack
, uint16_t packLength
) {
457 uint8_t cmd
[] = {MIFARE_ULEV1_AUTH
, pwd
[0], pwd
[1], pwd
[2], pwd
[3]};
458 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), pack
, packLength
);
459 // NACK tables different tags, but between 0-9 is a NEGATIVE response.
461 if (len
== 1 && pack
[0] <= 0x09) {
462 return PM3_EWRONGANSWER
;
468 Default AES key is 00-00h. Both the data and UID one.
469 Data key is 00, UID is 01. Authenticity is 02h
470 Auth is 1A[Key ID][CRC] - AF[RndB] - AF[RndA][RndB'] - 00[RndA']
472 static int ulaes_requestAuthentication(uint8_t *key
, uint8_t keyno
, bool switch_off_field
) {
479 payload
.turn_off_field
= switch_off_field
;
480 payload
.keyno
= keyno
;
481 memcpy(payload
.key
, key
, sizeof(payload
.key
));
483 clearCommandBuffer();
484 SendCommandNG(CMD_HF_MIFAREULAES_AUTH
, (uint8_t *)&payload
, sizeof(payload
));
485 PacketResponseNG resp
;
486 if (WaitForResponseTimeout(CMD_HF_MIFAREULAES_AUTH
, &resp
, 1500) == false) {
489 if (resp
.status
!= PM3_SUCCESS
) {
495 static int ulc_authentication(uint8_t *key
, bool switch_off_field
) {
497 clearCommandBuffer();
498 SendCommandMIX(CMD_HF_MIFAREUC_AUTH
, switch_off_field
, 0, 0, key
, 16);
499 PacketResponseNG resp
;
500 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
503 if (resp
.oldarg
[0] == 1) {
509 static int trace_mfuc_try_key(uint8_t *key
, int state
, uint8_t (*authdata
)[16]) {
511 uint8_t RndB
[8] = {0};
512 uint8_t RndARndB
[16] = {0};
513 uint8_t RndA
[8] = {0};
514 mbedtls_des3_context ctx_des3
;
517 mbedtls_des3_set2key_dec(&ctx_des3
, key
);
518 mbedtls_des3_crypt_cbc(&ctx_des3
, MBEDTLS_DES_DECRYPT
,
519 8, iv
, authdata
[0], RndB
);
520 mbedtls_des3_crypt_cbc(&ctx_des3
, MBEDTLS_DES_DECRYPT
,
521 16, iv
, authdata
[1], RndARndB
);
522 if ((memcmp(&RndB
[1], &RndARndB
[8], 7) == 0) &&
523 (RndB
[0] == RndARndB
[15])) {
528 if (key
== NULL
) {// if no key was found
531 memcpy(iv
, authdata
[0], 8);
532 mbedtls_des3_set2key_dec(&ctx_des3
, key
);
533 mbedtls_des3_crypt_cbc(&ctx_des3
, MBEDTLS_DES_DECRYPT
,
534 16, iv
, authdata
[1], RndARndB
);
535 mbedtls_des3_crypt_cbc(&ctx_des3
, MBEDTLS_DES_DECRYPT
,
536 8, iv
, authdata
[2], RndA
);
537 if ((memcmp(&RndARndB
[1], RndA
, 7) == 0) &&
538 (RndARndB
[0] == RndA
[7])) {
548 int trace_mfuc_try_default_3des_keys(uint8_t **correct_key
, int state
, uint8_t (*authdata
)[16]) {
551 for (uint8_t i
= 0; i
< ARRAYLEN(default_3des_keys
); ++i
) {
552 uint8_t *key
= default_3des_keys
[i
];
553 if (trace_mfuc_try_key(key
, state
, authdata
) == PM3_SUCCESS
) {
560 return trace_mfuc_try_key(*correct_key
, state
, authdata
);
568 // param override, means we override hw debug levels.
569 static int try_default_3des_keys(bool override
, uint8_t **correct_key
) {
571 uint8_t dbg_curr
= DBG_NONE
;
573 if (getDeviceDebugLevel(&dbg_curr
) != PM3_SUCCESS
) {
577 if (setDeviceDebugLevel(DBG_NONE
, false) != PM3_SUCCESS
) {
584 PrintAndLogEx(INFO
, "");
585 PrintAndLogEx(SUCCESS
, "--- " _CYAN_("Known UL-C 3DES keys"));
587 for (uint8_t i
= 0; i
< ARRAYLEN(default_3des_keys
); ++i
) {
588 uint8_t *key
= default_3des_keys
[i
];
589 if (ulc_authentication(key
, true) == PM3_SUCCESS
) {
597 setDeviceDebugLevel(dbg_curr
, false);
602 // param override, means we override hw debug levels.
603 static int try_default_aes_keys(bool override
) {
605 uint8_t dbg_curr
= DBG_NONE
;
607 if (getDeviceDebugLevel(&dbg_curr
) != PM3_SUCCESS
) {
611 if (setDeviceDebugLevel(DBG_NONE
, false) != PM3_SUCCESS
) {
618 PrintAndLogEx(NORMAL
, "");
619 PrintAndLogEx(SUCCESS
, "--- " _CYAN_("Known UL-AES keys"));
621 for (uint8_t i
= 0; i
< ARRAYLEN(default_aes_keys
); ++i
) {
622 uint8_t *key
= default_aes_keys
[i
];
624 for (uint8_t keyno
= 0; keyno
< 3; keyno
++) {
626 if (ulaes_requestAuthentication(key
, keyno
, true) == PM3_SUCCESS
) {
628 char keystr
[20] = {0};
631 sprintf(keystr
, "Data key");
634 sprintf(keystr
, "UID key");
637 sprintf(keystr
, "Authenticity key");
642 PrintAndLogEx(SUCCESS
, "%02X " _YELLOW_("%s") " - %s ( "_GREEN_("ok") " )"
645 , sprint_hex_inrow(key
, 16)
654 setDeviceDebugLevel(dbg_curr
, false);
659 static int ul_auth_select(iso14a_card_select_t
*card
, uint64_t tagtype
, bool hasAuthKey
, uint8_t *authkey
, uint8_t *pack
, uint8_t packSize
) {
661 if (hasAuthKey
&& (tagtype
& MFU_TT_UL_C
)) {
662 //will select card automatically and close connection on error
663 if (ulc_authentication(authkey
, false) != PM3_SUCCESS
) {
664 PrintAndLogEx(WARNING
, "Authentication Failed UL-C");
669 if (ul_select(card
) == false) {
674 if (ulev1_requestAuthentication(authkey
, pack
, packSize
) == PM3_EWRONGANSWER
) {
676 PrintAndLogEx(WARNING
, "Authentication Failed UL-EV1/NTAG");
684 static int ntagtt_getTamperStatus(uint8_t *response
, uint16_t responseLength
) {
685 uint8_t cmd
[] = {NTAGTT_CMD_READ_TT
, 0x00};
686 return ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
689 static int ulev1_getVersion(uint8_t *response
, uint16_t responseLength
) {
690 uint8_t cmd
[] = {MIFARE_ULEV1_VERSION
};
691 return ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
694 static int ulev1_readCounter(uint8_t counter
, uint8_t *response
, uint16_t responseLength
) {
695 uint8_t cmd
[] = {MIFARE_ULEV1_READ_CNT
, counter
};
696 return ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
699 static int ulev1_readTearing(uint8_t counter
, uint8_t *response
, uint16_t responseLength
) {
700 uint8_t cmd
[] = {MIFARE_ULEV1_CHECKTEAR
, counter
};
701 return ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
704 static int ulev1_readSignature(uint8_t *response
, uint16_t responseLength
) {
705 uint8_t cmd
[] = {MIFARE_ULEV1_READSIG
, 0x00};
706 return ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
709 // Fudan check checks for which error is given for a command with incorrect crc
710 // NXP UL chip responds with 01, fudan 00.
711 // other possible checks:
713 // UL responds with 00, fudan doesn't respond
716 // UL doesn't respond, fudan responds with 00
718 // send 300000 + crc (read with extra byte(s))
719 // UL responds with read of page 0, fudan doesn't respond.
721 // make sure field is off before calling this function
722 static int ul_fudan_check(void) {
723 iso14a_card_select_t card
;
724 if (ul_select(&card
) == false) {
725 return MFU_TT_UL_ERROR
;
728 uint8_t cmd
[4] = {ISO14443A_CMD_READBLOCK
, 0x00, 0x02, 0xa7}; // wrong crc on purpose, should be 0xa8
729 clearCommandBuffer();
730 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_NO_DISCONNECT
| ISO14A_NO_RATS
, 4, 0, cmd
, sizeof(cmd
));
731 PacketResponseNG resp
;
732 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
733 return MFU_TT_UL_ERROR
;
735 if (resp
.oldarg
[0] != 1) {
736 return MFU_TT_UL_ERROR
;
739 return (resp
.data
.asBytes
[0] == 0)
740 ? MFU_TT_FUDAN_UL
: MFU_TT_UL
; //if response == 0x00 then Fudan, else Genuine NXP
743 static int ul_print_default(uint8_t *data
, uint8_t *real_uid
) {
753 bool mful_uid_layout
= true;
755 if (memcmp(uid
, real_uid
, 7) != 0) {
756 mful_uid_layout
= false;
758 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(real_uid
, 7));
759 PrintAndLogEx(SUCCESS
, " UID[0]: %02X, %s", real_uid
[0], getTagInfo(real_uid
[0]));
760 if (real_uid
[0] == 0x05 && ((real_uid
[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP
761 uint8_t chip
= (data
[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU
764 PrintAndLogEx(SUCCESS
, " IC type: SLE 66R04P 770 Bytes");
767 PrintAndLogEx(SUCCESS
, " IC type: SLE 66R16P 2560 Bytes");
770 PrintAndLogEx(SUCCESS
, " IC type: SLE 66R32P 5120 Bytes");
771 break; //512 pages /2 sectors
774 if (mful_uid_layout
) {
775 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
776 int crc0
= 0x88 ^ uid
[0] ^ uid
[1] ^ uid
[2];
778 PrintAndLogEx(SUCCESS
, " BCC0: %02X ( " _GREEN_("ok") " )", data
[3]);
780 PrintAndLogEx(NORMAL
, " BCC0: %02X, crc should be %02X", data
[3], crc0
);
782 int crc1
= uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6];
784 PrintAndLogEx(SUCCESS
, " BCC1: %02X ( " _GREEN_("ok") " )", data
[8]);
786 PrintAndLogEx(NORMAL
, " BCC1: %02X, crc should be %02X", data
[8], crc1
);
787 PrintAndLogEx(SUCCESS
, " Internal: %02X ( %s )", data
[9], (data
[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
789 PrintAndLogEx(SUCCESS
, "Blocks 0-2: %s", sprint_hex(data
+ 0, 12));
792 PrintAndLogEx(SUCCESS
, " Lock: %s - %s",
793 sprint_hex(data
+ 10, 2),
794 sprint_bin(data
+ 10, 2)
797 PrintAndLogEx(SUCCESS
, " OTP: " _YELLOW_("%s") " - %s",
798 sprint_hex(data
+ 12, 4),
799 sprint_bin(data
+ 12, 4)
804 static int ndef_get_maxsize(const uint8_t *data
) {
811 else if (data
[2] == 0x12)
813 else if (data
[2] == 0x3E)
815 else if (data
[2] == 0x6D)
820 static int ndef_print_CC(uint8_t *data
) {
823 if (data
[0] != 0xE1 && data
[0] != 0xF1) {
827 //NFC Forum Type 1,2,3,4
831 // b7, b6 major version
832 // b5, b4 minor version
834 // 00 always, 01 rfu, 10 proprietary, 11 rfu
836 // 00 always, 01 rfo, 10 proprietary, 11 never
837 uint8_t cc_write
= data
[1] & 0x03;
838 uint8_t cc_read
= (data
[1] & 0x0C) >> 2;
839 uint8_t cc_minor
= (data
[1] & 0x30) >> 4;
840 uint8_t cc_major
= (data
[1] & 0xC0) >> 6;
845 wStr
= "Write access granted without any security";
851 wStr
= "Proprietary";
854 wStr
= "No write access";
863 rStr
= "Read access granted without any security";
870 rStr
= "Proprietary";
878 PrintAndLogEx(NORMAL
, "");
879 PrintAndLogEx(INFO
, "--- " _CYAN_("NDEF Message"));
880 PrintAndLogEx(SUCCESS
, "Capability Container: %s", sprint_hex(data
, 4));
881 PrintAndLogEx(SUCCESS
, " %02X: NDEF Magic Number", data
[0]);
883 // PrintAndLogEx(SUCCESS, " %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0F);
884 PrintAndLogEx(SUCCESS
, " %02X: version %d.%d supported by tag", data
[1], cc_major
, cc_minor
);
885 PrintAndLogEx(SUCCESS
, " : %s / %s", rStr
, wStr
);
887 PrintAndLogEx(SUCCESS
, " %02X: Physical Memory Size: %d bytes", data
[2], data
[2] * 8);
889 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 48);
890 else if (data
[2] == 0x12)
891 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 144);
892 else if (data
[2] == 0x3E)
893 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 496);
894 else if (data
[2] == 0x6D)
895 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 872);
897 uint8_t msb3
= (data
[3] & 0xE0) >> 5;
898 uint8_t sf
= (data
[3] & 0x10) >> 4;
899 uint8_t lb
= (data
[3] & 0x08) >> 3;
900 uint8_t mlrule
= (data
[3] & 0x06) >> 1;
901 uint8_t mbread
= (data
[3] & 0x01);
903 PrintAndLogEx(SUCCESS
, " %02X: Additional feature information", data
[3]);
905 uint8_t bits
[8 + 1] = {0};
906 num_to_bytebits(data
[3], 8, bits
);
907 const char *bs
= sprint_bytebits_bin(bits
, 8);
909 PrintAndLogEx(SUCCESS
, " %s", bs
);
911 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 0, 3, "RFU"));
913 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_RED
, bs
, 8, 0, 3, "RFU"));
917 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 3, 1, "Support special frame"));
919 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 3, 1, "Don\'t support special frame"));
923 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 4, 1, "Support lock block"));
925 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 4, 1, "Don\'t support lock block"));
929 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 5, 2, "RFU"));
931 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_RED
, bs
, 8, 5, 2, "RFU"));
935 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 7, 1, "IC support multiple block reads"));
937 PrintAndLogEx(SUCCESS
, " %s", sprint_breakdown_bin(C_NONE
, bs
, 8, 7, 1, "IC don\'t support multiple block reads"));
942 int ul_print_type(uint64_t tagtype
, uint8_t spaces
) {
949 memset(typestr
, 0x00, sizeof(typestr
));
951 if (tagtype
& MFU_TT_UL
)
952 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)"), spaces
, "");
953 else if (tagtype
& MFU_TT_UL_C
)
954 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces
, "");
955 else if (tagtype
& MFU_TT_UL_NANO_40
)
956 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces
, "");
957 else if (tagtype
& MFU_TT_UL_EV1_48
)
958 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces
, "");
959 else if (tagtype
& MFU_TT_UL_EV1_128
)
960 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces
, "");
961 else if (tagtype
& MFU_TT_UL_EV1
)
962 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces
, "");
963 else if (tagtype
& MFU_TT_UL_AES
)
964 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight AES"), spaces
, "");
965 else if (tagtype
& MFU_TT_NTAG
)
966 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces
, "");
967 else if (tagtype
& MFU_TT_NTAG_203
)
968 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces
, "");
969 else if (tagtype
& MFU_TT_NTAG_210u
)
970 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 210u (micro) 48bytes (NT2L1001G0DU)"), spaces
, "");
971 else if (tagtype
& MFU_TT_NTAG_210
)
972 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces
, "");
973 else if (tagtype
& MFU_TT_NTAG_212
)
974 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces
, "");
975 else if (tagtype
& MFU_TT_NTAG_213
)
976 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces
, "");
977 else if (tagtype
& MFU_TT_NTAG_213_F
)
978 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces
, "");
979 else if (tagtype
& MFU_TT_NTAG_213_C
)
980 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces
, "");
981 else if (tagtype
& MFU_TT_NTAG_213_TT
)
982 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces
, "");
983 else if (tagtype
& MFU_TT_NTAG_215
)
984 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces
, "");
985 else if (tagtype
& MFU_TT_NTAG_216
)
986 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces
, "");
987 else if (tagtype
& MFU_TT_NTAG_216_F
)
988 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces
, "");
989 else if (tagtype
& MFU_TT_NTAG_I2C_1K
)
990 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces
, "");
991 else if (tagtype
& MFU_TT_NTAG_I2C_2K
)
992 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces
, "");
993 else if (tagtype
& MFU_TT_NTAG_I2C_1K_PLUS
)
994 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces
, "");
995 else if (tagtype
& MFU_TT_NTAG_I2C_2K_PLUS
)
996 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces
, "");
997 else if (tagtype
& MFU_TT_MY_D
)
998 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces
, "");
999 else if (tagtype
& MFU_TT_MY_D_NFC
)
1000 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces
, "");
1001 else if (tagtype
& MFU_TT_MY_D_MOVE
)
1002 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces
, "");
1003 else if (tagtype
& MFU_TT_MY_D_MOVE_NFC
)
1004 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces
, "");
1005 else if (tagtype
& MFU_TT_MY_D_MOVE_LEAN
)
1006 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces
, "");
1007 else if (tagtype
& MFU_TT_FUDAN_UL
)
1008 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces
, "");
1010 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("Unknown %06" PRIx64
), spaces
, "", tagtype
);
1014 bool ismagic
= ((tagtype
& MFU_TT_MAGIC
) == MFU_TT_MAGIC
);
1016 tagtype
&= ~(MFU_TT_MAGIC
);
1019 snprintf(typestr
+ strlen(typestr
), 4, " (");
1022 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", ((tagtype
& MFU_TT_MAGIC_1A
) == MFU_TT_MAGIC_1A
) ? _GREEN_("Gen 1a") : "");
1023 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", ((tagtype
& MFU_TT_MAGIC_1B
) == MFU_TT_MAGIC_1B
) ? _GREEN_("Gen 1b") : "");
1024 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", ((tagtype
& MFU_TT_MAGIC_2
) == MFU_TT_MAGIC_2
) ? _GREEN_("Gen 2 / CUID") : "");
1025 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", ((tagtype
& MFU_TT_MAGIC_4
) == MFU_TT_MAGIC_4
) ? _GREEN_("USCUID-UL") : "");
1026 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", ((tagtype
& MFU_TT_MAGIC_NTAG
) == MFU_TT_MAGIC_NTAG
) ? _GREEN_("NTAG CUID") : "");
1027 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", ((tagtype
& MFU_TT_MAGIC_NTAG21X
) == MFU_TT_MAGIC_NTAG21X
) ? _GREEN_("NTAG21x") : "");
1031 snprintf(typestr
+ strlen(typestr
), 4, " )");
1034 PrintAndLogEx(SUCCESS
, "%s", typestr
);
1038 static int ulc_print_3deskey(uint8_t *data
) {
1039 PrintAndLogEx(INFO
, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data
, 4), sprint_ascii(data
, 4));
1040 PrintAndLogEx(INFO
, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data
+ 4, 4), sprint_ascii(data
+ 4, 4));
1041 PrintAndLogEx(INFO
, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data
+ 8, 4), sprint_ascii(data
+ 8, 4));
1042 PrintAndLogEx(INFO
, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data
+ 12, 4), sprint_ascii(data
+ 12, 4));
1043 PrintAndLogEx(INFO
, "3des key: " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(data
, 16, 8), 16));
1047 // Only takes 16 bytes of data. Now key data available here
1048 static int ulc_print_configuration(uint8_t *data
) {
1050 PrintAndLogEx(NORMAL
, "");
1051 PrintAndLogEx(INFO
, "--- " _CYAN_("UL-C Configuration") " --------------------------");
1052 PrintAndLogEx(INFO
, "Total memory....... " _YELLOW_("%u") " bytes", MAX_ULC_BLOCKS
* 4);
1053 PrintAndLogEx(INFO
, "Available memory... " _YELLOW_("%u") " bytes", (MAX_ULC_BLOCKS
- 4) * 4);
1054 PrintAndLogEx(INFO
, "40 / 0x28 | %s - %s Higher lockbits", sprint_hex(data
, 4), sprint_bin(data
, 2));
1055 PrintAndLogEx(INFO
, "41 / 0x29 | %s - %s Counter", sprint_hex(data
+ 4, 4), sprint_bin(data
+ 4, 2));
1057 bool validAuth
= (data
[8] >= 0x03 && data
[8] < 0x30);
1059 PrintAndLogEx(INFO
, "42 / 0x2A | %s Auth0 Page " _YELLOW_("%d") "/" _YELLOW_("0x%02X") " and above need authentication"
1060 , sprint_hex(data
+ 8, 4)
1066 PrintAndLogEx(INFO
, "42 / 0x2A | %s Auth0 default", sprint_hex(data
+ 8, 4));
1067 } else if (data
[8] == 0x30) {
1068 PrintAndLogEx(INFO
, "42 / 0x2A | %s Auth0 " _GREEN_("unlocked"), sprint_hex(data
+ 8, 4));
1070 PrintAndLogEx(INFO
, "42 / 0x2A | %s Auth0 " _RED_("byte is out-of-range"), sprint_hex(data
+ 8, 4));
1074 PrintAndLogEx(INFO
, "43 / 0x2B | %s Auth1 %s",
1075 sprint_hex(data
+ 12, 4),
1076 (data
[12] & 1) ? "write access restricted" : _RED_("R/W access restricted")
1082 static int ulaes_print_configuration(uint8_t *data
, uint8_t start_page
) {
1084 PrintAndLogEx(NORMAL
, "");
1085 PrintAndLogEx(INFO
, "--- " _CYAN_("UL-AES Configuration") " --------------------------");
1087 bool rid_act
= (data
[0] & 1);
1088 bool sec_msg_act
= (data
[0] & 2);
1089 bool prot
= (data
[4] & 0x80);
1090 bool cfglck
= (data
[4] & 0x40);
1091 bool cnt_inc_en
= (data
[4] & 8);
1092 bool cnt_rd_en
= (data
[4] & 4);
1093 uint16_t authlim
= (data
[6]) | ((data
[7] & 0x3) << 8);
1095 PrintAndLogEx(INFO
, " cfg0 [%u/0x%02X]: %s", start_page
, start_page
, sprint_hex(data
, 4));
1097 PrintAndLogEx(INFO
, " - Random ID is %s", (rid_act
) ? "enabled" : "disabled");
1098 PrintAndLogEx(INFO
, " - Secure messaging is %s", (sec_msg_act
) ? "enabled" : "disabled");
1099 if (data
[3] < 0x3c) {
1100 PrintAndLogEx(INFO
, " - page %d and above need authentication", data
[3]);
1102 PrintAndLogEx(INFO
, " - pages don't need authentication");
1104 PrintAndLogEx(INFO
, " cfg1 [%u/0x%02X]: %s", start_page
+ 1, start_page
+ 1, sprint_hex(data
+ 4, 4));
1107 PrintAndLogEx(INFO
, " - " _GREEN_("Unlimited authentication attempts"));
1109 PrintAndLogEx(INFO
, " - Max number of authentication attempts is " _YELLOW_("%d"), authlim
);
1111 PrintAndLogEx(INFO
, " - %s access requires authentication", prot
? "Read and write" : "Write");
1112 PrintAndLogEx(INFO
, " - User configuration is %s", cfglck
? _RED_("locked") : "unlocked");
1113 PrintAndLogEx(INFO
, " - Counter 2 increment access %s authentication", cnt_inc_en
? "does not require" : "requires");
1114 PrintAndLogEx(INFO
, " - Counter 2 read access %s authentication", cnt_rd_en
? "does not require" : "requires");
1118 static int ulev1_print_configuration(uint64_t tagtype
, uint8_t *data
, uint8_t startPage
) {
1120 PrintAndLogEx(NORMAL
, "");
1121 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Configuration"));
1123 bool strg_mod_en
= (data
[0] & 2);
1125 uint8_t authlim
= (data
[4] & 0x07);
1126 bool nfc_cnf_prot_pwd
= ((data
[4] & 0x08) == 0x08);
1127 bool nfc_cnf_en
= ((data
[4] & 0x10) == 0x10);
1128 bool cfglck
= ((data
[4] & 0x40) == 0x40);
1129 bool prot
= ((data
[4] & 0x80) == 0x80);
1131 uint8_t vctid
= data
[5];
1133 PrintAndLogEx(INFO
, " cfg0 [%u/0x%02X]: %s", startPage
, startPage
, sprint_hex(data
, 4));
1135 //NTAG213TT has different ASCII mirroring options and config bytes interpretation from other ulev1 class tags
1136 if (tagtype
& MFU_TT_NTAG_213_TT
) {
1137 uint8_t mirror_conf
= ((data
[0] & 0xE0) >> 5);
1138 uint8_t mirror_byte
= ((data
[0] & 0x18) >> 3);
1139 uint8_t mirror_page
= data
[2];
1141 switch (mirror_conf
) {
1143 PrintAndLogEx(INFO
, " - no ASCII mirror");
1146 PrintAndLogEx(INFO
, " - UID ASCII mirror");
1149 PrintAndLogEx(INFO
, " - NFC counter ASCII mirror");
1152 PrintAndLogEx(INFO
, " - UID and NFC counter ASCII mirror");
1155 PrintAndLogEx(INFO
, " - tag tamper ASCII mirror");
1158 PrintAndLogEx(INFO
, " - UID and tag tamper ASCII mirror");
1161 PrintAndLogEx(INFO
, " - NFC counter and tag tamper ASCII mirror");
1164 PrintAndLogEx(INFO
, " - UID, NFC counter, and tag tamper ASCII mirror");
1171 uint8_t mirror_user_mem_start_byte
= (4 * (mirror_page
- 4)) + mirror_byte
;
1172 uint8_t bytes_required_for_mirror_data
= 0;
1174 switch (mirror_conf
) {
1176 bytes_required_for_mirror_data
= 14;
1179 bytes_required_for_mirror_data
= 6;
1182 bytes_required_for_mirror_data
= 8;
1185 bytes_required_for_mirror_data
= 21;
1188 bytes_required_for_mirror_data
= 23;
1191 bytes_required_for_mirror_data
= 15;
1194 bytes_required_for_mirror_data
= 30;
1199 PrintAndLogEx(INFO
, " mirror start page %02X | byte pos %02X - %s"
1200 , mirror_page
, mirror_byte
1201 , (mirror_page
>= 0x4 && ((mirror_user_mem_start_byte
+ bytes_required_for_mirror_data
) <= 144)) ? _GREEN_("ok") : _YELLOW_("Invalid value")
1205 } else if (tagtype
& (MFU_TT_NTAG_213_F
| MFU_TT_NTAG_216_F
)) {
1206 uint8_t mirror_conf
= ((data
[0] & 0xC0) >> 6);
1207 uint8_t mirror_byte
= (data
[0] & 0x30);
1208 bool sleep_en
= (data
[0] & 0x08);
1209 strg_mod_en
= (data
[0] & 0x04);
1210 uint8_t fdp_conf
= (data
[0] & 0x03);
1212 switch (mirror_conf
) {
1214 PrintAndLogEx(INFO
, " - no ASCII mirror");
1217 PrintAndLogEx(INFO
, " - UID ASCII mirror");
1220 PrintAndLogEx(INFO
, " - NFC counter ASCII mirror");
1223 PrintAndLogEx(INFO
, " - UID and NFC counter ASCII mirror");
1229 PrintAndLogEx(INFO
, " - SLEEP mode %s", (sleep_en
) ? "enabled" : "disabled");
1233 PrintAndLogEx(INFO
, " - no field detect");
1236 PrintAndLogEx(INFO
, " - enabled by first State-of-Frame (start of communication)");
1239 PrintAndLogEx(INFO
, " - enabled by selection of the tag");
1242 PrintAndLogEx(INFO
, " - enabled by field presence");
1247 // valid mirror start page and byte position within start page.
1248 if (tagtype
& MFU_TT_NTAG_213_F
) {
1249 switch (mirror_conf
) {
1251 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0x24) ? "OK" : "Invalid value"); break;}
1253 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0x26) ? "OK" : "Invalid value"); break;}
1255 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0x22) ? "OK" : "Invalid value"); break;}
1259 } else if (tagtype
& MFU_TT_NTAG_216_F
) {
1260 switch (mirror_conf
) {
1262 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0xDE) ? "OK" : "Invalid value"); break;}
1264 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0xE0) ? "OK" : "Invalid value"); break;}
1266 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0xDC) ? "OK" : "Invalid value"); break;}
1272 PrintAndLogEx(INFO
, " - strong modulation mode %s", (strg_mod_en
) ? "enabled" : "disabled");
1275 PrintAndLogEx(INFO
, " - page %d and above need authentication", data
[3]);
1277 PrintAndLogEx(INFO
, " - pages don't need authentication");
1279 uint8_t tt_enabled
= 0;
1280 uint8_t tt_message
[4] = {0x00};
1281 uint8_t tt_msg_resp_len
= 0;
1282 uint8_t tt_status_resp
[5] = {0x00};
1284 if (tagtype
& MFU_TT_NTAG_213_TT
) {
1285 tt_enabled
= (data
[1] & 0x02);
1286 tt_msg_resp_len
= ul_read(45, tt_message
, 4);
1288 PrintAndLogEx(INFO
, " - tamper detection feature is %s"
1289 , (tt_enabled
) ? _GREEN_("ENABLED") : "disabled"
1292 switch (data
[1] & 0x06) {
1294 PrintAndLogEx(INFO
, " - tamper message is unlocked and read/write enabled");
1297 PrintAndLogEx(INFO
, " - tamper message is reversibly read/write locked in memory while the tamper feature is enabled");
1301 PrintAndLogEx(INFO
, " - tamper message is permanently read/write locked in memory");
1308 PrintAndLogEx(INFO
, " cfg1 [%u/0x%02X]: %s", startPage
+ 1, startPage
+ 1, sprint_hex(data
+ 4, 4));
1310 PrintAndLogEx(INFO
, " - " _GREEN_("Unlimited password attempts"));
1312 PrintAndLogEx(INFO
, " - Max number of password attempts is " _YELLOW_("%d"), authlim
);
1314 PrintAndLogEx(INFO
, " - NFC counter %s", (nfc_cnf_en
) ? "enabled" : "disabled");
1315 PrintAndLogEx(INFO
, " - NFC counter %s", (nfc_cnf_prot_pwd
) ? "password protection enabled" : "not protected");
1317 PrintAndLogEx(INFO
, " - user configuration %s", cfglck
? "permanently locked" : "writeable");
1318 PrintAndLogEx(INFO
, " - %s access is protected with password", prot
? "read and write" : "write");
1319 PrintAndLogEx(INFO
, " - %02X, Virtual Card Type Identifier is %sdefault", vctid
, (vctid
== 0x05) ? "" : "not ");
1320 PrintAndLogEx(INFO
, " PWD [%u/0x%02X]: %s- ( cannot be read )", startPage
+ 2, startPage
+ 2, sprint_hex(data
+ 8, 4));
1321 PrintAndLogEx(INFO
, " PACK [%u/0x%02X]: %s - ( cannot be read )", startPage
+ 3, startPage
+ 3, sprint_hex(data
+ 12, 2));
1322 PrintAndLogEx(INFO
, " RFU [%u/0x%02X]: %s- ( cannot be read )", startPage
+ 3, startPage
+ 3, sprint_hex(data
+ 14, 2));
1324 if (tagtype
& MFU_TT_NTAG_213_TT
) {
1325 if (data
[1] & 0x06) {
1326 PrintAndLogEx(INFO
, "TT_MSG [45/0x2D]: %s- (cannot be read)", sprint_hex(tt_message
, tt_msg_resp_len
));
1327 PrintAndLogEx(INFO
, " - tamper message is masked in memory");
1329 PrintAndLogEx(INFO
, "TT_MSG [45/0x2D]: %s", sprint_hex(tt_message
, tt_msg_resp_len
));
1330 PrintAndLogEx(INFO
, " - tamper message is %s and is readable/writablbe in memory", sprint_hex(tt_message
, tt_msg_resp_len
));
1334 //The NTAG213TT only returns meaningful information for the fields below if the tamper feature is enabled
1335 if ((tagtype
& MFU_TT_NTAG_213_TT
) && tt_enabled
) {
1337 int tt_status_len
= ntagtt_getTamperStatus(tt_status_resp
, 5);
1338 if (tt_status_len
!= 5) {
1339 PrintAndLogEx(WARNING
, "Error sending the READ_TT_STATUS command to tag\n");
1343 PrintAndLogEx(NORMAL
, "");
1344 PrintAndLogEx(INFO
, "--- " _CYAN_("Tamper Status"));
1345 PrintAndLogEx(INFO
, " READ_TT_STATUS: %s", sprint_hex(tt_status_resp
, 5));
1347 PrintAndLogEx(INFO
, " Tamper status result from this power-up:");
1348 switch (tt_status_resp
[4]) {
1350 PrintAndLogEx(INFO
, " - Tamper loop was detcted as closed during this power-up");
1353 PrintAndLogEx(INFO
, " - Tamper loop was detected as open during this power-up");
1356 PrintAndLogEx(INFO
, " - Tamper loop measurement was not enabled or not valid during this power-up");
1362 PrintAndLogEx(INFO
, " Tamper detection permanent memory:");
1363 if ((tt_status_resp
[0] | tt_status_resp
[1] | tt_status_resp
[2] | tt_status_resp
[3]) == 0x00)
1365 PrintAndLogEx(INFO
, " - Tamper loop has never been detected as open during power-up");
1367 PrintAndLogEx(INFO
, " - Tamper loop was detected as open during power-up at least once");
1368 PrintAndLogEx(INFO
, " - Tamper message returned by READ_TT_STATUS command: %s", sprint_hex(tt_status_resp
, 4));
1374 static int ulev1_print_counters(void) {
1375 PrintAndLogEx(NORMAL
, "");
1376 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Counters"));
1377 uint8_t tear
[1] = {0};
1378 uint8_t counter
[3] = {0, 0, 0};
1380 for (uint8_t i
= 0; i
< 3; ++i
) {
1381 ulev1_readTearing(i
, tear
, sizeof(tear
));
1382 len
= ulev1_readCounter(i
, counter
, sizeof(counter
));
1384 PrintAndLogEx(INFO
, " [%0d]: %s", i
, sprint_hex(counter
, 3));
1385 PrintAndLogEx(SUCCESS
, " - %02X tearing ( %s )"
1387 , (tear
[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
1394 static int ulev1_print_signature(uint64_t tagtype
, uint8_t *uid
, uint8_t *signature
, size_t signature_len
) {
1396 #define PUBLIC_ECDA_KEYLEN 33
1397 #define PUBLIC_ECDA_192_KEYLEN 49
1398 // known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier)
1399 // ref: AN11350 NTAG 21x Originality Signature Validation
1400 // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
1401 const ecdsa_publickey_t nxp_mfu_public_keys
[] = {
1402 {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
1403 {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
1404 {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
1405 {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
1406 {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
1407 {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
1408 {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"},
1409 {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"},
1410 {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"},
1411 {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"},
1414 // https://www.nxp.com/docs/en/application-note/AN13452.pdf
1415 const ecdsa_publickey_t nxp_mfu_192_public_keys
[] = {
1416 {"NXP Ultralight AES", "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"},
1420 uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = {
1421 // UL, NTAG21x and NDEF
1423 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c,
1424 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49,
1425 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39,
1426 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61
1430 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b,
1431 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8,
1432 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72,
1433 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8
1435 // unknown. Needs identification
1437 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57,
1438 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35,
1439 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2,
1440 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF
1442 // unknown. Needs identification
1444 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE,
1445 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1,
1446 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA,
1447 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC
1449 // manufacturer public key
1451 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61,
1452 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C,
1453 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07,
1454 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2
1456 // MIKRON public key.
1458 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8,
1459 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07,
1460 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7,
1461 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
1466 bool is_valid
= false;
1467 if (signature_len
== 32) {
1468 for (i
= 0; i
< ARRAYLEN(nxp_mfu_public_keys
); i
++) {
1471 uint8_t key
[PUBLIC_ECDA_KEYLEN
] = {0};
1472 param_gethex_to_eol(nxp_mfu_public_keys
[i
].value
, 0, key
, PUBLIC_ECDA_KEYLEN
, &dl
);
1474 int res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1
, key
, uid
, 7, signature
, signature_len
, false);
1476 is_valid
= (res
== 0);
1482 bool is_192_valid
= false;
1483 if (signature_len
== 48) {
1484 for (i
= 0; i
< ARRAYLEN(nxp_mfu_192_public_keys
); i
++) {
1486 uint8_t key
[PUBLIC_ECDA_192_KEYLEN
] = {0};
1487 param_gethex_to_eol(nxp_mfu_192_public_keys
[i
].value
, 0, key
, PUBLIC_ECDA_192_KEYLEN
, &dl
);
1489 int res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP192R1
, key
, uid
, 7, signature
, signature_len
, false);
1491 is_192_valid
= (res
== 0);
1497 PrintAndLogEx(NORMAL
, "");
1498 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Signature"));
1500 PrintAndLogEx(INFO
, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_192_public_keys
[i
].desc
);
1501 PrintAndLogEx(INFO
, "IC signature public key value: %s", nxp_mfu_192_public_keys
[i
].value
);
1502 PrintAndLogEx(INFO
, " Elliptic curve parameters: NID_secp192r1");
1503 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, signature_len
));
1504 PrintAndLogEx(SUCCESS
, " Signature verification ( " _GREEN_("successful") " )");
1509 PrintAndLogEx(INFO
, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_public_keys
[i
].desc
);
1510 PrintAndLogEx(INFO
, "IC signature public key value: %s", nxp_mfu_public_keys
[i
].value
);
1511 PrintAndLogEx(INFO
, " Elliptic curve parameters: NID_secp128r1");
1512 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, signature_len
));
1513 PrintAndLogEx(SUCCESS
, " Signature verification ( " _GREEN_("successful") " )");
1517 PrintAndLogEx(INFO
, " Elliptic curve parameters: %s", (signature_len
== 48) ? "NID_secp192r1" : "NID_secp128r1");
1518 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, signature_len
));
1519 PrintAndLogEx(SUCCESS
, " Signature verification ( " _RED_("fail") " )");
1523 static int ulev1_print_version(uint8_t *data
) {
1524 PrintAndLogEx(NORMAL
, "");
1525 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Version"));
1526 PrintAndLogEx(INFO
, " Raw bytes: %s", sprint_hex(data
, 8));
1527 PrintAndLogEx(INFO
, " Vendor ID: %02X, %s", data
[1], getTagInfo(data
[1]));
1528 PrintAndLogEx(INFO
, " Product type: %s", getProductTypeStr(data
[2]));
1529 PrintAndLogEx(INFO
, " Product subtype: %02X, %s", data
[3], (data
[3] == 1) ? "17 pF" : "50pF");
1530 PrintAndLogEx(INFO
, " Major version: %02X", data
[4]);
1531 PrintAndLogEx(INFO
, " Minor version: %02X", data
[5]);
1532 PrintAndLogEx(INFO
, " Size: %s", getUlev1CardSizeStr(data
[6]));
1533 PrintAndLogEx(INFO
, " Protocol type: %02X%s", data
[7], (data
[7] == 0x3) ? ", ISO14443-3 Compliant" : "");
1537 static int ntag_print_counter(void) {
1538 // NTAG has one counter/tearing. At address 0x02.
1539 PrintAndLogEx(NORMAL
, "");
1540 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Counter"));
1541 uint8_t tear
[1] = {0};
1542 uint8_t counter
[3] = {0, 0, 0};
1544 len
= ulev1_readTearing(0x02, tear
, sizeof(tear
));
1546 len
= ulev1_readCounter(0x02, counter
, sizeof(counter
));
1548 PrintAndLogEx(INFO
, " [02]: %s", sprint_hex(counter
, 3));
1549 PrintAndLogEx(SUCCESS
, " - %02X tearing ( %s )"
1551 , (tear
[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
1557 static int ulc_magic_test(){
1558 // Magic Ultralight test
1559 // Magic UL-C, by observation,
1560 // 1) it seems to have a static nonce response to 0x1A command.
1561 // 2) the deskey bytes is not-zero:d out on as datasheet states.
1562 // 3) UID - changeable, not only, but pages 0-1-2-3.
1563 // 4) use the ul_magic_test ! magic tags answers specially!
1564 int returnValue = UL_ERROR;
1565 iso14a_card_select_t card;
1566 uint8_t nonce1[11] = {0x00};
1567 uint8_t nonce2[11] = {0x00};
1568 if ( !ul_select(&card) ){
1569 return MFU_TT_UL_ERROR;
1571 int status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
1572 if ( status <= 0 ) {
1573 status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
1574 returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? MFU_TT_UL_C_MAGIC : MFU_TT_UL_C;
1576 returnValue = MFU_TT_UL;
1582 static uint64_t ul_magic_test(void) {
1583 // Magic Ultralight tests
1584 // 1) take present UID, and try to write it back. OBSOLETE
1585 // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
1589 iso14a_card_select_t card
;
1590 if (ul_select_rats(&card
) == false) {
1591 return MFU_TT_UL_ERROR
;
1595 // iceman: how to proper identify RU based UID cards
1597 (memcmp(card.uid, "\xAA\x55\x39", 3) == 0) ||
1598 (memcmp(card.uid, "\xAA\x55\xC3", 3) == 0)
1600 // Ul-5 MFU Ev1 FUID,
1601 return MFU_TT_UL_EV1_MAGIC;
1604 PrintAndLogEx(DEBUG
, "%u - %s", card
.ats_len
, sprint_hex_inrow(card
.ats
, card
.ats_len
));
1607 if (card
.ats_len
== 18) {
1609 // USCUID-UL configuration
1610 // https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/magic_cards_notes.md#uscuid-ul-configuration-guide
1611 // identify: ATS len 18,
1612 // First 8 bytes can vary depending on setup. next 8 bytes is GET VERSION data and finally 2 byte crc
1614 // \x85\x00\x00\xA0\x0A\x00\x0A\xC3 \x00\x04\x03\x01\x01\x00\x0B\x03 \xZZ\xZZ
1616 // 7AFF - back door enabled
1618 // if we ignore first 8 bytes we can identify regardless how card is configured
1620 if (compare_ul_family(card
.ats
+ 8, 8)) {
1621 return MFU_TT_MAGIC_4
| MFU_TT_MAGIC
;
1625 // Direct write alternative cards
1626 if (card
.ats_len
== 14) {
1628 // UL-C Direct write
1629 if (memcmp(card
.ats
, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
1630 return MFU_TT_MAGIC_2
| MFU_TT_UL_C_MAGIC
;
1633 // NTAG 213 Direct write
1634 if (memcmp(card
.ats
, "\x0A\x78\x00\x81\x02\xDB\xA0\xC1\x19\x40\x2A\xB5", 12) == 0) {
1636 // iceman: should this be the same as NTAg21x?!?
1637 return MFU_TT_MAGIC_2
| MFU_TT_MAGIC_NTAG
;
1642 int status
= ul_comp_write(0, NULL
, 0);
1644 if (status
== PM3_SUCCESS
) {
1645 PrintAndLogEx(INFO
, "comp write pass");
1646 return MFU_TT_MAGIC_2
| MFU_TT_MAGIC
;
1649 // check for GEN1A, GEN1B and NTAG21x
1650 PacketResponseNG resp
;
1651 clearCommandBuffer();
1652 uint8_t payload
[] = { 0 };
1653 SendCommandNG(CMD_HF_MIFARE_CIDENT
, payload
, sizeof(payload
));
1655 uint16_t is_generation
= MAGIC_FLAG_NONE
;
1656 if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT
, &resp
, 1500)) {
1657 if ((resp
.status
== PM3_SUCCESS
) && resp
.length
== sizeof(uint16_t)) {
1658 is_generation
= resp
.data
.asDwords
[0] & 0xFFFF;
1662 if ((is_generation
& MAGIC_FLAG_GEN_1A
) == MAGIC_FLAG_GEN_1A
) {
1663 return MFU_TT_MAGIC_1A
| MFU_TT_MAGIC
;
1666 if ((is_generation
& MAGIC_FLAG_GEN_1B
) == MAGIC_FLAG_GEN_1B
) {
1667 return MFU_TT_MAGIC_1B
| MFU_TT_MAGIC
;
1669 if ((is_generation
& MAGIC_FLAG_NTAG21X
) == MAGIC_FLAG_NTAG21X
) {
1670 return MFU_TT_MAGIC_NTAG21X
| MFU_TT_MAGIC
;
1673 return MFU_TT_UNKNOWN
;
1676 static char *mfu_generate_filename(const char *prefix
, const char *suffix
) {
1677 iso14a_card_select_t card
;
1678 if (ul_select(&card
) == false) {
1679 PrintAndLogEx(WARNING
, "No tag found.");
1683 char *fptr
= calloc(sizeof(char) * (strlen(prefix
) + strlen(suffix
)) + sizeof(card
.uid
) * 2 + 1, sizeof(uint8_t));
1684 strcpy(fptr
, prefix
);
1685 FillFileNameByUID(fptr
, card
.uid
, suffix
, card
.uidlen
);
1689 // used with the Amiibo dumps loading...
1690 // Not related to 'hf mfu dump'
1691 static int mfu_dump_tag(uint16_t pages
, void **pdata
, uint16_t *len
) {
1694 iso14a_card_select_t card
;
1695 if (ul_select(&card
) == false) {
1696 return PM3_ECARDEXCHANGE
;
1699 int res
= PM3_SUCCESS
;
1700 uint16_t maxbytes
= (pages
* MFU_BLOCK_SIZE
);
1702 *pdata
= calloc(maxbytes
, sizeof(uint8_t));
1703 if (*pdata
== NULL
) {
1704 PrintAndLogEx(FAILED
, "error, cannot allocate memory");
1710 uint8_t keytype
= 2;
1712 uint8_t key
[4] = {0};
1713 num_to_bytes(ul_ev1_pwdgenB(card
.uid
), 4, key
);
1715 clearCommandBuffer();
1716 SendCommandMIX(CMD_HF_MIFAREU_READCARD
, 0, pages
, keytype
, key
, 4);
1717 PacketResponseNG resp
;
1718 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
1719 PrintAndLogEx(WARNING
, "Command execute timeout");
1725 if (resp
.oldarg
[0] != 1) {
1726 PrintAndLogEx(WARNING
, "Failed reading card");
1733 uint32_t startindex
= resp
.oldarg
[2];
1734 uint32_t buffer_size
= resp
.oldarg
[1];
1735 if (buffer_size
> maxbytes
) {
1736 PrintAndLogEx(FAILED
, "Data exceeded buffer size!");
1737 buffer_size
= maxbytes
;
1740 if (GetFromDevice(BIG_BUF
, *pdata
, buffer_size
, startindex
, NULL
, 0, NULL
, 2500, false) == false) {
1741 PrintAndLogEx(WARNING
, "command execution time out");
1757 Version: 00 04 04 02 01 00 0F 03
1761 E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E
1769 uint32_t (*otp
)(const uint8_t *uid
);
1771 } mfu_otp_identify_t
;
1773 static mfu_otp_identify_t mfu_otp_ident_table
[] = {
1774 { "SALTO Systems card", 12, 4, "534C544F", ul_c_otpgenA
, NULL
},
1775 { NULL
, 0, 0, NULL
, NULL
, NULL
}
1778 static mfu_otp_identify_t
*mfu_match_otp_fingerprint(uint8_t *uid
, uint8_t *data
) {
1782 uint8_t mtmp
[40] = {0};
1784 // static or dynamic created OTP to fingerprint.
1785 if (mfu_otp_ident_table
[i
].match
) {
1786 param_gethex_to_eol(mfu_otp_ident_table
[i
].match
, 0, mtmp
, sizeof(mtmp
), &ml
);
1788 uint32_t otp
= mfu_otp_ident_table
[i
].otp(uid
);
1789 num_to_bytes(otp
, 4, mtmp
);
1792 int min
= MIN(mfu_otp_ident_table
[i
].mlen
, 4);
1794 PrintAndLogEx(DEBUG
, "uid.... %s", sprint_hex_inrow(uid
, 7));
1795 PrintAndLogEx(DEBUG
, "calc... %s", sprint_hex_inrow(mtmp
, 4));
1796 PrintAndLogEx(DEBUG
, "dump... %s", sprint_hex_inrow(data
+ mfu_otp_ident_table
[i
].mpos
, min
));
1798 bool m2
= (memcmp(mtmp
, data
+ mfu_otp_ident_table
[i
].mpos
, min
) == 0);
1800 PrintAndLogEx(DEBUG
, "(fingerprint) found %s", mfu_otp_ident_table
[i
].desc
);
1801 return &mfu_otp_ident_table
[i
];
1803 } while (mfu_otp_ident_table
[++i
].desc
);
1809 const char *version
;
1813 uint32_t (*Pwd
)(const uint8_t *uid
);
1814 uint16_t (*Pack
)(const uint8_t *uid
);
1818 static mfu_identify_t mfu_ident_table
[] = {
1820 "Jooki", "0004040201000F03",
1821 12, 32, "E11012000103A00C340329D101255504732E6A6F6F6B692E726F636B732F732F",
1822 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1826 "Lego Dimensions", "0004040201000F03",
1827 12, 18, "E11012000103A00C340313D1010F5402656E",
1828 ul_ev1_pwdgenC
, ul_ev1_packgenC
,
1829 "hf mfu dump -k %08x"
1832 "Hotwheels", "0004040201000F03",
1834 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1835 "hf mfu dump -k %08x"
1838 "Minecraft Earth", "0004040201000F03",
1839 9, 26, "48F6FFE1101200037C91012C55027069642E6D617474656C2F4167",
1840 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1841 "hf mfu dump -k %08x"
1844 "Snackworld", "0004040101000B03",
1845 9, 7, "483000E1100600",
1850 "Amiibo", "0004040201001103",
1851 9, 9, "480FE0F110FFEEA500",
1852 ul_ev1_pwdgenB
, ul_ev1_packgenB
,
1853 "hf mfu dump -k %08x"
1856 "Amiibo - Power Up band", "0004040502021303",
1857 8, 10, "44000FE0F110FFEEA500",
1858 ul_ev1_pwdgenB
, ul_ev1_packgenB
,
1859 "hf mfu dump -k %08x"
1863 "Xiaomi AIR Purifier", "0004040201000F03",
1865 ul_ev1_pwdgenE, ul_ev1_packgenE,
1866 "hf mfu dump -k %08x"
1870 "Philips Toothbrush", "0004040201010F03",
1871 16, 20, "0310D1010C55027068696C6970732E636F6DFE00",
1872 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1876 "Philips Toothbrush", "0004040201010F03",
1877 16, 36, "0320D1011C55027068696C6970732E636F6D2F6E6663627275736868656164746170FE00",
1878 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1882 "Bank Of Archie brothers", "0004030101000B03",
1883 9, 11, "48F6FF0000000036343533",
1884 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1888 "Art-Dass NFT card", "0004040201000F03",
1889 16, 16, "033ED1013A5504617274646173732E6E",
1890 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1894 "Bonverde Coffe card", "0004030101000B03",
1896 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1899 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
}
1902 static mfu_identify_t
*mfu_match_fingerprint(uint8_t *version
, uint8_t *data
) {
1907 uint8_t vtmp
[10] = {0};
1908 param_gethex_to_eol(mfu_ident_table
[i
].version
, 0, vtmp
, sizeof(vtmp
), &vl
);
1910 bool m1
= (memcmp(vtmp
, version
, vl
) == 0);
1912 PrintAndLogEx(DEBUG
, "(fingerprint) wrong version");
1917 uint8_t mtmp
[40] = {0};
1918 param_gethex_to_eol(mfu_ident_table
[i
].match
, 0, mtmp
, sizeof(mtmp
), &ml
);
1920 bool m2
= (memcmp(mtmp
, data
+ mfu_ident_table
[i
].mpos
, mfu_ident_table
[i
].mlen
) == 0);
1922 PrintAndLogEx(DEBUG
, "(fingerprint) found %s", mfu_ident_table
[i
].desc
);
1923 return &mfu_ident_table
[i
];
1925 } while (mfu_ident_table
[++i
].desc
);
1929 static uint8_t mfu_max_len(void) {
1930 uint8_t n
= 0, i
= 0;
1932 uint8_t tmp
= mfu_ident_table
[i
].mpos
+ mfu_ident_table
[i
].mlen
;
1936 } while (mfu_ident_table
[++i
].desc
);
1940 static int mfu_get_version_uid(uint8_t *version
, uint8_t *uid
) {
1941 iso14a_card_select_t card
;
1942 if (ul_select(&card
) == false) {
1945 memcpy(uid
, card
.uid
, card
.uidlen
);
1947 uint8_t v
[10] = {0x00};
1948 int len
= ulev1_getVersion(v
, sizeof(v
));
1950 if (len
!= sizeof(v
)) {
1954 memcpy(version
, v
, 8);
1958 static int mfu_fingerprint(uint64_t tagtype
, bool hasAuthKey
, uint8_t *authkey
, int ak_len
) {
1960 uint8_t dbg_curr
= DBG_NONE
;
1961 uint8_t *data
= NULL
;
1962 int res
= PM3_ESOFT
;
1963 PrintAndLogEx(INFO
, "");
1964 PrintAndLogEx(INFO
, "--- " _CYAN_("Fingerprint"));
1965 uint8_t maxbytes
= mfu_max_len();
1966 if (maxbytes
== 0) {
1967 PrintAndLogEx(ERR
, "fingerprint table wrong");
1972 maxbytes
= ((maxbytes
/ MFU_BLOCK_SIZE
) + 1) * MFU_BLOCK_SIZE
;
1973 data
= calloc(maxbytes
, sizeof(uint8_t));
1975 PrintAndLogEx(ERR
, "failed to allocate memory");
1980 uint8_t pages
= (maxbytes
/ MFU_BLOCK_SIZE
);
1981 uint8_t keytype
= 0;
1984 if (tagtype
& MFU_TT_UL_C
)
1985 keytype
= 1; // UL_C auth
1987 keytype
= 2; // UL_EV1/NTAG auth
1990 if (getDeviceDebugLevel(&dbg_curr
) != PM3_SUCCESS
) {
1995 if (setDeviceDebugLevel(DBG_NONE
, false) != PM3_SUCCESS
) {
2000 clearCommandBuffer();
2001 SendCommandMIX(CMD_HF_MIFAREU_READCARD
, 0, pages
, keytype
, authkey
, ak_len
);
2002 PacketResponseNG resp
;
2003 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
2004 PrintAndLogEx(WARNING
, "Command execute timeout");
2009 if (resp
.oldarg
[0] != 1) {
2010 PrintAndLogEx(WARNING
, "Failed reading card");
2016 uint32_t startindex
= resp
.oldarg
[2];
2017 uint32_t buffer_size
= resp
.oldarg
[1];
2019 if (buffer_size
> maxbytes
) {
2020 PrintAndLogEx(FAILED
, "Data exceeded buffer size!");
2021 buffer_size
= maxbytes
;
2024 if (GetFromDevice(BIG_BUF
, data
, buffer_size
, startindex
, NULL
, 0, NULL
, 2500, false) == false) {
2025 PrintAndLogEx(WARNING
, "command execution time out");
2030 uint8_t version
[8] = {0};
2031 uint8_t uid
[7] = {0};
2032 if (mfu_get_version_uid(version
, uid
) == PM3_SUCCESS
) {
2033 mfu_identify_t
*item
= mfu_match_fingerprint(version
, data
);
2035 PrintAndLogEx(SUCCESS
, _GREEN_("%s"), item
->desc
);
2041 snprintf(s
, sizeof(s
), item
->hint
, item
->Pwd(uid
));
2042 PrintAndLogEx(HINT
, "Use `" _YELLOW_("%s") "`", s
);
2044 PrintAndLogEx(HINT
, "Use `" _YELLOW_("%s") "`", item
->hint
);
2051 mfu_otp_identify_t
*item
= mfu_match_otp_fingerprint(uid
, data
);
2053 PrintAndLogEx(SUCCESS
, _GREEN_("%s"), item
->desc
);
2059 snprintf(s
, sizeof(s
), item
->hint
, item
->otp(uid
));
2060 PrintAndLogEx(HINT
, "Use `" _YELLOW_("%s") "`", s
);
2062 PrintAndLogEx(HINT
, "Use `" _YELLOW_("%s") "`", item
->hint
);
2069 if (res
!= PM3_SUCCESS
) {
2070 PrintAndLogEx(INFO
, "n/a");
2073 setDeviceDebugLevel(dbg_curr
, false);
2078 static int mfu_write_block(uint8_t *data
, uint8_t datalen
, bool has_auth_key
, bool has_pwd
, uint8_t *auth_key_ptr
, uint8_t blockno
) {
2082 memcpy(cmd
, data
, datalen
);
2084 // 0 - no pwd/key, no authentication
2085 // 1 - 3des key (16 bytes)
2086 // 2 - pwd (4 bytes)
2087 uint8_t keytype
= 0;
2088 size_t cmdlen
= datalen
;
2091 memcpy(cmd
+ datalen
, auth_key_ptr
, 16);
2093 } else if (has_pwd
) {
2095 memcpy(cmd
+ datalen
, auth_key_ptr
, 4);
2099 clearCommandBuffer();
2100 if (datalen
== 16) {
2101 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT
, blockno
, keytype
, 0, cmd
, cmdlen
);
2103 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, blockno
, keytype
, 0, cmd
, cmdlen
);
2105 PacketResponseNG resp
;
2106 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
2107 return PM3_ETIMEOUT
;
2110 uint8_t isOK
= resp
.oldarg
[0] & 0xFF;
2117 uint64_t GetHF14AMfU_Type(void) {
2119 uint64_t tagtype
= MFU_TT_UNKNOWN
;
2120 iso14a_card_select_t card
;
2122 if (ul_select(&card
) == false)
2123 return MFU_TT_UL_ERROR
;
2125 // Ultralight - ATQA / SAK
2126 if (card
.atqa
[1] != 0x00 || card
.atqa
[0] != 0x44 || card
.sak
!= 0x00) {
2127 //PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
2129 return MFU_TT_UL_ERROR
;
2132 if (card
.uid
[0] != 0x05) {
2134 uint8_t version
[10] = {0x00};
2135 int len
= ulev1_getVersion(version
, sizeof(version
));
2141 MF0UL1001DUx 0004030100000B03
2142 MF0UL1101DUx 0004030101000B03
2143 MF0ULH1101DUx 0004030201000B03
2144 MF0UL1141DUF 0004030301000B03
2145 MF0UL2101Dxy 0004030101000E03
2146 MF0UL2101DUx 0004030201000E03
2147 MF0UL3101DUx 0004030101001103
2148 MF0ULH3101DUx 0004030201001103
2149 MF0UL5101DUx 0004030101001303
2150 NT2L1011F0DUx 0004040101000B03
2151 NT2H1011G0DUD 0004040201000B03
2152 NT2L1211F0DUx 0004040101000E03
2153 NT2H1311G0DUx 0004040201000F03
2154 NT2H1311F0Dxy 0004040401000F03
2155 NT2H1411G0DUx 0004040201011103
2156 NT2H1511G0DUx 0004040201001103
2157 NT2H1511F0Dxy 0004040401001103
2158 NT2H1611G0DUx 0004040201001303
2159 NT2H1611F0Dxy 0004040401001303
2160 NT2H1311C1DTL 0004040201010F03
2161 NT2H1311TTDUx 0004040203000F03
2162 NT3H1101W0FHK 0004040502001303
2163 NT3H1201W0FHK 0004040502001503
2164 NT3H1101W0FHK_Variant 0004040502011303
2165 NT3H1201 0004040502011503
2166 NT3H2111 0004040502021303
2167 NT3H2211 0004040502021503
2168 nhs 0004040600001303
2169 MF0UN0001DUx 0004030102000B03
2170 MF0UNH0001DUx 0004030202000B03
2171 MF0UN1001DUx 0004030103000B03
2172 MF0UNH1001DUx 0004030203000B03
2173 NT2L1001G0DUx 0004040102000B03
2174 NT2H1001G0DUx 0004040202000B03
2175 NT2H1311TTDUx 0004040203000F03
2176 Micron UL 0034210101000E03
2177 Feiju NTAG 0053040201000F03
2178 MF0AES2001DUD 0004030104000F03
2181 if (memcmp(version
, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { tagtype
= MFU_TT_UL_EV1_48
; break; }
2182 else if (memcmp(version
, "\x00\x04\x03\x01\x02\x00\x0B", 7) == 0) { tagtype
= MFU_TT_UL_NANO_40
; break; }
2183 else if (memcmp(version
, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { tagtype
= MFU_TT_UL_EV1_48
; break; }
2184 else if (memcmp(version
, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { tagtype
= MFU_TT_UL_EV1_128
; break; }
2185 else if (memcmp(version
, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { tagtype
= MFU_TT_UL_EV1_128
; break; }
2186 else if (memcmp(version
, "\x00\x04\x03\x01\x04\x00\x0F\x03", 8) == 0) { tagtype
= MFU_TT_UL_AES
; break; }
2187 else if (memcmp(version
, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { tagtype
= MFU_TT_UL_EV1_128
; break; } // Mikron JSC Russia EV1 41 pages tag
2188 else if (memcmp(version
, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype
= MFU_TT_NTAG_210
; break; }
2189 else if (memcmp(version
, "\x00\x04\x04\x01\x02\x00\x0B", 7) == 0) { tagtype
= MFU_TT_NTAG_210u
; break; }
2190 else if (memcmp(version
, "\x00\x04\x04\x02\x02\x00\x0B", 7) == 0) { tagtype
= MFU_TT_NTAG_210u
; break; }
2191 else if (memcmp(version
, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype
= MFU_TT_NTAG_212
; break; }
2192 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype
= MFU_TT_NTAG_213
; break; }
2193 else if (memcmp(version
, "\x00\x53\x04\x02\x01\x00\x0F", 7) == 0) { tagtype
= MFU_TT_NTAG_213
; break; } // Shanghai Feiju Microelectronics Co. Ltd. China (Xiaomi Air Purifier filter)
2194 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x01\x0F", 7) == 0) { tagtype
= MFU_TT_NTAG_213_C
; break; }
2195 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x00\x11", 7) == 0) { tagtype
= MFU_TT_NTAG_215
; break; }
2196 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x00\x13", 7) == 0) { tagtype
= MFU_TT_NTAG_216
; break; }
2197 else if (memcmp(version
, "\x00\x04\x04\x04\x01\x00\x0F", 7) == 0) { tagtype
= MFU_TT_NTAG_213_F
; break; }
2198 else if (memcmp(version
, "\x00\x04\x04\x04\x01\x00\x13", 7) == 0) { tagtype
= MFU_TT_NTAG_216_F
; break; }
2199 else if (memcmp(version
, "\x00\x04\x04\x02\x03\x00\x0F", 7) == 0) { tagtype
= MFU_TT_NTAG_213_TT
; break; }
2200 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x01\x13", 7) == 0) { tagtype
= MFU_TT_NTAG_I2C_1K
; break; }
2201 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype
= MFU_TT_NTAG_I2C_2K
; break; }
2202 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype
= MFU_TT_NTAG_I2C_1K_PLUS
; break; }
2203 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x02\x15", 7) == 0) { tagtype
= MFU_TT_NTAG_I2C_2K_PLUS
; break; }
2204 else if (version
[2] == 0x04) { tagtype
= MFU_TT_NTAG
; break; }
2205 else if (version
[2] == 0x03) { tagtype
= MFU_TT_UL_EV1
; }
2209 tagtype
= MFU_TT_UL_C
;
2212 tagtype
= MFU_TT_UL
;
2215 case PM3_EWRONGANSWER
:
2216 tagtype
= (MFU_TT_UL
| MFU_TT_UL_C
| MFU_TT_NTAG_203
);
2217 break; // could be UL | UL_C magic tags
2219 tagtype
= MFU_TT_UNKNOWN
;
2223 // UL vs UL-C vs ntag203 test
2224 if (tagtype
& (MFU_TT_UL
| MFU_TT_UL_C
| MFU_TT_NTAG_203
)) {
2225 if (ul_select(&card
) == false) {
2226 return MFU_TT_UL_ERROR
;
2229 // do UL_C check first...
2230 uint8_t nonce
[11] = {0x00};
2231 int status
= ulc_requestAuthentication(nonce
, sizeof(nonce
));
2234 tagtype
= MFU_TT_UL_C
;
2236 // need to re-select after authentication error
2237 if (ul_select(&card
) == false) {
2238 return MFU_TT_UL_ERROR
;
2241 uint8_t data
[16] = {0x00};
2242 // read page 0x26-0x29 (last valid ntag203 page)
2243 status
= ul_read(0x26, data
, sizeof(data
));
2245 tagtype
= MFU_TT_UL
;
2247 // read page 0x30 (should error if it is a ntag203)
2248 status
= ul_read(0x30, data
, sizeof(data
));
2250 tagtype
= MFU_TT_NTAG_203
;
2252 tagtype
= MFU_TT_UNKNOWN
;
2258 if (tagtype
& MFU_TT_UL
) {
2259 tagtype
= ul_fudan_check();
2264 // Infinition MY-D tests Exam high nibble
2265 uint8_t nib
= (card
.uid
[1] & 0xf0) >> 4;
2267 // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
2269 tagtype
= MFU_TT_MY_D
;
2270 break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
2272 tagtype
= MFU_TT_MY_D_NFC
;
2273 break; // or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
2275 tagtype
= (MFU_TT_MY_D_MOVE
| MFU_TT_MY_D_MOVE_NFC
);
2276 break; // or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
2278 tagtype
= MFU_TT_MY_D_MOVE_LEAN
;
2279 break; // or SLE 66R01L // 16 pages of 4 bytes
2283 tagtype
|= ul_magic_test();
2284 if (tagtype
== (MFU_TT_UNKNOWN
| MFU_TT_MAGIC
)) {
2285 tagtype
= (MFU_TT_UL_MAGIC
);
2291 // extended tag information
2293 static int CmdHF14AMfUInfo(const char *Cmd
) {
2295 CLIParserContext
*ctx
;
2296 CLIParserInit(&ctx
, "hf mfu info",
2297 "Get info about MIFARE Ultralight Family styled tag.\n"
2298 "Sometimes the tags are locked down, and you may need a key to be able to read the information",
2300 "hf mfu info -k AABBCCDD\n"
2301 "hf mfu info --key 00112233445566778899AABBCCDDEEFF"
2304 void *argtable
[] = {
2306 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2307 arg_lit0("l", NULL
, "Swap entered key's endianness"),
2308 // arg_lit0("v", "verbose", "verbose output"),
2309 arg_lit0(NULL
, "force", "override `hw dbg` settings"),
2312 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2315 uint8_t authenticationkey
[16] = {0x00};
2316 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
2317 bool swap_endian
= arg_get_lit(ctx
, 2);
2318 // bool verbose = arg_get_lit(ctx, 3);
2319 bool override
= (arg_get_lit(ctx
, 3) == false);
2323 if (ak_len
!= 16 && ak_len
!= 4) {
2324 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
2329 bool has_auth_key
= false;
2331 has_auth_key
= true;
2333 uint8_t authlim
= 0xff;
2334 uint8_t data
[16] = {0x00};
2335 iso14a_card_select_t card
;
2337 uint8_t *authkeyptr
= authenticationkey
;
2338 uint8_t pwd
[4] = {0, 0, 0, 0};
2340 uint8_t pack
[4] = {0, 0, 0, 0};
2343 uint64_t tagtype
= GetHF14AMfU_Type();
2344 if (tagtype
== MFU_TT_UL_ERROR
) {
2348 PrintAndLogEx(NORMAL
, "");
2349 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " --------------------------");
2350 ul_print_type(tagtype
, 6);
2353 if (swap_endian
&& has_auth_key
) {
2354 authkeyptr
= SwapEndian64(authenticationkey
, ak_len
, (ak_len
== 16) ? 8 : 4);
2357 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2361 bool locked
= false;
2362 // read pages 0,1,2,3 (should read 4 pages)
2363 status
= ul_read(0, data
, sizeof(data
));
2366 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ");
2368 } else if (status
== 16) {
2369 ul_print_default(data
, card
.uid
);
2370 ndef_print_CC(data
+ 12);
2376 if ((tagtype
& MFU_TT_UL_C
)) {
2378 // read pages 0x28, 0x29, 0x2A, 0x2B
2379 uint8_t ulc_conf
[16] = {0x00};
2380 status
= ul_read(0x28, ulc_conf
, sizeof(ulc_conf
));
2382 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ UL-C");
2388 ulc_print_configuration(ulc_conf
);
2393 mfu_fingerprint(tagtype
, has_auth_key
, authkeyptr
, ak_len
);
2397 if ((tagtype
& MFU_TT_MAGIC
) == MFU_TT_MAGIC
) {
2399 uint8_t ulc_deskey
[16] = {0x00};
2400 status
= ul_read(0x2C, ulc_deskey
, sizeof(ulc_deskey
));
2403 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ magic");
2408 ulc_print_3deskey(ulc_deskey
);
2411 PrintAndLogEx(NORMAL
, "");
2415 // if we called info with key, just return
2417 PrintAndLogEx(NORMAL
, "");
2421 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
2422 if (try_default_3des_keys(override
, &key
) == PM3_SUCCESS
) {
2423 PrintAndLogEx(SUCCESS
, "Found default 3des key: ");
2424 uint8_t keySwap
[16];
2425 memcpy(keySwap
, SwapEndian64(key
, 16, 8), 16);
2426 ulc_print_3deskey(keySwap
);
2428 PrintAndLogEx(INFO
, "n/a");
2431 PrintAndLogEx(NORMAL
, "");
2437 if (tagtype
& MFU_TT_UL_AES
) {
2439 // read pages 0x28, 0x29, 0x2A, 0x2B
2440 uint8_t ulaes_conf
[16] = {0x00};
2441 status
= ul_read(0x29, ulaes_conf
, sizeof(ulaes_conf
));
2443 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ UL-AES");
2449 ulaes_print_configuration(ulaes_conf
, 0x29);
2456 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
2457 if (try_default_aes_keys(override
) != PM3_SUCCESS
) {
2458 PrintAndLogEx(INFO
, "n/a");
2462 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2467 // do counters and signature first (don't neet auth)
2469 // ul counters are different than ntag counters
2470 if ((tagtype
& (MFU_TT_UL_EV1_48
| MFU_TT_UL_EV1_128
| MFU_TT_UL_EV1
))) {
2471 if (ulev1_print_counters() != 3) {
2472 // failed - re-select
2473 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2480 if ((tagtype
& (MFU_TT_NTAG_213
| MFU_TT_NTAG_213_F
| MFU_TT_NTAG_213_C
| MFU_TT_NTAG_213_TT
| MFU_TT_NTAG_215
| MFU_TT_NTAG_216
))) {
2481 if (ntag_print_counter()) {
2482 // failed - re-select
2483 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2490 if ((tagtype
& (MFU_TT_UL_EV1_48
| MFU_TT_UL_EV1_128
| MFU_TT_UL_EV1
| MFU_TT_UL_NANO_40
|
2491 MFU_TT_NTAG_210u
| MFU_TT_NTAG_213
| MFU_TT_NTAG_213_F
| MFU_TT_NTAG_213_C
|
2492 MFU_TT_NTAG_213_TT
| MFU_TT_NTAG_215
| MFU_TT_NTAG_216
| MFU_TT_NTAG_216_F
|
2493 MFU_TT_NTAG_I2C_1K
| MFU_TT_NTAG_I2C_2K
| MFU_TT_NTAG_I2C_1K_PLUS
| MFU_TT_NTAG_I2C_2K_PLUS
|
2495 uint8_t ulev1_signature
[48] = {0x00};
2496 status
= ulev1_readSignature(ulev1_signature
, sizeof(ulev1_signature
));
2498 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ SIGNATURE");
2502 if (status
== 32 || status
== 34) {
2503 ulev1_print_signature(tagtype
, card
.uid
, ulev1_signature
, 32);
2504 } else if (status
== 48) {
2505 ulev1_print_signature(tagtype
, card
.uid
, ulev1_signature
, 48);
2508 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2513 // print silicon info
2514 ul_print_nxp_silicon_info(card
.uid
);
2517 uint8_t version
[10] = {0x00};
2518 status
= ulev1_getVersion(version
, sizeof(version
));
2520 PrintAndLogEx(ERR
, "Error: tag didn't answer to GETVERSION");
2523 } else if (status
== 10) {
2524 ulev1_print_version(version
);
2527 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2532 // Don't check config / passwords for Ul AES :)
2533 if (tagtype
== MFU_TT_UL_AES
) {
2537 uint8_t startconfigblock
= 0;
2538 uint8_t ulev1_conf
[16] = {0x00};
2540 for (uint8_t i
= 1; i
< ARRAYLEN(UL_TYPES_ARRAY
); i
++) {
2541 if ((tagtype
& UL_TYPES_ARRAY
[i
]) == UL_TYPES_ARRAY
[i
]) {
2542 startconfigblock
= UL_MEMORY_ARRAY
[i
] - 3;
2547 if (startconfigblock
) { // if we know where the config block is...
2548 status
= ul_read(startconfigblock
, ulev1_conf
, sizeof(ulev1_conf
));
2550 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ EV1");
2553 } else if (status
== 16) {
2554 // save AUTHENTICATION LIMITS for later:
2555 authlim
= (ulev1_conf
[4] & 0x07);
2556 // add pwd / pack if used from cli
2558 memcpy(ulev1_conf
+ 8, authkeyptr
, 4);
2559 memcpy(ulev1_conf
+ 12, pack
, 2);
2561 ulev1_print_configuration(tagtype
, ulev1_conf
, startconfigblock
);
2565 // AUTHLIMIT, (number of failed authentications)
2567 // 1-7 = limit. No automatic tries then.
2568 // hasAuthKey, if we was called with key, skip test.
2569 if (!authlim
&& (has_auth_key
== false)) {
2570 PrintAndLogEx(NORMAL
, "");
2571 PrintAndLogEx(SUCCESS
, "--- " _CYAN_("Known EV1/NTAG passwords"));
2574 num_to_bytes(ul_ev1_pwdgenA(card
.uid
), 4, key
);
2575 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
2577 has_auth_key
= true;
2579 memcpy(authenticationkey
, key
, 4);
2580 PrintAndLogEx(SUCCESS
, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key
, 4), pack
[0], pack
[1]);
2584 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2589 num_to_bytes(ul_ev1_pwdgenB(card
.uid
), 4, key
);
2590 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
2592 has_auth_key
= true;
2594 memcpy(authenticationkey
, key
, 4);
2595 PrintAndLogEx(SUCCESS
, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key
, 4), pack
[0], pack
[1]);
2599 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2604 num_to_bytes(ul_ev1_pwdgenC(card
.uid
), 4, key
);
2605 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
2607 has_auth_key
= true;
2609 memcpy(authenticationkey
, key
, 4);
2610 PrintAndLogEx(SUCCESS
, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key
, 4), pack
[0], pack
[1]);
2614 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2619 num_to_bytes(ul_ev1_pwdgenD(card
.uid
), 4, key
);
2620 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
2622 has_auth_key
= true;
2624 memcpy(authenticationkey
, key
, 4);
2625 PrintAndLogEx(SUCCESS
, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key
, 4), pack
[0], pack
[1]);
2629 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2633 for (uint8_t i
= 0; i
< ARRAYLEN(default_pwd_pack
); ++i
) {
2634 key
= default_pwd_pack
[i
];
2635 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
2637 has_auth_key
= true;
2639 memcpy(authenticationkey
, key
, 4);
2640 PrintAndLogEx(SUCCESS
, "Password... " _GREEN_("%s") " pack... " _GREEN_("%02X%02X"), sprint_hex_inrow(key
, 4), pack
[0], pack
[1]);
2643 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
2649 PrintAndLogEx(WARNING
, _YELLOW_("password not known"));
2650 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2654 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2662 mfu_fingerprint(tagtype
, has_auth_key
, authkeyptr
, ak_len
);
2665 PrintAndLogEx(INFO
, "\nTag appears to be locked, try using a key to get more info");
2666 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
2668 PrintAndLogEx(NORMAL
, "");
2673 // Write Single Block
2675 static int CmdHF14AMfUWrBl(const char *Cmd
) {
2677 CLIParserContext
*ctx
;
2678 CLIParserInit(&ctx
, "hf mfu wrbl",
2679 "Write a block. It autodetects card type.",
2680 "hf mfu wrbl -b 0 -d 01234567\n"
2681 "hf mfu wrbl -b 0 -d 01234567 -k AABBCCDD\n"
2682 "hf mfu wrbl -b 0 -d 01234567 -k 00112233445566778899AABBCCDDEEFF"
2685 void *argtable
[] = {
2687 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2688 arg_lit0("l", NULL
, "Swap entered key's endianness"),
2689 arg_int1("b", "block", "<dec>", "Block number to write"),
2690 arg_str1("d", "data", "<hex>", "Block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"),
2691 arg_lit0(NULL
, "force", "Force operation even if address is out of range"),
2694 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2697 uint8_t authenticationkey
[16] = {0x00};
2698 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
2699 bool swap_endian
= arg_get_lit(ctx
, 2);
2701 int blockno
= arg_get_int_def(ctx
, 3, -1);
2704 uint8_t data
[16] = {0x00};
2705 CLIGetHexWithReturn(ctx
, 4, data
, &datalen
);
2706 bool force
= arg_get_lit(ctx
, 5);
2709 bool has_auth_key
= false;
2710 bool has_pwd
= false;
2712 has_auth_key
= true;
2713 } else if (ak_len
== 4) {
2715 } else if (ak_len
!= 0) {
2716 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
2721 PrintAndLogEx(WARNING
, "Wrong block number");
2725 if (datalen
!= 16 && datalen
!= 4) {
2726 PrintAndLogEx(WARNING
, "Wrong data length. Expect 16 or 4, got %d", datalen
);
2730 uint8_t *auth_key_ptr
= authenticationkey
;
2732 // starting with getting tagtype
2733 uint64_t tagtype
= GetHF14AMfU_Type();
2734 if (tagtype
== MFU_TT_UL_ERROR
)
2737 uint8_t maxblockno
= 0;
2738 for (uint8_t idx
= 1; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
2739 if ((tagtype
& UL_TYPES_ARRAY
[idx
]) == UL_TYPES_ARRAY
[idx
]) {
2740 maxblockno
= UL_MEMORY_ARRAY
[idx
];
2744 if ((blockno
> maxblockno
) && (!force
)) {
2745 PrintAndLogEx(WARNING
, "block number too large. Max block is %u/0x%02X \n", maxblockno
, maxblockno
);
2752 auth_key_ptr
= SwapEndian64(authenticationkey
, 16, 8);
2755 auth_key_ptr
= SwapEndian64(authenticationkey
, 4, 4);
2759 PrintAndLogEx(INFO
, "Special block: %0d (0x%02X) [ %s]", blockno
, blockno
, sprint_hex(data
, datalen
));
2761 PrintAndLogEx(INFO
, "Block: %0d (0x%02X) [ %s]", blockno
, blockno
, sprint_hex(data
, datalen
));
2764 PrintAndLogEx(INFO
, "Using %s " _GREEN_("%s"), (ak_len
== 16) ? "3des" : "pwd", sprint_hex(authenticationkey
, ak_len
));
2768 // Send write Block.
2771 if (datalen
== 16) {
2772 // Comp write may take 16bytes, but only write 4bytes. See UL-C datasheet
2773 for (uint8_t i
= 0; i
< 4; i
++) {
2775 res
= mfu_write_block(d
, 4, has_auth_key
, has_pwd
, auth_key_ptr
, blockno
+ i
);
2776 if (res
== PM3_SUCCESS
) {
2779 PrintAndLogEx(INFO
, "Write ( %s )", _RED_("fail"));
2784 if (res
== PM3_SUCCESS
) {
2785 PrintAndLogEx(SUCCESS
, "Write ( " _GREEN_("ok") " )");
2786 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno
);
2790 res
= mfu_write_block(data
, datalen
, has_auth_key
, has_pwd
, auth_key_ptr
, blockno
);
2793 PrintAndLogEx(SUCCESS
, "Write ( " _GREEN_("ok") " )");
2794 PrintAndLogEx(HINT
, "Try `" _YELLOW_("hf mfu rdbl -b %u") "` to verify ", blockno
);
2798 PrintAndLogEx(FAILED
, "Write ( " _RED_("fail") " )");
2799 PrintAndLogEx(HINT
, "Check password / key!");
2804 PrintAndLogEx(WARNING
, "Command execute timeout");
2813 // Read Single Block
2815 static int CmdHF14AMfURdBl(const char *Cmd
) {
2817 CLIParserContext
*ctx
;
2818 CLIParserInit(&ctx
, "hf mfu rdbl",
2819 "Read a block and print. It autodetects card type.",
2820 "hf mfu rdbl -b 0\n"
2821 "hf mfu rdbl -b 0 -k AABBCCDD\n"
2822 "hf mfu rdbl -b 0 --key 00112233445566778899AABBCCDDEEFF"
2825 void *argtable
[] = {
2827 arg_str0("k", "key", "<hex>", "Authentication key (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2828 arg_lit0("l", NULL
, "Swap entered key's endianness"),
2829 arg_int1("b", "block", "<dec>", "Block number to read"),
2830 arg_lit0(NULL
, "force", "Force operation even if address is out of range"),
2833 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2836 uint8_t authenticationkey
[16] = {0x00};
2837 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
2838 bool swap_endian
= arg_get_lit(ctx
, 2);
2839 int blockno
= arg_get_int_def(ctx
, 3, -1);
2840 bool force
= arg_get_lit(ctx
, 4);
2843 bool has_auth_key
= false;
2844 bool has_pwd
= false;
2846 has_auth_key
= true;
2847 } else if (ak_len
== 4) {
2849 } else if (ak_len
!= 0) {
2850 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
2855 PrintAndLogEx(WARNING
, "Wrong block number");
2859 uint8_t *authKeyPtr
= authenticationkey
;
2861 // start with getting tagtype
2862 uint64_t tagtype
= GetHF14AMfU_Type();
2863 if (tagtype
== MFU_TT_UL_ERROR
)
2866 uint8_t maxblockno
= 0;
2867 for (uint8_t idx
= 1; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
2868 if ((tagtype
& UL_TYPES_ARRAY
[idx
]) == UL_TYPES_ARRAY
[idx
]) {
2869 maxblockno
= UL_MEMORY_ARRAY
[idx
];
2873 if ((blockno
> maxblockno
) && (!force
)) {
2874 PrintAndLogEx(WARNING
, "block number to large. Max block is %u/0x%02X \n", maxblockno
, maxblockno
);
2881 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 8);
2884 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 4);
2888 PrintAndLogEx(INFO
, "Using %s " _GREEN_("%s"), (ak_len
== 16) ? "3des" : "pwd", sprint_hex(authenticationkey
, ak_len
));
2892 uint8_t keytype
= 0;
2893 uint8_t datalen
= 0;
2897 } else if (has_pwd
) {
2902 clearCommandBuffer();
2903 SendCommandMIX(CMD_HF_MIFAREU_READBL
, blockno
, keytype
, 0, authKeyPtr
, datalen
);
2904 PacketResponseNG resp
;
2905 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2906 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
2908 uint8_t *d
= resp
.data
.asBytes
;
2909 PrintAndLogEx(NORMAL
, "");
2910 PrintAndLogEx(INFO
, "Block# | Data | Ascii");
2911 PrintAndLogEx(INFO
, "-----------------------------");
2912 PrintAndLogEx(INFO
, "%02d/0x%02X | %s| %s\n", blockno
, blockno
, sprint_hex(d
, 4), sprint_ascii(d
, 4));
2914 PrintAndLogEx(WARNING
, "Failed reading block: ( %02x )", isOK
);
2917 PrintAndLogEx(WARNING
, "Command execute timeout");
2922 void mfu_print_dump(mfu_dump_t
*card
, uint16_t pages
, uint8_t startpage
, bool dense_output
) {
2924 PrintAndLogEx(NORMAL
, "");
2925 PrintAndLogEx(INFO
, _CYAN_("MFU dump file information"));
2926 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
2927 PrintAndLogEx(INFO
, "Version..... " _YELLOW_("%s"), sprint_hex(card
->version
, sizeof(card
->version
)));
2928 PrintAndLogEx(INFO
, "TBD 0....... %s", sprint_hex(card
->tbo
, sizeof(card
->tbo
)));
2929 PrintAndLogEx(INFO
, "TBD 1....... %s", sprint_hex(card
->tbo1
, sizeof(card
->tbo1
)));
2930 PrintAndLogEx(INFO
, "Signature... %s", sprint_hex(card
->signature
, 16));
2931 PrintAndLogEx(INFO
, " %s", sprint_hex(card
->signature
+ 16, sizeof(card
->signature
) - 16));
2932 for (uint8_t i
= 0; i
< 3; i
++) {
2933 PrintAndLogEx(INFO
, "Counter %d... %s", i
, sprint_hex(card
->counter_tearing
[i
], 3));
2934 PrintAndLogEx(INFO
, "Tearing %d... %s", i
, sprint_hex(card
->counter_tearing
[i
] + 3, 1));
2937 // 0-bases index, to get total bytes, its +1 page.
2939 // Max index page is 47.
2940 // total pages is 48
2941 // total bytes is 192
2942 PrintAndLogEx(INFO
, "Max data page... " _YELLOW_("%d") " ( " _YELLOW_("%d") " bytes )", card
->pages
, (card
->pages
+ 1) * MFU_BLOCK_SIZE
);
2943 PrintAndLogEx(INFO
, "Header size..... %d bytes", MFU_DUMP_PREFIX_LENGTH
);
2946 bool lckbit
= false;
2947 uint8_t *data
= card
->data
;
2949 uint8_t lockbytes_sta
[] = {0, 0};
2950 uint8_t lockbytes_dyn
[] = {0, 0, 0};
2951 bool bit_stat
[16] = {0};
2952 bool bit_dyn
[16] = {0};
2954 // Load static lock bytes.
2955 memcpy(lockbytes_sta
, data
+ 10, sizeof(lockbytes_sta
));
2956 for (j
= 0; j
< 16; j
++) {
2957 bit_stat
[j
] = lockbytes_sta
[j
/ 8] & (1 << (7 - j
% 8));
2960 // Load dynamic lockbytes if available
2961 // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG
2964 memcpy(lockbytes_dyn
, data
+ (40 * 4), sizeof(lockbytes_dyn
));
2966 for (j
= 0; j
< 16; j
++) {
2967 bit_dyn
[j
] = lockbytes_dyn
[j
/ 8] & (1 << (7 - j
% 8));
2969 PrintAndLogEx(INFO
, "Dynamic lock.... %s", sprint_hex(lockbytes_dyn
, 3));
2972 PrintAndLogEx(NORMAL
, "");
2973 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
2974 PrintAndLogEx(INFO
, "block# | data |lck| ascii");
2975 PrintAndLogEx(INFO
, "---------+-------------+---+------");
2977 bool in_repeated_block
= false;
2979 for (uint16_t i
= 0; i
< pages
; ++i
) {
2981 PrintAndLogEx(INFO
, "%3d/0x%02X | " _RED_("%s")"| | %s",
2984 sprint_hex(data
+ i
* 4, 4),
2985 sprint_ascii(data
+ i
* 4, 4)
2991 lckbit
= bit_stat
[4];
2994 lckbit
= bit_stat
[3];
2997 lckbit
= bit_stat
[2];
3000 lckbit
= bit_stat
[1];
3003 lckbit
= bit_stat
[0];
3006 lckbit
= bit_stat
[15];
3009 lckbit
= bit_stat
[14];
3012 lckbit
= bit_stat
[13];
3015 lckbit
= bit_stat
[12];
3018 lckbit
= bit_stat
[11];
3021 lckbit
= bit_stat
[10];
3024 lckbit
= bit_stat
[9];
3027 lckbit
= bit_stat
[8];
3033 lckbit
= bit_dyn
[6];
3039 lckbit
= bit_dyn
[5];
3045 lckbit
= bit_dyn
[4];
3051 lckbit
= bit_dyn
[2];
3057 lckbit
= bit_dyn
[1];
3063 lckbit
= bit_dyn
[0];
3066 lckbit
= bit_dyn
[12];
3069 lckbit
= bit_dyn
[11];
3072 lckbit
= bit_dyn
[10];
3075 lckbit
= bit_dyn
[9];
3082 // suppress repeating blocks, truncate as such that the first and last block with the same data is shown
3083 // but the blocks in between are replaced with a single line of "......" if dense_output is enabled
3084 uint8_t *blk
= data
+ (i
* MFU_BLOCK_SIZE
);
3088 (in_repeated_block
== false) &&
3089 (memcmp(blk
, blk
- MFU_BLOCK_SIZE
, MFU_BLOCK_SIZE
) == 0) &&
3090 (memcmp(blk
, blk
+ MFU_BLOCK_SIZE
, MFU_BLOCK_SIZE
) == 0) &&
3091 (memcmp(blk
, blk
+ (MFU_BLOCK_SIZE
* 2), MFU_BLOCK_SIZE
) == 0)
3093 // we're in a user block that isn't the first user block nor last two user blocks,
3094 // and the current block data is the same as the previous and next two block
3095 in_repeated_block
= true;
3096 PrintAndLogEx(INFO
, " ......");
3097 } else if (in_repeated_block
&&
3098 (memcmp(blk
, blk
+ MFU_BLOCK_SIZE
, MFU_BLOCK_SIZE
) || i
== pages
)
3100 // in a repeating block, but the next block doesn't match anymore, or we're at the end block
3101 in_repeated_block
= false;
3105 if (in_repeated_block
== false) {
3106 PrintAndLogEx(INFO
, "%3d/0x%02X | %s| %s | %s"
3109 , sprint_hex(data
+ i
* 4, 4)
3110 , (lckbit
) ? _RED_("1") : "0"
3111 , sprint_ascii(data
+ i
* 4, 4)
3115 PrintAndLogEx(INFO
, "---------------------------------");
3119 // Mifare Ultralight / Ultralight-C / Ultralight-EV1
3120 // Read and Dump Card Contents, using auto detection of tag size.
3121 static int CmdHF14AMfUDump(const char *Cmd
) {
3123 CLIParserContext
*ctx
;
3124 CLIParserInit(&ctx
, "hf mfu dump",
3125 "Dump MIFARE Ultralight/NTAG tag to files (bin/json)\n"
3126 "It autodetects card type."
3128 "Ultralight, Ultralight-C, Ultralight EV1\n"
3129 "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216\n",
3130 "hf mfu dump -f myfile\n"
3131 "hf mfu dump -k AABBCCDD -> dump whole tag using pwd AABBCCDD\n"
3132 "hf mfu dump -p 10 -> start at page 10 and dump rest of blocks\n"
3133 "hf mfu dump -p 10 -q 2 -> start at page 10 and dump two blocks\n"
3134 "hf mfu dump --key 00112233445566778899AABBCCDDEEFF"
3137 void *argtable
[] = {
3139 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
3140 arg_str0("k", "key", "<hex>", "Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
3141 arg_lit0("l", NULL
, "Swap entered key's endianness"),
3142 arg_int0("p", "page", "<dec>", "Manually set start page number to start from"),
3143 arg_int0("q", "qty", "<dec>", "Manually set number of pages to dump"),
3144 arg_lit0(NULL
, "ns", "no save to file"),
3145 arg_lit0("z", "dense", "dense dump output style"),
3148 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3151 char filename
[FILE_PATH_SIZE
] = {0};
3152 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
3155 uint8_t authenticationkey
[16] = {0x00};
3156 uint8_t *authKeyPtr
= authenticationkey
;
3157 CLIGetHexWithReturn(ctx
, 2, authenticationkey
, &ak_len
);
3158 bool swap_endian
= arg_get_lit(ctx
, 3);
3159 int start_page
= arg_get_int_def(ctx
, 4, 0);
3160 int pages
= arg_get_int_def(ctx
, 5, 16);
3161 bool nosave
= arg_get_lit(ctx
, 6);
3162 bool dense_output
= (g_session
.dense_output
|| arg_get_lit(ctx
, 7));
3165 bool has_auth_key
= false;
3166 bool has_pwd
= false;
3168 has_auth_key
= true;
3169 } else if (ak_len
== 4) {
3171 } else if (ak_len
!= 0) {
3172 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
3176 bool manual_pages
= false;
3177 if (start_page
> 0) {
3178 manual_pages
= true;
3182 manual_pages
= true;
3185 uint8_t card_mem_size
= 0;
3190 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 8);
3194 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 4);
3198 uint64_t tagtype
= GetHF14AMfU_Type();
3199 if (tagtype
== MFU_TT_UL_ERROR
) {
3203 //get number of pages to read
3204 if (manual_pages
== false) {
3205 for (uint8_t idx
= 1; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
3206 if ((tagtype
& UL_TYPES_ARRAY
[idx
]) == UL_TYPES_ARRAY
[idx
]) {
3207 //add one as maxblks starts at 0
3208 card_mem_size
= pages
= UL_MEMORY_ARRAY
[idx
] + 1;
3214 ul_print_type(tagtype
, 0);
3215 PrintAndLogEx(SUCCESS
, "Reading tag memory...");
3216 uint8_t keytype
= 0;
3217 if (has_auth_key
|| has_pwd
) {
3218 if ((tagtype
& MFU_TT_UL_C
) == MFU_TT_UL_C
)
3219 keytype
= 1; // UL_C auth
3221 keytype
= 2; // UL_EV1/NTAG auth
3224 uint8_t dbg_curr
= DBG_NONE
;
3225 if (getDeviceDebugLevel(&dbg_curr
) != PM3_SUCCESS
) {
3229 if (setDeviceDebugLevel(DBG_NONE
, false) != PM3_SUCCESS
) {
3233 clearCommandBuffer();
3234 SendCommandMIX(CMD_HF_MIFAREU_READCARD
, start_page
, pages
, keytype
, authKeyPtr
, ak_len
);
3235 PacketResponseNG resp
;
3236 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 2500) == false) {
3237 PrintAndLogEx(WARNING
, "Command execute timeout");
3238 return PM3_ETIMEOUT
;
3241 if (resp
.oldarg
[0] != 1) {
3242 PrintAndLogEx(WARNING
, "Failed dumping card");
3246 setDeviceDebugLevel(dbg_curr
, false);
3249 uint8_t data
[1024] = {0x00};
3250 memset(data
, 0x00, sizeof(data
));
3252 uint32_t startindex
= resp
.oldarg
[2];
3253 uint32_t buffer_size
= resp
.oldarg
[1];
3254 if (buffer_size
> sizeof(data
)) {
3255 PrintAndLogEx(FAILED
, "Data exceeded buffer size!");
3256 buffer_size
= sizeof(data
);
3259 if (GetFromDevice(BIG_BUF
, data
, buffer_size
, startindex
, NULL
, 0, NULL
, 2500, false) == false) {
3260 PrintAndLogEx(WARNING
, "command execute timeout");
3261 return PM3_ETIMEOUT
;
3264 bool is_partial
= (pages
!= buffer_size
/ MFU_BLOCK_SIZE
);
3266 pages
= buffer_size
/ MFU_BLOCK_SIZE
;
3270 if ((tagtype
& MFU_TT_UL_C
) == MFU_TT_UL_C
) {
3271 if (card_mem_size
!= (pages
+ 4)) {
3272 PrintAndLogEx(INFO
, "Partial dump, got " _RED_("%d") " bytes - card mem size is %u bytes", pages
* MFU_BLOCK_SIZE
, card_mem_size
* MFU_BLOCK_SIZE
);
3273 PrintAndLogEx(HINT
, "Try using a key");
3276 PrintAndLogEx(HINT
, "Try using a pwd");
3280 iso14a_card_select_t card
;
3281 mfu_dump_t dump_file_data
;
3282 memset(&dump_file_data
, 0, sizeof(dump_file_data
));
3283 uint8_t get_version
[] = {0, 0, 0, 0, 0, 0, 0, 0};
3284 uint8_t get_counter_tearing
[][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
3285 uint8_t get_signature
[32];
3286 memset(get_signature
, 0, sizeof(get_signature
));
3288 // not ul_c and not std ul then attempt to collect info like
3289 // VERSION, SIGNATURE, COUNTERS, TEARING, PACK,
3290 if (!(tagtype
& MFU_TT_UL_C
|| tagtype
& MFU_TT_UL
|| tagtype
& MFU_TT_MY_D_MOVE
|| tagtype
& MFU_TT_MY_D_MOVE_LEAN
)) {
3291 // attempt to read pack
3292 bool has_key
= (has_auth_key
|| has_pwd
);
3293 uint8_t get_pack
[] = {0, 0};
3294 if (ul_auth_select(&card
, tagtype
, has_key
, authKeyPtr
, get_pack
, sizeof(get_pack
)) != PM3_SUCCESS
) {
3301 // only add pack if not partial read, and complete pages read.
3302 if (!is_partial
&& pages
== card_mem_size
) {
3304 // add pack to block read
3305 memcpy(data
+ (pages
* 4) - 4, get_pack
, sizeof(get_pack
));
3309 uint8_t dummy_pack
[] = {0, 0};
3310 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
3315 ulev1_getVersion(get_version
, sizeof(get_version
));
3317 // ULEV-1 has 3 counters
3320 // NTAG has 1 counter, at 0x02
3321 if ((tagtype
& (MFU_TT_NTAG_213
| MFU_TT_NTAG_213_F
| MFU_TT_NTAG_213_C
| MFU_TT_NTAG_213_TT
| MFU_TT_NTAG_215
| MFU_TT_NTAG_216
))) {
3325 // NTAG can have nfc counter pwd protection enabled
3326 for (; n
< 3; n
++) {
3329 uint8_t dummy_pack
[] = {0, 0};
3330 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
3334 ulev1_readCounter(n
, &get_counter_tearing
[n
][0], 3);
3337 uint8_t dummy_pack
[] = {0, 0};
3338 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
3342 ulev1_readTearing(n
, &get_counter_tearing
[n
][3], 1);
3348 uint8_t dummy_pack
[] = {0, 0};
3349 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
3354 ulev1_readSignature(get_signature
, sizeof(get_signature
));
3359 // format and add keys to block dump output
3360 // only add keys if not partial read, and complete pages read
3362 // UL-C add a working known key
3363 if (has_auth_key
&& (tagtype
& MFU_TT_UL_C
) == MFU_TT_UL_C
) { // add 4 pages of key
3365 // if we didn't swapendian before - do it now for the sprint_hex call
3366 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
3367 // need to swap to keep it the same
3368 if (swap_endian
== false) {
3369 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 8);
3371 authKeyPtr
= authenticationkey
;
3374 memcpy(data
+ pages
* MFU_BLOCK_SIZE
, authKeyPtr
, ak_len
);
3375 pages
+= ak_len
/ MFU_BLOCK_SIZE
;
3378 if (is_partial
&& pages
== card_mem_size
) {
3383 if (!is_partial
&& pages
== card_mem_size
&& has_pwd
) {
3384 // if we didn't swapendian before - do it now for the sprint_hex call
3385 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
3386 // need to swap to keep it the same
3387 if (swap_endian
== false) {
3388 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 4);
3390 authKeyPtr
= authenticationkey
;
3393 memcpy(data
+ (pages
* MFU_BLOCK_SIZE
) - 8, authenticationkey
, ak_len
);
3396 //add *special* blocks to dump
3397 // pack and pwd saved into last pages of dump, if was not partial read
3398 dump_file_data
.pages
= pages
- 1;
3399 memcpy(dump_file_data
.version
, get_version
, sizeof(dump_file_data
.version
));
3400 memcpy(dump_file_data
.signature
, get_signature
, sizeof(dump_file_data
.signature
));
3401 memcpy(dump_file_data
.counter_tearing
, get_counter_tearing
, sizeof(dump_file_data
.counter_tearing
));
3402 memcpy(dump_file_data
.data
, data
, pages
* MFU_BLOCK_SIZE
);
3404 mfu_print_dump(&dump_file_data
, pages
, start_page
, dense_output
);
3407 PrintAndLogEx(INFO
, "Called with no save option");
3408 PrintAndLogEx(NORMAL
, "");
3412 // user supplied filename?
3414 PrintAndLogEx(INFO
, "Using UID as filename");
3415 uint8_t uid
[7] = {0};
3416 memcpy(uid
, (uint8_t *)&dump_file_data
.data
, 3);
3417 memcpy(uid
+ 3, (uint8_t *)&dump_file_data
.data
+ 4, 4);
3418 strcat(filename
, "hf-mfu-");
3419 FillFileNameByUID(filename
, uid
, "-dump", sizeof(uid
));
3422 uint16_t datalen
= MFU_DUMP_PREFIX_LENGTH
+ (pages
* MFU_BLOCK_SIZE
);
3423 pm3_save_dump(filename
, (uint8_t *)&dump_file_data
, datalen
, jsfMfuMemory
);
3426 PrintAndLogEx(WARNING
, "Partial dump created. (%d of %d blocks)", pages
, card_mem_size
);
3431 static void wait4response(uint8_t b
) {
3432 PacketResponseNG resp
;
3433 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
3434 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
3436 PrintAndLogEx(WARNING
, "failed to write block %d", b
);
3439 PrintAndLogEx(WARNING
, "Command execute timeout");
3444 //Configure tamper feature of NTAG 213TT
3446 int CmdHF14MfUTamper(const char *Cmd
) {
3447 CLIParserContext
*ctx
;
3448 CLIParserInit(&ctx
, "hf mfu tamper",
3449 "Set the configuration of the NTAG 213TT tamper feature\n"
3452 "hf mfu tamper -e -> enable tamper feature\n"
3453 "hf mfu tamper -d -> disable tamper feature\n"
3454 "hf mfu tamper -m 0A0A0A0A -> set the tamper message to 0A0A0A0A\n"
3455 "hf mfu tamper --lockmessage -> permanently lock the tamper message and mask it from memory\n"
3458 void *argtable
[] = {
3460 arg_lit0("e", "enable", "Enable the tamper feature"),
3461 arg_lit0("d", "disable", "Disable the tamper feature"),
3462 arg_str0("m", "message", "<hex>", "Set the tamper message (4 bytes)"),
3463 arg_lit0(NULL
, "lockmessage", "Permanently lock the tamper message and mask it from memory (does not lock tamper feature itself)"),
3466 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3468 int tt_cfg_page
= 41;
3469 int tt_msg_page
= 45;
3471 uint8_t msg_data
[4] = {0x00};
3472 CLIGetHexWithReturn(ctx
, 3, msg_data
, &msg_len
);
3473 bool use_msg
= (msg_len
> 0);
3475 if (use_msg
&& msg_len
!= 4) {
3476 PrintAndLogEx(WARNING
, "The tamper message must be 4 hex bytes if provided");
3482 bool lock_msg
= arg_get_lit(ctx
, 4);
3483 bool enable
= arg_get_lit(ctx
, 1);
3484 bool disable
= arg_get_lit(ctx
, 2);
3487 uint64_t tagtype
= GetHF14AMfU_Type();
3488 if (tagtype
== MFU_TT_UL_ERROR
) {
3489 PrintAndLogEx(WARNING
, "Tag type not detected");
3493 if (tagtype
!= MFU_TT_NTAG_213_TT
) {
3494 PrintAndLogEx(WARNING
, "Tag type not NTAG 213TT");
3500 iso14a_card_select_t card
;
3502 if (enable
&& disable
) {
3503 PrintAndLogEx(WARNING
, "You can only select one of the options enable/disable tamper feature");
3509 if (ul_select(&card
) == false) {
3511 return MFU_TT_UL_ERROR
;
3513 PrintAndLogEx(INFO
, "Trying to write tamper message");
3514 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, tt_msg_page
, 0, 0, msg_data
, 4);
3516 PacketResponseNG resp
;
3518 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
3519 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
3521 PrintAndLogEx(WARNING
, "Failed to write tamper message");
3523 PrintAndLogEx(SUCCESS
, "Tamper message written successfully");
3525 PrintAndLogEx(WARNING
, "Command execute timeout");
3529 if (enable
|| disable
|| lock_msg
) {
3531 if (ul_select(&card
) == false) {
3532 PrintAndLogEx(ERR
, "Unable to select tag");
3534 return MFU_TT_UL_ERROR
;
3537 uint8_t cfg_page
[4] = {0x00};
3538 uint8_t cmd
[] = {ISO14443A_CMD_READBLOCK
, tt_cfg_page
};
3539 int status
= ul_send_cmd_raw(cmd
, sizeof(cmd
), cfg_page
, 4);
3543 PrintAndLogEx(WARNING
, "Problem reading current config from tag");
3549 cfg_page
[1] = cfg_page
[1] | 0x02;
3550 PrintAndLogEx(INFO
, "Enabling tamper feature");
3553 cfg_page
[1] = cfg_page
[1] & 0xFD;
3554 PrintAndLogEx(INFO
, "Disabling tamper feature");
3557 cfg_page
[1] = cfg_page
[1] | 0x04;
3558 PrintAndLogEx(INFO
, "Locking tamper message");
3561 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, tt_cfg_page
, 0, 0, cfg_page
, 4);
3562 PacketResponseNG resp
;
3564 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
3565 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
3567 PrintAndLogEx(WARNING
, "Failed to write tamper configuration");
3569 PrintAndLogEx(SUCCESS
, "Tamper configuration written successfully");
3571 PrintAndLogEx(WARNING
, "Command execute timeout");
3580 // Restore dump file onto tag
3582 static int CmdHF14AMfURestore(const char *Cmd
) {
3583 CLIParserContext
*ctx
;
3584 CLIParserInit(&ctx
, "hf mfu restore",
3585 "Restore MIFARE Ultralight/NTAG dump file (bin/eml/json) to tag.\n",
3586 "hf mfu restore -f myfile -s -> special write\n"
3587 "hf mfu restore -f myfile -k AABBCCDD -s -> special write, use key\n"
3588 "hf mfu restore -f myfile -k AABBCCDD -ser -> special write, use key, write dump pwd, ..."
3591 void *argtable
[] = {
3593 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
3594 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
3595 arg_lit0("l", NULL
, "swap entered key's endianness"),
3596 arg_lit0("s", NULL
, "enable special write UID -MAGIC TAG ONLY-"),
3597 arg_lit0("e", NULL
, "enable special write version/signature -MAGIC NTAG 21* ONLY-"),
3598 arg_lit0("r", NULL
, "use password found in dumpfile to configure tag. Requires " _YELLOW_("'-e'") " parameter to work"),
3599 arg_lit0("v", "verbose", "verbose output"),
3600 arg_lit0("z", "dense", "dense dump output style"),
3603 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3606 char filename
[FILE_PATH_SIZE
] = {0};
3607 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
3610 uint8_t authkey
[16] = {0x00};
3611 uint8_t *p_authkey
= authkey
;
3612 CLIGetHexWithReturn(ctx
, 2, authkey
, &ak_len
);
3614 bool swap_endian
= arg_get_lit(ctx
, 3);
3615 bool write_special
= arg_get_lit(ctx
, 4);
3616 bool write_extra
= arg_get_lit(ctx
, 5);
3617 bool read_key
= arg_get_lit(ctx
, 6);
3618 bool verbose
= arg_get_lit(ctx
, 7);
3619 bool dense_output
= (g_session
.dense_output
|| arg_get_lit(ctx
, 8));
3622 bool has_key
= false;
3624 if (ak_len
!= 4 && ak_len
!= 16) {
3625 PrintAndLogEx(ERR
, "Wrong key length. expected 4 or 16, got %d", ak_len
);
3633 char *fptr
= mfu_generate_filename("hf-mfu-", "-dump.bin");
3635 strncpy(filename
, fptr
, sizeof(filename
) - 1);
3637 snprintf(filename
, sizeof(filename
), "dumpdata.bin");
3643 uint8_t *dump
= NULL
;
3644 size_t bytes_read
= 0;
3645 int res
= pm3_load_dump(filename
, (void **)&dump
, &bytes_read
, (MFU_MAX_BYTES
+ MFU_DUMP_PREFIX_LENGTH
));
3646 if (res
!= PM3_SUCCESS
) {
3650 if (bytes_read
< MFU_DUMP_PREFIX_LENGTH
) {
3651 PrintAndLogEx(ERR
, "Error, dump file is too small");
3656 res
= convert_mfu_dump_format(&dump
, &bytes_read
, verbose
);
3657 if (res
!= PM3_SUCCESS
) {
3658 PrintAndLogEx(FAILED
, "Failed convert on load to new Ultralight/NTAG format");
3663 mfu_dump_t
*mem
= (mfu_dump_t
*)dump
;
3664 uint8_t pages
= (bytes_read
- MFU_DUMP_PREFIX_LENGTH
) / MFU_BLOCK_SIZE
;
3666 if (pages
- 1 != mem
->pages
) {
3667 PrintAndLogEx(ERR
, "Error, invalid dump, wrong page count");
3668 PrintAndLogEx(INFO
, " %u vs mempg %u", pages
- 1, mem
->pages
);
3673 PrintAndLogEx(INFO
, "Restoring " _YELLOW_("%s")" to card", filename
);
3675 mfu_print_dump(mem
, pages
, 0, dense_output
);
3678 if (swap_endian
&& has_key
) {
3680 p_authkey
= SwapEndian64(authkey
, ak_len
, 8);
3682 p_authkey
= SwapEndian64(authkey
, ak_len
, 4);
3685 uint8_t data
[20] = {0};
3686 uint8_t keytype
= 0;
3687 // set key - only once
3689 keytype
= (ak_len
== 16) ? 1 : 2;
3690 memcpy(data
+ 4, p_authkey
, ak_len
);
3693 // write version, signature, pack
3694 // only magic NTAG cards
3697 #define MFU_NTAG_SPECIAL_PWD 0xF0
3698 #define MFU_NTAG_SPECIAL_PACK 0xF1
3699 #define MFU_NTAG_SPECIAL_VERSION 0xFA
3700 #define MFU_NTAG_SPECIAL_SIGNATURE 0xF2
3702 if (has_key
|| read_key
) {
3704 memcpy(data
, p_authkey
, 4);
3706 // try reading key from dump and use.
3707 memcpy(data
, mem
->data
+ (bytes_read
- MFU_DUMP_PREFIX_LENGTH
- 8), 4);
3710 PrintAndLogEx(INFO
, "special PWD block written 0x%X - %s", MFU_NTAG_SPECIAL_PWD
, sprint_hex(data
, 4));
3711 clearCommandBuffer();
3712 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, MFU_NTAG_SPECIAL_PWD
, keytype
, 0, data
, sizeof(data
));
3714 wait4response(MFU_NTAG_SPECIAL_PWD
);
3718 memcpy(authkey
, data
, 4);
3719 memcpy(data
+ 4, authkey
, 4);
3723 memcpy(data
, mem
->data
+ (bytes_read
- MFU_DUMP_PREFIX_LENGTH
- 4), 2);
3726 PrintAndLogEx(INFO
, "special PACK block written 0x%X - %s", MFU_NTAG_SPECIAL_PACK
, sprint_hex(data
, 4));
3727 clearCommandBuffer();
3728 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, MFU_NTAG_SPECIAL_PACK
, keytype
, 0, data
, sizeof(data
));
3729 wait4response(MFU_NTAG_SPECIAL_PACK
);
3732 for (uint8_t s
= MFU_NTAG_SPECIAL_SIGNATURE
, i
= 0; s
< MFU_NTAG_SPECIAL_SIGNATURE
+ 8; s
++, i
+= 4) {
3733 memcpy(data
, mem
->signature
+ i
, 4);
3734 PrintAndLogEx(INFO
, "special SIG block written 0x%X - %s", s
, sprint_hex(data
, 4));
3735 clearCommandBuffer();
3736 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, s
, keytype
, 0, data
, sizeof(data
));
3741 for (uint8_t s
= MFU_NTAG_SPECIAL_VERSION
, i
= 0; s
< MFU_NTAG_SPECIAL_VERSION
+ 2; s
++, i
+= 4) {
3742 memcpy(data
, mem
->version
+ i
, 4);
3743 PrintAndLogEx(INFO
, "special VERSION block written 0x%X - %s", s
, sprint_hex(data
, 4));
3744 clearCommandBuffer();
3745 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, s
, keytype
, 0, data
, sizeof(data
));
3750 PrintAndLogEx(INFO
, "Restoring data blocks.");
3751 PrintAndLogEx(INFO
, "." NOLF
);
3752 // write all other data
3753 // Skip block 0,1,2,3 (only magic tags can write to them)
3754 // Skip last 5 blocks usually is configuration
3755 for (uint8_t b
= 4; b
< pages
- 5; b
++) {
3758 memcpy(data
, mem
->data
+ (b
* 4), 4);
3759 clearCommandBuffer();
3760 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, b
, keytype
, 0, data
, sizeof(data
));
3762 PrintAndLogEx(NORMAL
, "." NOLF
);
3765 PrintAndLogEx(NORMAL
, "");
3767 // write special data last
3768 if (write_special
) {
3770 PrintAndLogEx(INFO
, "Restoring configuration blocks");
3772 PrintAndLogEx(INFO
, "Authentication with keytype[%x] %s\n", (uint8_t)(keytype
& 0xff), sprint_hex(p_authkey
, 4));
3775 // otp, uid, lock, dynlockbits, cfg0, cfg1, pwd, pack
3776 uint8_t blocks
[] = {3, 0, 1, 2, pages
- 5, pages
- 4, pages
- 3, pages
- 2, pages
- 1};
3778 // otp, uid, lock, dynlockbits, cfg0, cfg1
3779 uint8_t blocks
[] = {3, 0, 1, 2, pages
- 5, pages
- 4, pages
- 3};
3781 for (uint8_t i
= 0; i
< ARRAYLEN(blocks
); i
++) {
3782 uint8_t b
= blocks
[i
];
3783 memcpy(data
, mem
->data
+ (b
* 4), 4);
3784 clearCommandBuffer();
3785 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, b
, keytype
, 0, data
, sizeof(data
));
3787 PrintAndLogEx(INFO
, "special block written " _YELLOW_("%u") " - %s", b
, sprint_hex(data
, 4));
3793 PrintAndLogEx(HINT
, "try `" _YELLOW_("hf mfu dump --ns") "` to verify");
3794 PrintAndLogEx(INFO
, "Done!");
3798 // Load emulator with dump file
3800 static int CmdHF14AMfUeLoad(const char *Cmd
) {
3802 CLIParserContext
*ctx
;
3803 CLIParserInit(&ctx
, "hf mfu eload",
3804 "Load emulator memory with data from (bin/eml/json) dump file\n",
3805 "hf mfu eload -f hf-mfu-04010203040506.bin\n"
3806 "hf mfu eload -f hf-mfu-04010203040506.bin -q 57 -> load 57 blocks from myfile"
3809 void *argtable
[] = {
3811 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
3812 arg_int0("q", "qty", "<dec>", "Number of blocks to load from eml file"),
3813 arg_lit0("v", "verbose", "verbose output"),
3816 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3819 size_t nc_len
= strlen(Cmd
) + 6;
3820 char *nc
= calloc(nc_len
, 1);
3822 return CmdHF14AMfELoad(Cmd
);
3825 snprintf(nc
, nc_len
, "%s --ul", Cmd
);
3826 int res
= CmdHF14AMfELoad(nc
);
3829 PrintAndLogEx(HINT
, "Try " _YELLOW_("`hf mfu sim -t 7`") " to simulate an Amiibo.");
3830 PrintAndLogEx(INFO
, "Done!");
3837 static int CmdHF14AMfUSim(const char *Cmd
) {
3838 CLIParserContext
*ctx
;
3839 CLIParserInit(&ctx
, "hf mfu sim",
3840 "Simulate MIFARE Ultralight family type based upon\n"
3841 "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
3842 "from emulator memory. See `hf mfu eload` first. \n"
3843 "The UID from emulator memory will be used if not specified.\n"
3844 "See `hf 14a sim -h` to see available types. You want 2 or 7 usually.",
3845 "hf mfu sim -t 2 --uid 11223344556677 -> MIFARE Ultralight\n"
3846 "hf mfu sim -t 7 --uid 11223344556677 -n 5 -> MFU EV1 / NTAG 215 Amiibo\n"
3847 "hf mfu sim -t 7 -> MFU EV1 / NTAG 215 Amiibo"
3850 void *argtable
[] = {
3852 arg_int1("t", "type", "<1..12> ", "Simulation type to use"),
3853 arg_str0("u", "uid", "<hex>", "<4|7|10> hex bytes UID"),
3854 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks. 0 = infinite"),
3855 arg_lit0("v", "verbose", "Verbose output"),
3858 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
3860 return CmdHF14ASim(Cmd
);
3863 //-------------------------------------------------------------------------------
3864 // Ultralight C Methods
3865 //-------------------------------------------------------------------------------
3867 // Ultralight C Authentication
3869 static int CmdHF14AMfUCAuth(const char *Cmd
) {
3870 CLIParserContext
*ctx
;
3871 CLIParserInit(&ctx
, "hf mfu cauth",
3872 "Tests 3DES password on Mifare Ultralight-C tag.\n"
3873 "If password is not specified, a set of known defaults will be tested.",
3875 "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f"
3878 void *argtable
[] = {
3880 arg_str0(NULL
, "key", "<hex>", "Authentication key (UL-C 16 hex bytes)"),
3881 arg_lit0("l", NULL
, "Swap entered key's endianness"),
3882 arg_lit0("k", NULL
, "Keep field on (only if a password is provided)"),
3885 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3888 uint8_t authenticationkey
[16] = {0x00};
3889 uint8_t *authKeyPtr
= authenticationkey
;
3890 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
3891 bool swap_endian
= arg_get_lit(ctx
, 2);
3892 bool keep_field_on
= arg_get_lit(ctx
, 3);
3895 if (ak_len
!= 16 && ak_len
!= 0) {
3896 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length");
3901 if (swap_endian
&& ak_len
) {
3902 authKeyPtr
= SwapEndian64(authenticationkey
, 16, 8);
3907 // If no hex key is specified, try default keys
3909 isok
= try_default_3des_keys(false, &authKeyPtr
);
3911 // try user-supplied
3912 isok
= ulc_authentication(authKeyPtr
, !keep_field_on
);
3915 if (isok
== PM3_SUCCESS
) {
3916 PrintAndLogEx(SUCCESS
, "Authentication 3DES key... " _GREEN_("%s") " ( " _GREEN_("ok")" )", sprint_hex_inrow(authKeyPtr
, 16));
3918 PrintAndLogEx(WARNING
, "Authentication ( " _RED_("fail") " )");
3924 A test function to validate that the polarssl-function works the same
3925 was as the openssl-implementation.
3926 Commented out, since it requires openssl
3928 static int CmdTestDES(const char * cmd)
3930 uint8_t key[16] = {0x00};
3932 memcpy(key,key3_3des_data,16);
3933 DES_cblock RndA, RndB;
3935 PrintAndLogEx(NORMAL, "----------OpenSSL DES implementation----------");
3937 uint8_t e_RndB[8] = {0x00};
3938 unsigned char RndARndB[16] = {0x00};
3940 DES_cblock iv = { 0 };
3941 DES_key_schedule ks1,ks2;
3942 DES_cblock key1,key2;
3944 memcpy(key,key3_3des_data,16);
3946 memcpy(key2,key+8,8);
3949 DES_set_key((DES_cblock *)key1,&ks1);
3950 DES_set_key((DES_cblock *)key2,&ks2);
3952 DES_random_key(&RndA);
3953 PrintAndLogEx(NORMAL, " RndA:%s",sprint_hex(RndA, 8));
3954 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(e_RndB, 8));
3955 //void DES_ede2_cbc_encrypt(const unsigned char *input,
3956 // unsigned char *output, long length, DES_key_schedule *ks1,
3957 // DES_key_schedule *ks2, DES_cblock *ivec, int enc);
3958 DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
3960 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(RndB, 8));
3962 memcpy(RndARndB,RndA,8);
3963 memcpy(RndARndB+8,RndB,8);
3964 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(RndARndB, 16));
3965 DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
3966 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(RndARndB, 16));
3969 PrintAndLogEx(NORMAL, "----------PolarSSL implementation----------");
3971 uint8_t random_a[8] = { 0 };
3972 uint8_t enc_random_a[8] = { 0 };
3973 uint8_t random_b[8] = { 0 };
3974 uint8_t enc_random_b[8] = { 0 };
3975 uint8_t random_a_and_b[16] = { 0 };
3976 des3_context ctx = { 0 };
3978 memcpy(random_a, RndA,8);
3980 uint8_t output[8] = { 0 };
3981 uint8_t iv[8] = { 0 };
3983 PrintAndLogEx(NORMAL, " RndA :%s",sprint_hex(random_a, 8));
3984 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(enc_random_b, 8));
3986 des3_set2key_dec(&ctx, key);
3988 des3_crypt_cbc(&ctx // des3_context *ctx
3989 , DES_DECRYPT // int mode
3990 , sizeof(random_b) // size_t length
3991 , iv // unsigned char iv[8]
3992 , enc_random_b // const unsigned char *input
3993 , random_b // unsigned char *output
3996 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(random_b, 8));
3999 memcpy(random_a_and_b ,random_a,8);
4000 memcpy(random_a_and_b+8,random_b,8);
4002 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(random_a_and_b, 16));
4004 des3_set2key_enc(&ctx, key);
4006 des3_crypt_cbc(&ctx // des3_context *ctx
4007 , DES_ENCRYPT // int mode
4008 , sizeof(random_a_and_b) // size_t length
4009 , enc_random_b // unsigned char iv[8]
4010 , random_a_and_b // const unsigned char *input
4011 , random_a_and_b // unsigned char *output
4014 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
4021 // Mifare Ultralight C - Set password
4023 static int CmdHF14AMfUCSetPwd(const char *Cmd
) {
4024 CLIParserContext
*ctx
;
4025 CLIParserInit(&ctx
, "hf mfu setpwd",
4026 "Set the 3DES key on MIFARE Ultralight-C tag. ",
4027 "hf mfu setpwd --key 000102030405060708090a0b0c0d0e0f"
4030 void *argtable
[] = {
4032 arg_str0("k", "key", "<hex>", "New key (16 hex bytes)"),
4035 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4038 uint8_t key
[16] = {0x00};
4039 CLIGetHexWithReturn(ctx
, 1, key
, &k_len
);
4043 PrintAndLogEx(WARNING
, "Key must be 16 hex bytes");
4047 clearCommandBuffer();
4048 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD
, 0, 0, 0, key
, sizeof(key
));
4050 PacketResponseNG resp
;
4051 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4052 if ((resp
.oldarg
[0] & 0xff) == 1) {
4053 PrintAndLogEx(INFO
, "Ultralight-C new key... " _GREEN_("%s"), sprint_hex_inrow(key
, sizeof(key
)));
4055 PrintAndLogEx(WARNING
, "Failed writing at block %u", (uint8_t)(resp
.oldarg
[1] & 0xFF));
4059 PrintAndLogEx(WARNING
, "command execute timeout");
4060 return PM3_ETIMEOUT
;
4066 // Magic UL / UL-C tags - Set UID
4068 static int CmdHF14AMfUCSetUid(const char *Cmd
) {
4070 CLIParserContext
*ctx
;
4071 CLIParserInit(&ctx
, "hf mfu setuid",
4072 "Set UID on MIFARE Ultralight tag.\n"
4073 "This only works for `magic Ultralight` tags.",
4074 "hf mfu setuid --uid 11223344556677"
4077 void *argtable
[] = {
4079 arg_str0("u", "uid", "<hex>", "New UID (7 hex bytes)"),
4082 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4085 uint8_t uid
[7] = {0x00};
4086 CLIGetHexWithReturn(ctx
, 1, uid
, &u_len
);
4090 PrintAndLogEx(WARNING
, "UID must be 7 hex bytes");
4094 PrintAndLogEx(INFO
, "Please ignore possible transient BCC warnings");
4097 PacketResponseNG resp
;
4098 clearCommandBuffer();
4099 SendCommandMIX(CMD_HF_MIFAREU_READBL
, 2, 0, 0, NULL
, 0);
4100 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4101 PrintAndLogEx(WARNING
, "Command execute timeout");
4102 return PM3_ETIMEOUT
;
4106 uint8_t oldblock2
[4] = {0x00};
4107 memcpy(resp
.data
.asBytes
, oldblock2
, 4);
4109 // Enforce bad BCC handling temporarily as BCC will be wrong between
4110 // block 1 write and block2 write
4111 hf14a_config config
;
4112 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG
, NULL
, 0);
4113 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG
, &resp
, 2000)) {
4114 PrintAndLogEx(WARNING
, "command execute timeout");
4115 return PM3_ETIMEOUT
;
4117 memcpy(&config
, resp
.data
.asBytes
, sizeof(hf14a_config
));
4118 int8_t oldconfig_bcc
= config
.forcebcc
;
4119 if (oldconfig_bcc
!= 2) {
4120 config
.forcebcc
= 2;
4121 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG
, (uint8_t *)&config
, sizeof(hf14a_config
));
4129 data
[3] = 0x88 ^ uid
[0] ^ uid
[1] ^ uid
[2];
4130 clearCommandBuffer();
4131 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, 0, 0, 0, data
, sizeof(data
));
4132 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4133 PrintAndLogEx(WARNING
, "Command execute timeout");
4134 return PM3_ETIMEOUT
;
4142 clearCommandBuffer();
4143 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, 1, 0, 0, data
, sizeof(data
));
4144 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4145 PrintAndLogEx(WARNING
, "Command execute timeout");
4146 return PM3_ETIMEOUT
;
4150 data
[0] = uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6];
4151 data
[1] = oldblock2
[1];
4152 data
[2] = oldblock2
[2];
4153 data
[3] = oldblock2
[3];
4154 clearCommandBuffer();
4155 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, 2, 0, 0, data
, sizeof(data
));
4156 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4157 PrintAndLogEx(WARNING
, "Command execute timeout");
4158 return PM3_ETIMEOUT
;
4161 // restore BCC config
4162 if (oldconfig_bcc
!= 2) {
4163 config
.forcebcc
= oldconfig_bcc
;
4164 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG
, (uint8_t *)&config
, sizeof(hf14a_config
));
4169 static int CmdHF14AMfUKeyGen(const char *Cmd
) {
4170 CLIParserContext
*ctx
;
4171 CLIParserInit(&ctx
, "hf mfu keygen",
4172 "Calculate MFC keys based ",
4173 "hf mfu keygen -r\n"
4174 "hf mfu keygen --uid 11223344556677"
4177 void *argtable
[] = {
4179 arg_str0("u", "uid", "<hex>", "<4|7> hex byte UID"),
4180 arg_lit0("r", NULL
, "Read UID from tag"),
4181 arg_u64_0("b", "blk", "<dec>", "Block number"),
4184 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4188 CLIGetHexWithReturn(ctx
, 1, uid
, &ulen
);
4189 bool read_tag
= arg_get_lit(ctx
, 2);
4190 uint8_t block
= arg_get_u64_def(ctx
, 3, 1) & 0xFF;
4194 // read uid from tag
4195 clearCommandBuffer();
4196 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
4197 PacketResponseNG resp
;
4198 WaitForResponse(CMD_ACK
, &resp
);
4199 iso14a_card_select_t card
;
4200 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
4202 uint64_t select_status
= resp
.oldarg
[0];
4203 // 0: couldn't read,
4206 // 3: proprietary Anticollision
4208 if (select_status
== 0) {
4209 PrintAndLogEx(WARNING
, "iso14443a card select failed");
4213 if (card
.uidlen
!= 4 && card
.uidlen
!= 7) {
4214 PrintAndLogEx(WARNING
, "Wrong sized UID, expected 4|7 bytes got %d", card
.uidlen
);
4218 memcpy(uid
, card
.uid
, card
.uidlen
);
4220 if (ulen
!= 4 && ulen
!= 7) {
4221 PrintAndLogEx(ERR
, "Must supply 4 or 7 hex byte uid");
4226 uint8_t iv
[8] = { 0x00 };
4228 uint8_t mifarekeyA
[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
4229 uint8_t mifarekeyB
[] = { 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5 };
4230 uint8_t dkeyA
[8] = { 0x00 };
4231 uint8_t dkeyB
[8] = { 0x00 };
4233 uint8_t masterkey
[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
4234 uint8_t mix
[8] = { 0x00 };
4235 uint8_t divkey
[8] = { 0x00 };
4237 memcpy(mix
, mifarekeyA
, 4);
4239 mix
[4] = mifarekeyA
[4] ^ uid
[0];
4240 mix
[5] = mifarekeyA
[5] ^ uid
[1];
4241 mix
[6] = block
^ uid
[2];
4244 mbedtls_des3_context ctx_des3
;
4245 mbedtls_des3_set2key_enc(&ctx_des3
, masterkey
);
4247 mbedtls_des3_crypt_cbc(&ctx_des3
// des3_context
4248 , MBEDTLS_DES_ENCRYPT
// int mode
4249 , sizeof(mix
) // length
4255 PrintAndLogEx(SUCCESS
, "-- 3DES version");
4256 PrintAndLogEx(SUCCESS
, "Masterkey......... %s", sprint_hex(masterkey
, sizeof(masterkey
)));
4257 PrintAndLogEx(SUCCESS
, "UID............... %s", sprint_hex(uid
, ulen
));
4258 PrintAndLogEx(SUCCESS
, "block............. %0d", block
);
4259 PrintAndLogEx(SUCCESS
, "Mifare key........ %s", sprint_hex(mifarekeyA
, sizeof(mifarekeyA
)));
4260 PrintAndLogEx(SUCCESS
, "Message........... %s", sprint_hex(mix
, sizeof(mix
)));
4261 PrintAndLogEx(SUCCESS
, "Diversified key... %s", sprint_hex(divkey
+ 1, 6));
4263 for (int i
= 0; i
< ARRAYLEN(mifarekeyA
); ++i
) {
4264 dkeyA
[i
] = (mifarekeyA
[i
] << 1) & 0xff;
4265 dkeyA
[6] |= ((mifarekeyA
[i
] >> 7) & 1) << (i
+ 1);
4268 for (int i
= 0; i
< ARRAYLEN(mifarekeyB
); ++i
) {
4269 dkeyB
[1] |= ((mifarekeyB
[i
] >> 7) & 1) << (i
+ 1);
4270 dkeyB
[2 + i
] = (mifarekeyB
[i
] << 1) & 0xff;
4273 uint8_t zeros
[8] = {0x00};
4274 uint8_t newpwd
[8] = {0x00};
4275 uint8_t dmkey
[24] = {0x00};
4276 memcpy(dmkey
, dkeyA
, 8);
4277 memcpy(dmkey
+ 8, dkeyB
, 8);
4278 memcpy(dmkey
+ 16, dkeyA
, 8);
4279 memset(iv
, 0x00, 8);
4281 mbedtls_des3_set3key_enc(&ctx_des3
, dmkey
);
4283 mbedtls_des3_crypt_cbc(&ctx_des3
// des3_context
4284 , MBEDTLS_DES_ENCRYPT
// int mode
4285 , sizeof(newpwd
) // length
4291 PrintAndLogEx(SUCCESS
, "\n-- DES version");
4292 PrintAndLogEx(SUCCESS
, "MIFARE dkeyA...... %s", sprint_hex(dkeyA
, sizeof(dkeyA
)));
4293 PrintAndLogEx(SUCCESS
, "MIFARE dkeyB...... %s", sprint_hex(dkeyB
, sizeof(dkeyB
)));
4294 PrintAndLogEx(SUCCESS
, "MIFARE ABA........ %s", sprint_hex(dmkey
, sizeof(dmkey
)));
4295 PrintAndLogEx(SUCCESS
, "MIFARE PWD........ %s", sprint_hex(newpwd
, sizeof(newpwd
)));
4297 mbedtls_des3_free(&ctx_des3
);
4299 mbedtls_aes_context ctx_aes
;
4300 uint8_t aes_iv
[16] = { 0x00 };
4301 uint8_t aes_masterkey
[] = { 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
4302 uint8_t aes_input
[16] = {0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80, 0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80};
4303 uint8_t aes_output
[16] = {0x00};
4304 mbedtls_aes_setkey_enc(&ctx_aes
, aes_masterkey
, 128);
4305 mbedtls_aes_crypt_cbc(&ctx_aes
, MBEDTLS_AES_ENCRYPT
, 16, aes_iv
, aes_input
, aes_output
);
4306 mbedtls_aes_free(&ctx_aes
);
4308 PrintAndLogEx(SUCCESS
, "\n-- AES version");
4309 PrintAndLogEx(SUCCESS
, "MIFARE AES mk..... %s", sprint_hex(aes_masterkey
, sizeof(aes_masterkey
)));
4310 PrintAndLogEx(SUCCESS
, "MIFARE Div........ %s", sprint_hex(aes_output
, sizeof(aes_output
)));
4312 // next. from the diversify_key method.
4316 static int CmdHF14AMfUPwdGen(const char *Cmd
) {
4317 CLIParserContext
*ctx
;
4318 CLIParserInit(&ctx
, "hf mfu pwdgen",
4319 "Generate different passwords from known pwdgen algos",
4320 "hf mfu pwdgen -r\n"
4321 "hf mfu pwdgen --uid 11223344556677\n"
4322 "hf mfu pwdgen --test"
4325 void *argtable
[] = {
4327 arg_str0("u", "uid", "<hex>", "UID (7 hex bytes)"),
4328 arg_lit0("r", NULL
, "Read UID from tag"),
4329 arg_lit0(NULL
, "test", "self test"),
4332 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4335 uint8_t uid
[7] = {0x00};
4336 CLIGetHexWithReturn(ctx
, 1, uid
, &u_len
);
4337 bool use_tag
= arg_get_lit(ctx
, 2);
4338 bool selftest
= arg_get_lit(ctx
, 3);
4342 return generator_selftest();
4345 uint8_t philips_mfg
[10] = {0};
4348 // read uid from tag
4349 int res
= ul_read_uid(uid
);
4350 if (res
== PM3_ELENGTH
) {
4351 // got 4 byte UID, lets adapt to 7 bytes :)
4352 memset(uid
+ 4, 0x00, 3);
4356 if (res
!= PM3_SUCCESS
) {
4360 iso14a_card_select_t card
;
4361 if (ul_select(&card
)) {
4362 // Philips toothbrush needs page 0x21-0x23
4363 uint8_t data
[16] = {0x00};
4364 int status
= ul_read(0x21, data
, sizeof(data
));
4366 PrintAndLogEx(DEBUG
, "Error: tag didn't answer to READ");
4367 } else if (status
== 16) {
4368 memcpy(philips_mfg
, data
+ 2, sizeof(philips_mfg
));
4374 if (u_len
!= 7 && u_len
!= 4) {
4375 PrintAndLogEx(WARNING
, "Key must be 7 hex bytes");
4378 // adapt to 7 bytes :)
4379 memset(uid
+ 4, 0x00, 3);
4384 PrintAndLogEx(INFO
, "-----------------------------------");
4385 PrintAndLogEx(INFO
, " UID 4b... " _YELLOW_("%s"), sprint_hex(uid
, 4));
4386 PrintAndLogEx(INFO
, " UID 7b... " _YELLOW_("%s"), sprint_hex(uid
, 7));
4387 PrintAndLogEx(INFO
, "-----------------------------------");
4388 PrintAndLogEx(INFO
, " algo pwd pack");
4389 PrintAndLogEx(INFO
, "-----------------------------+-----");
4390 PrintAndLogEx(INFO
, " Transport EV1..... %08X | %04X", ul_ev1_pwdgenA(uid
), ul_ev1_packgenA(uid
));
4391 PrintAndLogEx(INFO
, " Amiibo............ %08X | %04X", ul_ev1_pwdgenB(uid
), ul_ev1_packgenB(uid
));
4392 PrintAndLogEx(INFO
, " Lego Dimension.... %08X | %04X", ul_ev1_pwdgenC(uid
), ul_ev1_packgenC(uid
));
4393 PrintAndLogEx(INFO
, " XYZ 3D printer.... %08X | %04X", ul_ev1_pwdgenD(uid
), ul_ev1_packgenD(uid
));
4394 PrintAndLogEx(INFO
, " Xiaomi purifier... %08X | %04X", ul_ev1_pwdgenE(uid
), ul_ev1_packgenE(uid
));
4395 PrintAndLogEx(INFO
, " NTAG tools........ %08X | %04X", ul_ev1_pwdgenF(uid
), ul_ev1_packgen_def(uid
));
4396 if (philips_mfg
[0] != 0) {
4397 PrintAndLogEx(INFO
, " Philips Toothbrush | %08X | %04X", ul_ev1_pwdgenG(uid
, philips_mfg
), ul_ev1_packgenG(uid
, philips_mfg
));
4399 PrintAndLogEx(INFO
, "-----------------------------+-----");
4400 PrintAndLogEx(INFO
, _CYAN_("Vingcard"));
4402 mfc_algo_saflok_one(uid
, 0, 0, &key
);
4403 PrintAndLogEx(INFO
, " Saflok algo | %012" PRIX64
, key
);
4404 PrintAndLogEx(INFO
, " SALTO algo");
4405 PrintAndLogEx(INFO
, " Dorma Kaba algo");
4406 PrintAndLogEx(INFO
, " STiD algo");
4407 PrintAndLogEx(INFO
, "-------------------------------------");
4412 // MFU TearOff against OTP
4415 static int CmdHF14AMfuOtpTearoff(const char *Cmd
) {
4416 CLIParserContext
*ctx
;
4417 CLIParserInit(&ctx
, "hf mfu otptear",
4418 "Tear-off test against OTP block",
4419 "hf mfu otptear -b 3\n"
4420 "hf mfu otptear -b 3 -i 100 -s 1000\n"
4421 "hf mfu otptear -b 3 -i 1 -e 200\n"
4422 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE\n"
4423 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quit when OTP is reset"
4426 void *argtable
[] = {
4428 arg_u64_0("b", "blk", "<dec>", "target block (def 8)"),
4429 arg_u64_0("i", "inc", "<dec>", "increase time steps (def 500 us)"),
4430 arg_u64_0("e", "end", "<dec>", "end time (def 3000 us)"),
4431 arg_u64_0("s", "start", "<dec>", "start time (def 0 us)"),
4432 arg_str0("d", "data", "<hex>", "initialise data before run (4 bytes)"),
4433 arg_str0("t", "test", "<hex>", "test write data (4 bytes, 00000000 by default)"),
4434 arg_str0("m", "match", "<hex>", "exit criteria, if block matches this value (4 bytes)"),
4437 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
4439 uint8_t blockno
= arg_get_u32_def(ctx
, 1, 8);
4440 uint32_t steps
= arg_get_u32_def(ctx
, 2, 500);
4441 uint32_t end
= arg_get_u32_def(ctx
, 3, 3000);
4442 uint32_t start
= arg_get_u32_def(ctx
, 4, 0);
4445 uint8_t data
[4] = {0x00};
4446 CLIGetHexWithReturn(ctx
, 5, data
, &d_len
);
4447 bool use_data
= (d_len
> 0);
4450 uint8_t test
[4] = {0x00};
4451 CLIGetHexWithReturn(ctx
, 6, test
, &t_len
);
4454 uint8_t match
[4] = {0x00};
4455 CLIGetHexWithReturn(ctx
, 7, match
, &m_len
);
4456 bool use_match
= (m_len
> 0);
4460 PrintAndLogEx(WARNING
, "Block number must be larger than 2.");
4464 PrintAndLogEx(WARNING
, "end time smaller than increase value");
4468 PrintAndLogEx(WARNING
, "end time - out of 1 .. 43000 range");
4471 if (start
> (end
- steps
)) {
4472 PrintAndLogEx(WARNING
, "Start time larger than (end time + steps)");
4476 if (d_len
&& d_len
!= 4) {
4477 PrintAndLogEx(WARNING
, "data must be 4 hex bytes");
4481 if (t_len
&& t_len
!= 4) {
4482 PrintAndLogEx(WARNING
, "test data must be 4 hex bytes");
4486 if (m_len
&& m_len
!= 4) {
4487 PrintAndLogEx(WARNING
, "match data must be 4 hex bytes");
4491 uint8_t teardata
[4] = {0x00};
4492 memcpy(teardata
, test
, sizeof(test
));
4494 PrintAndLogEx(INFO
, "----------------- " _CYAN_("MFU Tear off") " ---------------------");
4495 PrintAndLogEx(INFO
, "Starting Tear-off test");
4496 PrintAndLogEx(INFO
, "Target block no: %u", blockno
);
4498 PrintAndLogEx(INFO
, "Target initial block data : %s", sprint_hex_inrow(data
, 4));
4500 PrintAndLogEx(INFO
, "Target write block data : %s", sprint_hex_inrow(teardata
, 4));
4502 PrintAndLogEx(INFO
, "Target match block data : %s", sprint_hex_inrow(match
, 4));
4504 PrintAndLogEx(INFO
, "----------------------------------------------------");
4506 bool lock_on
= false;
4507 uint8_t pre
[4] = {0};
4508 uint8_t post
[4] = {0};
4509 uint32_t current
= start
;
4510 int phase_begin_clear
= -1;
4511 int phase_end_clear
= -1;
4512 int phase_begin_newwr
= -1;
4513 int phase_end_newwr
= -1;
4514 bool skip_phase1
= false;
4515 uint8_t retries
= 0;
4516 uint8_t error_retries
= 0;
4518 while ((current
<= (end
- steps
)) && (error_retries
< 10)) {
4520 if (kbd_enter_pressed()) {
4521 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
4525 PrintAndLogEx(INFO
, "Using tear-off delay " _GREEN_("%" PRIu32
) " us", current
);
4527 clearCommandBuffer();
4528 PacketResponseNG resp
;
4531 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, blockno
, 0, 0, data
, d_len
);
4532 bool got_written
= false;
4533 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4534 isOK
= resp
.oldarg
[0] & 0xff;
4539 if (! got_written
) {
4540 PrintAndLogEx(FAILED
, "Failed to write block BEFORE");
4542 continue; // try again
4546 SendCommandMIX(CMD_HF_MIFAREU_READBL
, blockno
, 0, 0, NULL
, 0);
4548 bool got_pre
= false;
4549 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4550 isOK
= resp
.oldarg
[0] & 0xFF;
4552 memcpy(pre
, resp
.data
.asBytes
, sizeof(pre
));
4557 PrintAndLogEx(FAILED
, "Failed to read block BEFORE");
4559 continue; // try again
4561 clearCommandBuffer();
4562 SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF
, blockno
, current
, 0, teardata
, sizeof(teardata
));
4564 // we be getting ACK that we are silently ignoring here..
4566 if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF
, &resp
, 2000)) {
4567 PrintAndLogEx(WARNING
, "Failed");
4571 if (resp
.status
!= PM3_SUCCESS
) {
4572 PrintAndLogEx(WARNING
, "Tear off reporting failure to select tag");
4577 bool got_post
= false;
4578 clearCommandBuffer();
4579 SendCommandMIX(CMD_HF_MIFAREU_READBL
, blockno
, 0, 0, NULL
, 0);
4580 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
4581 isOK
= resp
.oldarg
[0] & 0xFF;
4583 memcpy(post
, resp
.data
.asBytes
, sizeof(post
));
4588 PrintAndLogEx(FAILED
, "Failed to read block BEFORE");
4590 continue; // try again
4593 char prestr
[20] = {0};
4594 snprintf(prestr
, sizeof(prestr
), "%s", sprint_hex_inrow(pre
, sizeof(pre
)));
4595 char poststr
[20] = {0};
4596 snprintf(poststr
, sizeof(poststr
), "%s", sprint_hex_inrow(post
, sizeof(post
)));
4598 if (memcmp(pre
, post
, sizeof(pre
)) == 0) {
4600 PrintAndLogEx(INFO
, "Current : %02d (0x%02X) %s"
4606 PrintAndLogEx(INFO
, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s")
4615 uint32_t post32
= bytes_to_num(post
, 4);
4616 uint32_t pre32
= bytes_to_num(pre
, 4);
4618 if ((phase_begin_clear
== -1) && (bitcount32(pre32
) > bitcount32(post32
)))
4619 phase_begin_clear
= current
;
4621 if ((phase_begin_clear
> -1) && (phase_end_clear
== -1) && (bitcount32(post32
) == 0))
4622 phase_end_clear
= current
;
4624 if ((current
== start
) && (phase_end_clear
> -1))
4626 // new write phase must be atleast 100us later..
4627 if (((bitcount32(pre32
) == 0) || (phase_end_clear
> -1)) && (phase_begin_newwr
== -1) && (bitcount32(post32
) != 0) && (skip_phase1
|| (current
> (phase_end_clear
+ 100))))
4628 phase_begin_newwr
= current
;
4630 if ((phase_begin_newwr
> -1) && (phase_end_newwr
== -1) && (memcmp(post
, teardata
, sizeof(teardata
)) == 0))
4631 phase_end_newwr
= current
;
4634 if (use_match
&& memcmp(post
, match
, sizeof(post
)) == 0) {
4635 PrintAndLogEx(SUCCESS
, "Block matches stop condition!\n");
4639 /* TEMPORALLY DISABLED
4640 uint8_t d0, d1, d2, d3;
4641 d0 = *resp.data.asBytes;
4642 d1 = *(resp.data.asBytes + 1);
4643 d2 = *(resp.data.asBytes + 2);
4644 d3 = *(resp.data.asBytes + 3);
4645 if ((d0 != 0xFF) || (d1 != 0xFF) || (d2 != 0xFF) || (d3 = ! 0xFF)) {
4646 PrintAndLogEx(NORMAL, "---------------------------------");
4647 PrintAndLogEx(NORMAL, " EFFECT AT: %d us", actualTime);
4648 PrintAndLogEx(NORMAL, "---------------------------------\n");
4654 if (lock_on
== false) {
4655 if (++retries
== 20) {
4660 PrintAndLogEx(INFO
, _CYAN_("Retried %u times, increased delay with 1us"), retries
);
4666 PrintAndLogEx(INFO
, "----------------------------------------------------");
4667 if ((phase_begin_clear
> - 1) && (phase_begin_clear
!= start
)) {
4668 PrintAndLogEx(INFO
, "Erase phase start boundary around " _YELLOW_("%5d") " us", phase_begin_clear
);
4670 if ((phase_end_clear
> - 1) && (phase_end_clear
!= start
)) {
4671 PrintAndLogEx(INFO
, "Erase phase end boundary around " _YELLOW_("%5d") " us", phase_end_clear
);
4673 if (phase_begin_newwr
> - 1) {
4674 PrintAndLogEx(INFO
, "Write phase start boundary around " _YELLOW_("%5d") " us", phase_begin_newwr
);
4676 if (phase_end_newwr
> - 1) {
4677 PrintAndLogEx(INFO
, "Write phase end boundary around " _YELLOW_("%5d") " us", phase_end_newwr
);
4679 PrintAndLogEx(NORMAL
, "");
4684 static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
4686 PrintAndLogEx(INFO, "Reset tear check");
4688 uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00};
4689 uint8_t ct[1] = {0};
4690 uint8_t resp[10] = {0};
4692 if (ul_select(card) == false) {
4693 PrintAndLogEx(FAILED, "failed to select card, exiting...");
4696 if (ul_send_cmd_raw(cw, sizeof(cw), resp, sizeof(resp)) < 0) {
4697 PrintAndLogEx(FAILED, "failed to write all ZEROS");
4700 if (ulev1_readTearing(cnt_no, ct, sizeof(ct)) < 0) {
4701 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
4706 if (ct[0] != 0xBD) {
4707 PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
4715 static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
4717 CLIParserContext *ctx;
4718 CLIParserInit(&ctx, "hf mfu countertear",
4719 "Tear-off test against a Ev1 counter",
4720 "hf mfu countertear\n"
4721 "hf mfu countertear -s 200 -l 2500 -> target counter 0, start delay 200\n"
4722 "hf mfu countertear -i 2 -s 200 -l 400 -> target counter 0, start delay 200\n"
4725 void *argtable[] = {
4727 arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
4728 arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
4729 arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
4730 arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
4731 arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"),
4732 arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"),
4735 CLIExecWithReturn(ctx, Cmd, argtable, false);
4738 int time_limit, start_time = 0;
4739 int counter = arg_get_int_def(ctx, 1, 0);
4740 int fixed = arg_get_int_def(ctx, 5, -1);
4742 if ( fixed == -1 ) {
4743 interval = arg_get_int_def(ctx, 2, 10);
4744 time_limit = arg_get_int_def(ctx, 3, 3000);
4745 start_time = arg_get_int_def(ctx, 4, 0);
4752 uint8_t newvalue[5] = {0};
4753 int newvaluelen = 0;
4754 CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
4758 if (start_time > (time_limit - interval)) {
4759 PrintAndLogEx(WARNING, "Wrong start time number");
4762 if (time_limit < interval) {
4763 PrintAndLogEx(WARNING, "Wrong time limit number");
4766 if (time_limit > 43000) {
4767 PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
4771 if (counter < 0 || counter > 2) {
4772 PrintAndLogEx(WARNING, "Counter must 0, 1 or 2");
4776 cnt_no = (uint8_t)counter;
4778 iso14a_card_select_t card;
4780 // reset counter tear
4781 counter_reset_tear(&card, cnt_no);
4783 if (ul_select(&card) == false) {
4784 PrintAndLogEx(INFO, "failed to select card, exiting...");
4788 uint8_t initial_cnt[3] = {0, 0, 0};
4789 int len = ulev1_readCounter(cnt_no, initial_cnt, sizeof(initial_cnt));
4790 if ( len != sizeof(initial_cnt) ) {
4791 PrintAndLogEx(WARNING, "failed to read counter");
4795 uint8_t initial_tear[1] = {0};
4796 len = ulev1_readTearing(cnt_no, initial_tear, sizeof(initial_tear));
4798 if ( len != sizeof(initial_tear) ) {
4799 PrintAndLogEx(WARNING, "failed to read ANTITEAR, exiting... %d", len);
4803 uint32_t wr_value = ( newvalue[0] | newvalue[1] << 8 | newvalue[2] << 16 );
4804 uint32_t initial_value = ( initial_cnt[0] | initial_cnt[1] << 8 | initial_cnt[2] << 16 );;
4806 PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
4807 PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter);
4808 PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(initial_cnt, sizeof(initial_cnt)));
4809 PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", initial_tear[0]);
4810 PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen));
4811 PrintAndLogEx(INFO, "----------------------------------------------------");
4813 uint8_t pre_tear = 0, post_tear = 0;
4814 uint8_t pre[3] = {0};
4815 uint8_t post[3] = {0};
4816 uint32_t actual_time = start_time;
4817 uint32_t a = 0, b = 0;
4822 while (actual_time <= (time_limit - interval)) {
4828 if (kbd_enter_pressed()) {
4829 PrintAndLogEx(INFO, "\naborted via keyboard!\n");
4833 PrintAndLogEx(INPLACE, "Using tear-off delay " _GREEN_("%" PRIu32) " µs (attempt %u)", actual_time, loop);
4835 if (ul_select(&card) == false) {
4836 PrintAndLogEx(FAILED, "BEFORE, failed to select card, looping...");
4840 uint8_t cntresp[3] = {0, 0, 0};
4841 int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
4842 if ( rlen == sizeof(cntresp) ) {
4843 memcpy(pre, cntresp, sizeof(pre));
4845 PrintAndLogEx(NORMAL, "");
4846 PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
4850 uint8_t tear[1] = {0};
4851 int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
4852 if ( tlen == sizeof(tear) ) {
4855 PrintAndLogEx(NORMAL, "");
4856 PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
4864 uint32_t tearoff_time;
4867 payload.counter = cnt_no;
4868 payload.tearoff_time = actual_time;
4869 memcpy(payload.value, newvalue, sizeof(payload.value));
4871 clearCommandBuffer();
4872 PacketResponseNG resp;
4873 SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
4874 if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
4875 PrintAndLogEx(WARNING, "\ntear off command failed");
4879 if (ul_select(&card) == false) {
4880 PrintAndLogEx(FAILED, "AFTER, failed to select card, exiting...");
4884 rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
4885 if ( rlen == sizeof(cntresp) ) {
4886 memcpy(post, cntresp, sizeof(post));
4888 PrintAndLogEx(NORMAL, "");
4889 PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
4894 tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
4895 if ( tlen == sizeof(tear) ) {
4896 post_tear = tear[0];
4898 PrintAndLogEx(NORMAL, "");
4899 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
4905 char prestr[20] = {0};
4906 snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
4907 char poststr[20] = {0};
4908 snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
4910 bool post_tear_check = (post_tear == 0xBD);
4911 a = (pre[0] | pre[1] << 8 | pre[2] << 16);
4912 b = (post[0] | post[1] << 8 | post[2] << 16);
4915 if (memcmp(pre, post, sizeof(pre)) != 0) {
4918 PrintAndLogEx(NORMAL, "");
4920 if (initial_value != a ) {
4922 if ( initial_value != b )
4923 PrintAndLogEx(INFO, "pre %08x, post %08x != initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4925 PrintAndLogEx(INFO, "pre %08x != initial and post %08x == initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4928 if ( initial_value != b )
4929 PrintAndLogEx(INFO, "pre %08x == initial and post %08x != initial %08x | tear: 0x%02X == 0x%02X", a, b, initial_value, pre_tear, post_tear);
4933 PrintAndLogEx(INFO, _CYAN_("Tear off occurred (ZEROS value!) -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
4938 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4944 PrintAndLogEx(INFO, _CYAN_("Tear off occurred " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
4949 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4953 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
4954 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
4958 uint32_t bar = (0x1000000 - b) + 2;
4960 // newvalue[0] = (bar) & 0xFF;
4961 // newvalue[1] = ((bar >> 8) & 0xFF);
4962 // newvalue[2] = ((bar >> 16) & 0xFF);
4969 PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar);
4970 PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value);
4971 PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b);
4973 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
4977 PrintAndLogEx(NORMAL, "");
4978 PrintAndLogEx(INFO, _CYAN_("Tear off occurred (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
4983 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
4986 if ( post_tear_check && b == initial_value) {
4987 PrintAndLogEx(INFO, "Reverted to previous value");
4990 if ( wr_value != 0 ) {
4992 //uint32_t bar = (0x1000000 - b) + 2;
4998 if ( b >= (initial_value + (2 * wr_value))) {
4999 PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
5003 // newvalue[0] = (bar) & 0xFF;
5004 // newvalue[1] = ((bar >> 8) & 0xFF);
5005 // newvalue[2] = ((bar >> 16) & 0xFF);
5009 // newvalue[0] = (bar) & 0xFF;
5010 // newvalue[1] = ((bar >> 8) & 0xFF);
5011 // newvalue[2] = ((bar >> 16) & 0xFF);
5019 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
5025 PrintAndLogEx(NORMAL, "");
5026 PrintAndLogEx(INFO, _CYAN_("Status: same value! -> ") "%s == %s Tear: 0x%02X == 0x%02X ( %s )"
5031 , post_tear_check ? _GREEN_("ok") : _RED_("DETECTED")
5034 if ( post_tear_check ) {
5040 if ( b == initial_value ) {
5041 PrintAndLogEx(INFO, "Reverted to previous value");
5046 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
5047 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
5054 actual_time += interval;
5059 PrintAndLogEx(INFO, " Sent %u tear offs ", loop);
5061 counter_reset_tear(&card, cnt_no);
5063 PrintAndLogEx(INFO, "hf 14a raw -s -c 3900 --> read counter 0");
5064 PrintAndLogEx(INFO, "hf 14a raw -s -c 3e00 --> read tearing 0");
5065 PrintAndLogEx(NORMAL, "");
5066 char read_cnt_str[30];
5067 snprintf(read_cnt_str, sizeof(read_cnt_str), "hf 14a raw -s -c 39%02x", counter);
5068 CommandReceived(read_cnt_str);
5069 char read_tear_str[30];
5070 snprintf(read_tear_str, sizeof(read_tear_str), "hf 14a raw -s -c 3e%02x", counter);
5071 CommandReceived(read_tear_str);
5078 // name, identifying bytes, decode function, hints text
5080 // 1. getversion data must match.
5081 // 2. magic bytes in the readable payload
5084 int CmdHF14MfuNDEFRead(const char *Cmd
) {
5087 int maxsize
= 16, status
;
5088 bool hasAuthKey
= false;
5089 bool swapEndian
= false;
5091 iso14a_card_select_t card
;
5092 uint8_t data
[16] = {0x00};
5093 uint8_t key
[16] = {0x00};
5094 uint8_t *p_key
= key
;
5095 uint8_t pack
[4] = {0, 0, 0, 0};
5097 CLIParserContext
*ctx
;
5098 CLIParserInit(&ctx
, "hf mfu ndefread",
5099 "Prints NFC Data Exchange Format (NDEF)",
5100 "hf mfu ndefread -> shows NDEF data\n"
5101 "hf mfu ndefread -k ffffffff -> shows NDEF data with key\n"
5102 "hf mfu ndefread -f myfilename -> save raw NDEF to file"
5105 void *argtable
[] = {
5107 arg_str0("k", "key", "Replace default key for NDEF", NULL
),
5108 arg_lit0("l", NULL
, "Swap entered key's endianness"),
5109 arg_str0("f", "file", "<fn>", "Save raw NDEF to file"),
5110 arg_lit0("v", "verbose", "Verbose output"),
5113 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
5114 CLIGetHexWithReturn(ctx
, 1, key
, &keylen
);
5115 swapEndian
= arg_get_lit(ctx
, 2);
5117 char filename
[FILE_PATH_SIZE
] = {0};
5118 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
5119 bool verbose
= arg_get_lit(ctx
, 4);
5130 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
5135 uint64_t tagtype
= GetHF14AMfU_Type();
5136 if (tagtype
== MFU_TT_UL_ERROR
) {
5137 PrintAndLogEx(WARNING
, "No Ultralight / NTAG based tag found");
5144 if (swapEndian
&& hasAuthKey
) p_key
= SwapEndian64(key
, keylen
, (keylen
== 16) ? 8 : 4);
5147 if (ul_auth_select(&card
, tagtype
, hasAuthKey
, p_key
, pack
, sizeof(pack
)) == PM3_ESOFT
) return PM3_ESOFT
;
5149 // read pages 0,1,2,3 (should read 4pages)
5150 status
= ul_read(0, data
, sizeof(data
));
5153 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ");
5155 } else if (status
== 16) {
5157 status
= ndef_print_CC(data
+ 12);
5158 if (status
== PM3_ESOFT
) {
5160 PrintAndLogEx(ERR
, "Error: tag didn't contain a NDEF Container");
5165 maxsize
= ndef_get_maxsize(data
+ 12);
5168 // iceman: maybe always take MIN of tag identified size vs NDEF reported size?
5169 // fix: UL_EV1 48bytes != NDEF reported size
5170 for (uint8_t idx
= 1; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
5171 if ((tagtype
& UL_TYPES_ARRAY
[idx
]) == UL_TYPES_ARRAY
[idx
]) {
5173 if (maxsize
!= (UL_MEMORY_ARRAY
[idx
] * 4)) {
5174 PrintAndLogEx(INFO
, "Tag reported size vs NDEF reported size mismatch. Using smallest value");
5176 maxsize
= MIN(maxsize
, (UL_MEMORY_ARRAY
[idx
] * 4));
5181 // The following read will read in blocks of 16 bytes.
5182 // ensure maxsize is rounded up to a multiple of 16
5183 maxsize
= maxsize
+ (16 - (maxsize
% 16));
5185 uint8_t *records
= calloc(maxsize
, sizeof(uint8_t));
5186 if (records
== NULL
) {
5191 // read NDEF records.
5192 for (uint32_t i
= 0, j
= 0; i
< maxsize
; i
+= 16, j
+= 4) {
5193 status
= ul_read(4 + j
, records
+ i
, 16);
5196 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ");
5204 status
= NDEFRecordsDecodeAndPrint(records
, (size_t)maxsize
, verbose
);
5205 if (status
!= PM3_SUCCESS
) {
5206 status
= NDEFDecodeAndPrint(records
, (size_t)maxsize
, verbose
);
5209 // get total NDEF length before save. If fails, we save it all
5211 if (NDEFGetTotalLength(records
, maxsize
, &n
) != PM3_SUCCESS
)
5214 pm3_save_dump(filename
, records
, n
, jsfNDEF
);
5217 char *jooki
= strstr((char *)records
, "s.jooki.rocks/s/?s=");
5221 if ((*jooki
) != '=')
5226 strncpy(s
, jooki
, 16);
5227 PrintAndLogEx(HINT
, "Use `" _YELLOW_("hf jooki decode -d %s") "` to decode", s
);
5232 char *mattel
= strstr((char *)records
, ".pid.mattel/");
5236 if ((*mattel
) != '/')
5241 strncpy(b64
, mattel
, 32);
5242 uint8_t arr
[24] = {0};
5244 mbedtls_base64_decode(arr
, sizeof(arr
), &arrlen
, (const unsigned char *)b64
, 32);
5246 PrintAndLogEx(INFO
, "decoded... %s", sprint_hex(arr
, arrlen
));
5256 // utility function. Retrieves emulator memory
5257 static int GetMfuDumpFromEMul(mfu_dump_t
**buf
) {
5259 mfu_dump_t
*dump
= calloc(1, sizeof(mfu_dump_t
));
5261 PrintAndLogEx(WARNING
, "Fail, cannot allocate memory");
5265 PrintAndLogEx(INFO
, "downloading from emulator memory");
5266 if (!GetFromDevice(BIG_BUF_EML
, (uint8_t *)dump
, MFU_MAX_BYTES
+ MFU_DUMP_PREFIX_LENGTH
, 0, NULL
, 0, NULL
, 2500, false)) {
5267 PrintAndLogEx(WARNING
, "Fail, transfer from device time-out");
5269 return PM3_ETIMEOUT
;
5273 return PM3_SUCCESS
;
5276 static int CmdHF14AMfuEView(const char *Cmd
) {
5277 CLIParserContext
*ctx
;
5278 CLIParserInit(&ctx
, "hf mfu eview",
5279 "Displays emulator memory\n"
5280 "By default number of pages shown depends on defined tag type.\n"
5281 "You can override this with option --end.",
5283 "hf mfu eview --end 255 -> dumps whole memory"
5286 void *argtable
[] = {
5288 arg_int0("e", "end", "<dec>", "index of last block"),
5289 arg_lit0("z", "dense", "dense dump output style"),
5293 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
5294 int end
= arg_get_int_def(ctx
, 1, -1);
5295 bool dense_output
= (g_session
.dense_output
|| arg_get_lit(ctx
, 2));
5298 bool override_end
= (end
!= -1) ;
5300 if (override_end
&& (end
< 0 || end
> MFU_MAX_BLOCKS
)) {
5301 PrintAndLogEx(WARNING
, "Invalid value for end: %d Must be be positive integer < %d", end
, MFU_MAX_BLOCKS
);
5302 return PM3_EINVARG
;
5306 int res
= GetMfuDumpFromEMul(&dump
) ;
5307 if (res
!= PM3_SUCCESS
) {
5314 end
= dump
->pages
+ 1;
5317 mfu_print_dump(dump
, end
, 0, dense_output
);
5322 static int CmdHF14AMfuESave(const char *Cmd
) {
5323 CLIParserContext
*ctx
;
5324 CLIParserInit(&ctx
, "hf mfu esave",
5325 "Saves emulator memory to a MIFARE Ultralight/NTAG dump file (bin/json)\n"
5326 "By default number of pages saved depends on defined tag type.\n"
5327 "You can override this with option --end.",
5329 "hf mfu esave --end 255 -> saves whole memory\n"
5330 "hf mfu esave -f hf-mfu-04010203040506-dump"
5333 void *argtable
[] = {
5335 arg_int0("e", "end", "<dec>", "index of last block"),
5336 arg_str0("f", "file", "<fn>", "Specify a filename for dump file"),
5340 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
5341 int end
= arg_get_int_def(ctx
, 1, -1);
5343 char filename
[FILE_PATH_SIZE
];
5345 CLIParamStrToBuf(arg_get_str(ctx
, 2), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
5349 bool override_end
= (end
!= -1) ;
5351 if (override_end
&& (end
< 0 || end
> MFU_MAX_BLOCKS
)) {
5352 PrintAndLogEx(WARNING
, "Invalid value for end:%d. Must be be positive integer <= %d.", end
, MFU_MAX_BLOCKS
);
5353 return PM3_EINVARG
;
5356 // get dump from memory
5358 int res
= GetMfuDumpFromEMul(&dump
) ;
5359 if (res
!= PM3_SUCCESS
) {
5363 // initialize filename
5365 PrintAndLogEx(INFO
, "Using UID as filename");
5366 uint8_t uid
[7] = {0};
5367 memcpy(uid
, (uint8_t *) & (dump
->data
), 3);
5368 memcpy(uid
+ 3, (uint8_t *) & (dump
->data
) + 4, 4);
5369 strcat(filename
, "hf-mfu-");
5370 FillFileNameByUID(filename
, uid
, "-dump", sizeof(uid
));
5379 // save dump. Last block contains PACK + RFU
5380 uint16_t datalen
= (end
+ 1) * MFU_BLOCK_SIZE
+ MFU_DUMP_PREFIX_LENGTH
;
5381 res
= pm3_save_dump(filename
, (uint8_t *)dump
, datalen
, jsfMfuMemory
);
5387 static int CmdHF14AMfuView(const char *Cmd
) {
5389 CLIParserContext
*ctx
;
5390 CLIParserInit(&ctx
, "hf mfu view",
5391 "Print a MIFARE Ultralight/NTAG dump file (bin/eml/json)",
5392 "hf mfu view -f hf-mfu-01020304-dump.bin"
5394 void *argtable
[] = {
5396 arg_str1("f", "file", "<fn>", "Specify a filename for dump file"),
5397 arg_lit0("v", "verbose", "Verbose output"),
5398 arg_lit0("z", "dense", "dense dump output style"),
5401 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
5403 char filename
[FILE_PATH_SIZE
];
5404 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
5405 bool verbose
= arg_get_lit(ctx
, 2);
5406 bool dense_output
= (g_session
.dense_output
|| arg_get_lit(ctx
, 3));
5410 uint8_t *dump
= NULL
;
5411 size_t bytes_read
= 0;
5412 int res
= pm3_load_dump(filename
, (void **)&dump
, &bytes_read
, (MFU_MAX_BYTES
+ MFU_DUMP_PREFIX_LENGTH
));
5413 if (res
!= PM3_SUCCESS
) {
5417 if (bytes_read
< MFU_DUMP_PREFIX_LENGTH
) {
5418 PrintAndLogEx(ERR
, "Error, dump file is too small");
5423 res
= convert_mfu_dump_format(&dump
, &bytes_read
, verbose
);
5424 if (res
!= PM3_SUCCESS
) {
5425 PrintAndLogEx(FAILED
, "Failed convert on load to new Ultralight/NTAG format");
5430 uint16_t block_cnt
= ((bytes_read
- MFU_DUMP_PREFIX_LENGTH
) / MFU_BLOCK_SIZE
);
5433 PrintAndLogEx(INFO
, "File: " _YELLOW_("%s"), filename
);
5434 PrintAndLogEx(INFO
, "File size %zu bytes, file blocks %d (0x%x)", bytes_read
, block_cnt
, block_cnt
);
5437 mfu_print_dump((mfu_dump_t
*)dump
, block_cnt
, 0, dense_output
);
5442 static int CmdHF14AMfuList(const char *Cmd
) {
5443 return CmdTraceListAlias(Cmd
, "hf 14a", "14a -c");
5446 static int CmdHF14AAmiibo(const char *Cmd
) {
5448 CLIParserContext
*ctx
;
5449 CLIParserInit(&ctx
, "hf mfu amiibo",
5450 "Tries to read all memory from amiibo tag and decrypt it",
5451 "hf mfu amiiboo --dec -f hf-mfu-04579DB27C4880-dump.bin --> decrypt file\n"
5452 "hf mfu amiiboo -v --dec --> decrypt tag"
5455 void *argtable
[] = {
5457 arg_lit0(NULL
, "dec", "Decrypt memory"),
5458 arg_lit0(NULL
, "enc", "Encrypt memory"),
5459 arg_str0("i", "in", "<fn>", "Specify a filename for input dump file"),
5460 arg_str0("o", "out", "<fn>", "Specify a filename for output dump file"),
5461 arg_lit0("v", "verbose", "Verbose output"),
5464 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
5466 bool shall_decrypt
= arg_get_lit(ctx
, 1);
5467 bool shall_encrypt
= arg_get_lit(ctx
, 2);
5470 char infilename
[FILE_PATH_SIZE
];
5471 CLIParamStrToBuf(arg_get_str(ctx
, 3), (uint8_t *)infilename
, FILE_PATH_SIZE
, &infnlen
);
5474 char outfilename
[FILE_PATH_SIZE
];
5475 CLIParamStrToBuf(arg_get_str(ctx
, 4), (uint8_t *)outfilename
, FILE_PATH_SIZE
, &outfnlen
);
5477 bool verbose
= arg_get_lit(ctx
, 5);
5481 if ((shall_decrypt
+ shall_encrypt
) > 1) {
5482 PrintAndLogEx(WARNING
, "Only specify decrypt or encrypt");
5487 nfc3d_amiibo_keys_t amiibo_keys
;
5488 if (nfc3d_amiibo_load_keys(&amiibo_keys
) == false) {
5489 PrintAndLogEx(INFO
, "loading key file ( " _RED_("fail") " )");
5493 int res
= PM3_ESOFT
;
5495 uint8_t original
[NFC3D_AMIIBO_SIZE
] = {0};
5497 // load dump file if available
5499 uint8_t *dump
= NULL
;
5501 res
= loadFile_safe(infilename
, "", (void **)&dump
, &dumplen
);
5502 if (res
!= PM3_SUCCESS
) {
5507 if (dumplen
< MFU_DUMP_PREFIX_LENGTH
) {
5508 PrintAndLogEx(ERR
, "Error, dump file is too small");
5513 res
= convert_mfu_dump_format(&dump
, &dumplen
, verbose
);
5514 if (res
!= PM3_SUCCESS
) {
5515 PrintAndLogEx(FAILED
, "Failed convert on load to new Ultralight/NTAG format");
5520 mfu_dump_t
*d
= (mfu_dump_t
*)dump
;
5521 memcpy(original
, d
->data
, sizeof(original
));
5525 uint8_t *dump
= NULL
;
5526 res
= mfu_dump_tag(MAX_NTAG_215
, (void **)&dump
, &dlen
);
5527 if (res
!= PM3_SUCCESS
) {
5528 PrintAndLogEx(FAILED
, "Failed to dump memory from tag");
5532 memcpy(original
, dump
, sizeof(original
));
5537 uint8_t decrypted
[NFC3D_AMIIBO_SIZE
] = {0};
5538 if (shall_decrypt
) {
5539 if (nfc3d_amiibo_unpack(&amiibo_keys
, original
, decrypted
) == false) {
5540 PrintAndLogEx(INFO
, "Tag signature ( " _RED_("fail") " )");
5545 for (uint8_t i
= 0; i
< (NFC3D_AMIIBO_SIZE
/ 16); i
++) {
5546 PrintAndLogEx(INFO
, "[%d] %s", i
, sprint_hex_ascii(decrypted
+ (i
* 16), 16));
5551 if (shall_encrypt
) {
5552 uint8_t encrypted
[NFC3D_AMIIBO_SIZE
] = {0};
5553 nfc3d_amiibo_pack(&amiibo_keys
, decrypted
, encrypted
);
5556 for (uint8_t i
= 0; i
< (NFC3D_AMIIBO_SIZE
/ 16); i
++) {
5557 PrintAndLogEx(INFO
, "[%d] %s", i
, sprint_hex_ascii(encrypted
+ (i
* 16), 16));
5563 // save dump. Last block contains PACK + RFU
5564 // uint16_t datalen = MFU_BLOCK_SIZE + MFU_DUMP_PREFIX_LENGTH;
5565 // res = pm3_save_dump(outfilename, (uint8_t *)dump, datalen, jsfMfuMemory);
5571 static int CmdHF14AMfuWipe(const char *Cmd
) {
5572 CLIParserContext
*ctx
;
5573 CLIParserInit(&ctx
, "hf mfu wipe",
5574 "Wipe card to zeros. It will ignore block0,1,2,3\n"
5575 "you will need to call it with password in order to wipe the config and sett default pwd/pack\n"
5576 "Abort by pressing a key\n"
5577 "New password.... FFFFFFFF\n"
5578 "New 3-DES key... 49454D4B41455242214E4143554F5946\n",
5580 "hf mfu wipe -k 49454D4B41455242214E4143554F5946\n"
5582 void *argtable
[] = {
5584 arg_str0("k", "key", "<hex>", "Key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
5585 arg_lit0("l", NULL
, "Swap entered key's endianness"),
5588 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
5591 uint8_t authenticationkey
[16] = {0x00};
5592 uint8_t *auth_key_ptr
= authenticationkey
;
5593 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
5594 bool swap_endian
= arg_get_lit(ctx
, 2);
5598 bool has_auth_key
= false;
5599 bool has_pwd
= false;
5601 has_auth_key
= true;
5602 } else if (ak_len
== 4) {
5604 } else if (ak_len
!= 0) {
5605 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
5609 uint8_t card_mem_size
= 0;
5614 auth_key_ptr
= SwapEndian64(authenticationkey
, ak_len
, 8);
5618 auth_key_ptr
= SwapEndian64(authenticationkey
, ak_len
, 4);
5622 uint64_t tagtype
= GetHF14AMfU_Type();
5623 if (tagtype
== MFU_TT_UL_ERROR
) {
5627 // number of pages to WRITE
5628 for (uint8_t idx
= 1; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
5629 if ((tagtype
& UL_TYPES_ARRAY
[idx
]) == UL_TYPES_ARRAY
[idx
]) {
5630 //add one as maxblks starts at 0
5631 card_mem_size
= UL_MEMORY_ARRAY
[idx
] + 1;
5636 ul_print_type(tagtype
, 0);
5638 // GDM / GEN1A / GEN4 / NTAG21x read the key
5643 int res
= get_ulc_3des_key_magic(tagtype
, auth_key_ptr
);
5644 if (res
!= PM3_SUCCESS
) {
5647 PrintAndLogEx(SUCCESS
, "Using 3DES key... %s", sprint_hex_inrow(auth_key_ptr
, 16));
5648 has_auth_key
= true;
5653 PrintAndLogEx(INFO
, "Start wiping...");
5654 PrintAndLogEx(INFO
, "-----+-----------------------------");
5655 // time to wipe card
5656 // We skip the first four blocks.
5660 for (uint8_t i
= 4; i
< card_mem_size
; i
++) {
5662 if (kbd_enter_pressed()) {
5663 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
5667 uint8_t data
[MFU_BLOCK_SIZE
];
5668 memset(data
, 0x00, sizeof(data
));
5671 if ((tagtype
& MFU_TT_UL_C
) == MFU_TT_UL_C
) {
5676 memcpy(data
, "\x02\x00\x00\x10", 4);
5679 memcpy(data
, "\x00\x06\x01\x10", 4);
5682 memcpy(data
, "\x11\xFF\x00\x00", 4);
5685 memcpy(data
, "\x30\x00\x00\x00", 4);
5693 if ((tagtype
& MFU_TT_UL_AES
)) {
5697 // UL / NTAG with PWD/PACK
5698 if ((tagtype
& (MFU_TT_UL_EV1_48
| MFU_TT_UL_EV1_128
| MFU_TT_UL_EV1
| MFU_TT_UL_NANO_40
|
5699 MFU_TT_NTAG_210u
| MFU_TT_NTAG_213
| MFU_TT_NTAG_213_F
| MFU_TT_NTAG_213_C
|
5700 MFU_TT_NTAG_213_TT
| MFU_TT_NTAG_215
| MFU_TT_NTAG_216
| MFU_TT_NTAG_216_F
|
5701 MFU_TT_NTAG_I2C_1K
| MFU_TT_NTAG_I2C_2K
| MFU_TT_NTAG_I2C_1K_PLUS
| MFU_TT_NTAG_I2C_2K_PLUS
5706 if (i
== card_mem_size
- 4) {
5707 // strong modulation mode disabled
5708 // pages don't need authentication
5709 uint8_t cfg1
[MFU_BLOCK_SIZE
] = {0x00, 0x00, 0x00, 0xFF};
5710 memcpy(data
, cfg1
, sizeof(cfg1
));
5714 if (i
== card_mem_size
- 3) {
5715 // Unlimited password attempts
5716 // NFC counter disabled
5717 // NFC counter not protected
5718 // user configuration writeable
5719 // write access is protected with password
5720 // 05, Virtual Card Type Identifier is default
5721 uint8_t cfg2
[MFU_BLOCK_SIZE
] = {0x00, 0x05, 0x00, 0x00};
5722 memcpy(data
, cfg2
, sizeof(cfg2
));
5725 // Set PWD blocks 0xFF FF FF FF
5726 if (i
== card_mem_size
- 2) {
5727 memset(data
, 0xFF, sizeof(data
));
5730 // Since we changed PWD before, we need to use new PWD to set PACK
5731 // Pack will be all zeros,
5732 if (i
== card_mem_size
- 1) {
5733 memset(auth_key_ptr
, 0xFF, ak_len
);
5738 int res = PM3_SUCCESS;
5739 if (res == PM3_ESOFT) {
5740 res = mfu_write_block(data, MFU_BLOCK_SIZE, has_auth_key, has_pwd, auth_key_ptr, i);
5744 int res
= mfu_write_block(data
, MFU_BLOCK_SIZE
, has_auth_key
, has_pwd
, auth_key_ptr
, i
);
5746 PrintAndLogEx(INFO
, " %3d | %s" NOLF
, i
, sprint_hex(data
, MFU_BLOCK_SIZE
));
5749 PrintAndLogEx(NORMAL
, "( " _GREEN_("ok") " )");
5753 PrintAndLogEx(NORMAL
, "( " _RED_("fail") " )");
5758 PrintAndLogEx(NORMAL
, "");
5759 PrintAndLogEx(WARNING
, "Command execute timeout");
5765 PrintAndLogEx(INFO
, "-----+-----------------------------");
5769 // UL-C - set 3-DES key
5770 if ((tagtype
& MFU_TT_UL_C
) == MFU_TT_UL_C
) {
5773 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42,
5774 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46
5777 clearCommandBuffer();
5778 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD
, 0, 0, 0, key
, sizeof(key
));
5779 PacketResponseNG resp
;
5780 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
5781 if ((resp
.oldarg
[0] & 0xff) == 1) {
5782 PrintAndLogEx(INFO
, "Ultralight-C new key... " _GREEN_("%s"), sprint_hex_inrow(key
, sizeof(key
)));
5784 PrintAndLogEx(WARNING
, "Failed writing at block %u", (uint8_t)(resp
.oldarg
[1] & 0xFF));
5788 PrintAndLogEx(WARNING
, "command execute timeout");
5789 return PM3_ETIMEOUT
;
5794 if ((tagtype
& MFU_TT_UL_AES
)) {
5799 PrintAndLogEx(HINT
, "try `" _YELLOW_("hf mfu dump --ns") "` to verify");
5800 PrintAndLogEx(NORMAL
, "");
5801 PrintAndLogEx(INFO
, "Done!");
5807 static command_t CommandTable
[] = {
5808 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
5809 {"list", CmdHF14AMfuList
, AlwaysAvailable
, "List MIFARE Ultralight / NTAG history"},
5810 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("recovery") " -------------------------"},
5811 {"keygen", CmdHF14AMfUKeyGen
, AlwaysAvailable
, "Generate DES/3DES/AES MIFARE diversified keys"},
5812 {"pwdgen", CmdHF14AMfUPwdGen
, AlwaysAvailable
, "Generate pwd from known algos"},
5813 {"otptear", CmdHF14AMfuOtpTearoff
, IfPm3Iso14443a
, "Tear-off test on OTP bits"},
5814 // {"tear_cnt", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1/NTAG Counter bits"},
5815 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("operations") " -----------------------"},
5816 {"cauth", CmdHF14AMfUCAuth
, IfPm3Iso14443a
, "Ultralight-C - Authentication"},
5817 {"setpwd", CmdHF14AMfUCSetPwd
, IfPm3Iso14443a
, "Ultralight-C - Set 3DES key"},
5818 {"dump", CmdHF14AMfUDump
, IfPm3Iso14443a
, "Dump MIFARE Ultralight family tag to binary file"},
5819 {"info", CmdHF14AMfUInfo
, IfPm3Iso14443a
, "Tag information"},
5820 {"ndefread", CmdHF14MfuNDEFRead
, IfPm3Iso14443a
, "Prints NDEF records from card"},
5821 {"rdbl", CmdHF14AMfURdBl
, IfPm3Iso14443a
, "Read block"},
5822 {"restore", CmdHF14AMfURestore
, IfPm3Iso14443a
, "Restore a dump file onto a tag"},
5823 {"tamper", CmdHF14MfUTamper
, IfPm3Iso14443a
, "NTAG 213TT - Configure the tamper feature"},
5824 {"view", CmdHF14AMfuView
, AlwaysAvailable
, "Display content from tag dump file"},
5825 {"wipe", CmdHF14AMfuWipe
, IfPm3Iso14443a
, "Wipe card to zeros and default key"},
5826 {"wrbl", CmdHF14AMfUWrBl
, IfPm3Iso14443a
, "Write block"},
5827 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("simulation") " -----------------------"},
5828 {"eload", CmdHF14AMfUeLoad
, IfPm3Iso14443a
, "Upload file into emulator memory"},
5829 {"esave", CmdHF14AMfuESave
, IfPm3Iso14443a
, "Save emulator memory to file"},
5830 {"eview", CmdHF14AMfuEView
, IfPm3Iso14443a
, "View emulator memory"},
5831 {"sim", CmdHF14AMfUSim
, IfPm3Iso14443a
, "Simulate MIFARE Ultralight from emulator memory"},
5832 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("magic") " ----------------------------"},
5833 {"setuid", CmdHF14AMfUCSetUid
, IfPm3Iso14443a
, "Set UID - MAGIC tags only"},
5834 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("amiibo") " ----------------------------"},
5835 {"amiibo", CmdHF14AAmiibo
, IfPm3Iso14443a
, "Amiibo tag operations"},
5836 {NULL
, NULL
, NULL
, NULL
}
5839 static int CmdHelp(const char *Cmd
) {
5840 (void)Cmd
; // Cmd is not used so far
5841 CmdsHelp(CommandTable
);
5845 int CmdHFMFUltra(const char *Cmd
) {
5846 clearCommandBuffer();
5847 return CmdsParse(CommandTable
, Cmd
);