1 //-----------------------------------------------------------------------------
2 // Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura
3 // 2015,2016,2017 Iceman, Marshmellow
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
8 // High frequency MIFARE ULTRALIGHT (C) commands
9 //-----------------------------------------------------------------------------
12 #include "cmdparser.h"
13 #include "commonutil.h"
14 #include "crypto/libpcrypto.h"
20 #include "fileutils.h"
21 #include "protocols.h"
22 #include "generator.h"
24 #include "cliparser.h"
26 #include "amiibo.h" // amiiboo fcts
29 #define MAX_UL_BLOCKS 0x0F
30 #define MAX_ULC_BLOCKS 0x2F
31 #define MAX_ULEV1a_BLOCKS 0x13
32 #define MAX_ULEV1b_BLOCKS 0x28
33 #define MAX_NTAG_203 0x29
34 #define MAX_NTAG_210 0x13
35 #define MAX_NTAG_212 0x28
36 #define MAX_NTAG_213 0x2C
37 #define MAX_NTAG_215 0x86
38 #define MAX_NTAG_216 0xE6
39 #define MAX_NTAG_I2C_1K 0xE9
40 #define MAX_MY_D_NFC 0xFF
41 #define MAX_MY_D_MOVE 0x25
42 #define MAX_MY_D_MOVE_LEAN 0x0F
43 #define MAX_UL_NANO_40 0x0A
45 static int CmdHelp(const char *Cmd
);
47 uint8_t default_3des_keys
[][16] = {
48 { 0x42, 0x52, 0x45, 0x41, 0x4b, 0x4d, 0x45, 0x49, 0x46, 0x59, 0x4f, 0x55, 0x43, 0x41, 0x4e, 0x21 }, // 3des std key
49 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // all zeroes
50 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, // 0x00-0x0F
51 { 0x49, 0x45, 0x4D, 0x4B, 0x41, 0x45, 0x52, 0x42, 0x21, 0x4E, 0x41, 0x43, 0x55, 0x4F, 0x59, 0x46 }, // NFC-key
52 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // all ones
53 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, // all FF
54 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } // 11 22 33
57 uint8_t default_pwd_pack
[][4] = {
58 {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default
59 {0x4E, 0x45, 0x78, 0x54},
62 uint32_t UL_TYPES_ARRAY
[] = {
63 UNKNOWN
, UL
, UL_C
, UL_EV1_48
, UL_EV1_128
, NTAG
,
64 NTAG_203
, NTAG_210
, NTAG_212
, NTAG_213
, NTAG_215
, NTAG_216
,
65 MY_D
, MY_D_NFC
, MY_D_MOVE
, MY_D_MOVE_NFC
, MY_D_MOVE_LEAN
, FUDAN_UL
,
66 UL_EV1
, NTAG_213_F
, NTAG_216_F
, UL_NANO_40
, NTAG_I2C_1K
, NTAG_213_TT
,
70 uint8_t UL_MEMORY_ARRAY
[ARRAYLEN(UL_TYPES_ARRAY
)] = {
71 MAX_UL_BLOCKS
, MAX_UL_BLOCKS
, MAX_ULC_BLOCKS
, MAX_ULEV1a_BLOCKS
, MAX_ULEV1b_BLOCKS
, MAX_NTAG_203
,
72 MAX_NTAG_203
, MAX_NTAG_210
, MAX_NTAG_212
, MAX_NTAG_213
, MAX_NTAG_215
, MAX_NTAG_216
,
73 MAX_UL_BLOCKS
, MAX_MY_D_NFC
, MAX_MY_D_MOVE
, MAX_MY_D_MOVE
, MAX_MY_D_MOVE_LEAN
, MAX_UL_BLOCKS
,
74 MAX_ULEV1a_BLOCKS
, MAX_NTAG_213
, MAX_NTAG_216
, MAX_UL_NANO_40
, MAX_NTAG_I2C_1K
, MAX_NTAG_213
,
75 MAX_NTAG_213
, MAX_NTAG_210
78 //------------------------------------
79 // get version nxp product type
80 static char *getProductTypeStr(uint8_t id
) {
87 sprintf(retStr
, "%02X, Ultralight", id
);
90 sprintf(retStr
, "%02X, NTAG", id
);
93 sprintf(retStr
, "%02X, unknown", id
);
100 The 7 MSBits (=n) code the storage size itself based on 2^n,
101 the LSBit is set to '0' if the size is exactly 2^n
102 and set to '1' if the storage size is between 2^n and 2^(n+1).
104 static char *getUlev1CardSizeStr(uint8_t fsize
) {
108 memset(buf
, 0, sizeof(buf
));
110 uint16_t usize
= 1 << ((fsize
>> 1) + 1);
111 uint16_t lsize
= 1 << (fsize
>> 1);
115 sprintf(retStr
, "%02X, (%u <-> %u bytes)", fsize
, usize
, lsize
);
117 sprintf(retStr
, "%02X, (%u bytes)", fsize
, lsize
);
121 int ul_read_uid(uint8_t *uid
) {
123 PrintAndLogEx(WARNING
, "NUll parameter UID");
127 clearCommandBuffer();
128 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
129 PacketResponseNG resp
;
130 WaitForResponse(CMD_ACK
, &resp
);
131 iso14a_card_select_t card
;
132 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
134 uint64_t select_status
= resp
.oldarg
[0];
138 // 3: proprietary Anticollision
139 if (select_status
== 0) {
140 PrintAndLogEx(WARNING
, "iso14443a card select failed");
143 if (card
.uidlen
!= 7) {
144 PrintAndLogEx(WARNING
, "Wrong sized UID, expected 7bytes got %d", card
.uidlen
);
147 memcpy(uid
, card
.uid
, 7);
151 static void ul_switch_on_field(void) {
152 clearCommandBuffer();
153 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_DISCONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
156 static int ul_send_cmd_raw(uint8_t *cmd
, uint8_t cmdlen
, uint8_t *response
, uint16_t responseLength
) {
157 clearCommandBuffer();
158 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_NO_DISCONNECT
| ISO14A_APPEND_CRC
| ISO14A_NO_RATS
, cmdlen
, 0, cmd
, cmdlen
);
159 PacketResponseNG resp
;
160 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) return -1;
161 if (!resp
.oldarg
[0] && responseLength
) return -1;
163 uint16_t resplen
= (resp
.oldarg
[0] < responseLength
) ? resp
.oldarg
[0] : responseLength
;
164 memcpy(response
, resp
.data
.asBytes
, resplen
);
168 static bool ul_select(iso14a_card_select_t
*card
) {
170 ul_switch_on_field();
172 PacketResponseNG resp
;
173 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500) == false) {
174 PrintAndLogEx(WARNING
, "timeout while waiting for reply.");
179 uint16_t len
= (resp
.oldarg
[1] & 0xFFFF);
181 PrintAndLogEx(WARNING
, "iso14443a card select failed");
187 memcpy(card
, resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
192 // This read command will at least return 16bytes.
193 static int ul_read(uint8_t page
, uint8_t *response
, uint16_t responseLength
) {
195 uint8_t cmd
[] = {ISO14443A_CMD_READBLOCK
, page
};
196 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
200 static int ul_comp_write(uint8_t page
, uint8_t *data
, uint8_t datalen
) {
206 memset(cmd
, 0x00, sizeof(cmd
));
207 datalen
= (datalen
> 16) ? 16 : datalen
;
209 cmd
[0] = ISO14443A_CMD_WRITEBLOCK
;
211 memcpy(cmd
+ 2, data
, datalen
);
213 uint8_t response
[1] = {0xFF};
214 ul_send_cmd_raw(cmd
, 2 + datalen
, response
, sizeof(response
));
216 if (response
[0] == 0x0a) return 0;
221 static int ulc_requestAuthentication(uint8_t *nonce
, uint16_t nonceLength
) {
223 uint8_t cmd
[] = {MIFARE_ULC_AUTH_1
, 0x00};
224 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), nonce
, nonceLength
);
228 static int ulc_authentication(uint8_t *key
, bool switch_off_field
) {
230 clearCommandBuffer();
231 SendCommandMIX(CMD_HF_MIFAREUC_AUTH
, switch_off_field
, 0, 0, key
, 16);
232 PacketResponseNG resp
;
233 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) return 0;
234 if (resp
.oldarg
[0] == 1) return 1;
239 static int try_default_3des_keys(uint8_t **correct_key
) {
240 PrintAndLogEx(INFO
, "Trying some default 3des keys");
241 for (uint8_t i
= 0; i
< ARRAYLEN(default_3des_keys
); ++i
) {
242 uint8_t *key
= default_3des_keys
[i
];
243 if (ulc_authentication(key
, true)) {
251 static int ulev1_requestAuthentication(uint8_t *pwd
, uint8_t *pack
, uint16_t packLength
) {
253 uint8_t cmd
[] = {MIFARE_ULEV1_AUTH
, pwd
[0], pwd
[1], pwd
[2], pwd
[3]};
254 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), pack
, packLength
);
255 // NACK tables different tags, but between 0-9 is a NEGATIVE response.
257 if (len
== 1 && pack
[0] <= 0x09)
262 static int ul_auth_select(iso14a_card_select_t
*card
, TagTypeUL_t tagtype
, bool hasAuthKey
, uint8_t *authkey
, uint8_t *pack
, uint8_t packSize
) {
263 if (hasAuthKey
&& (tagtype
& UL_C
)) {
264 //will select card automatically and close connection on error
265 if (!ulc_authentication(authkey
, false)) {
266 PrintAndLogEx(WARNING
, "Authentication Failed UL-C");
270 if (!ul_select(card
)) return PM3_ESOFT
;
273 if (ulev1_requestAuthentication(authkey
, pack
, packSize
) == -1) {
275 PrintAndLogEx(WARNING
, "Authentication Failed UL-EV1/NTAG");
283 static int ulev1_getVersion(uint8_t *response
, uint16_t responseLength
) {
284 uint8_t cmd
[] = {MIFARE_ULEV1_VERSION
};
285 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
289 static int ulev1_readCounter(uint8_t counter
, uint8_t *response
, uint16_t responseLength
) {
291 uint8_t cmd
[] = {MIFARE_ULEV1_READ_CNT
, counter
};
292 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
296 static int ulev1_readTearing(uint8_t counter
, uint8_t *response
, uint16_t responseLength
) {
298 uint8_t cmd
[] = {MIFARE_ULEV1_CHECKTEAR
, counter
};
299 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
303 static int ulev1_readSignature(uint8_t *response
, uint16_t responseLength
) {
305 uint8_t cmd
[] = {MIFARE_ULEV1_READSIG
, 0x00};
306 int len
= ul_send_cmd_raw(cmd
, sizeof(cmd
), response
, responseLength
);
310 // Fudan check checks for which error is given for a command with incorrect crc
311 // NXP UL chip responds with 01, fudan 00.
312 // other possible checks:
314 // UL responds with 00, fudan doesn't respond
317 // UL doesn't respond, fudan responds with 00
319 // send 300000 + crc (read with extra byte(s))
320 // UL responds with read of page 0, fudan doesn't respond.
322 // make sure field is off before calling this function
323 static int ul_fudan_check(void) {
324 iso14a_card_select_t card
;
325 if (!ul_select(&card
))
328 uint8_t cmd
[4] = {0x30, 0x00, 0x02, 0xa7}; //wrong crc on purpose should be 0xa8
329 clearCommandBuffer();
330 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_RAW
| ISO14A_NO_DISCONNECT
| ISO14A_NO_RATS
, 4, 0, cmd
, sizeof(cmd
));
331 PacketResponseNG resp
;
332 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) return UL_ERROR
;
333 if (resp
.oldarg
[0] != 1) return UL_ERROR
;
335 return (!resp
.data
.asBytes
[0]) ? FUDAN_UL
: UL
; //if response == 0x00 then Fudan, else Genuine NXP
338 static int ul_print_default(uint8_t *data
, uint8_t *real_uid
) {
348 bool mful_uid_layout
= true;
350 if (memcmp(uid
, real_uid
, 7) != 0) {
351 mful_uid_layout
= false;
353 PrintAndLogEx(SUCCESS
, " UID: " _GREEN_("%s"), sprint_hex(real_uid
, 7));
354 PrintAndLogEx(SUCCESS
, " UID[0]: %02X, %s", real_uid
[0], getTagInfo(real_uid
[0]));
355 if (real_uid
[0] == 0x05 && ((real_uid
[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP
356 uint8_t chip
= (data
[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU
359 PrintAndLogEx(SUCCESS
, " IC type: SLE 66R04P 770 Bytes");
362 PrintAndLogEx(SUCCESS
, " IC type: SLE 66R16P 2560 Bytes");
365 PrintAndLogEx(SUCCESS
, " IC type: SLE 66R32P 5120 Bytes");
366 break; //512 pages /2 sectors
369 if (mful_uid_layout
) {
370 // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
371 int crc0
= 0x88 ^ uid
[0] ^ uid
[1] ^ uid
[2];
373 PrintAndLogEx(SUCCESS
, " BCC0: %02X (" _GREEN_("ok") ")", data
[3]);
375 PrintAndLogEx(NORMAL
, " BCC0: %02X, crc should be %02X", data
[3], crc0
);
377 int crc1
= uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6];
379 PrintAndLogEx(SUCCESS
, " BCC1: %02X (" _GREEN_("ok") ")", data
[8]);
381 PrintAndLogEx(NORMAL
, " BCC1: %02X, crc should be %02X", data
[8], crc1
);
382 PrintAndLogEx(SUCCESS
, " Internal: %02X (%s)", data
[9], (data
[9] == 0x48) ? _GREEN_("default") : _RED_("not default"));
384 PrintAndLogEx(SUCCESS
, "Blocks 0-2: %s", sprint_hex(data
+ 0, 12));
387 PrintAndLogEx(SUCCESS
, " Lock: %s - %s",
388 sprint_hex(data
+ 10, 2),
389 sprint_bin(data
+ 10, 2)
392 PrintAndLogEx(SUCCESS
, "OneTimePad: %s - %s",
393 sprint_hex(data
+ 12, 4),
394 sprint_bin(data
+ 12, 4)
400 static int ndef_get_maxsize(uint8_t *data
) {
407 else if (data
[2] == 0x12)
409 else if (data
[2] == 0x3E)
411 else if (data
[2] == 0x6D)
416 static int ndef_print_CC(uint8_t *data
) {
421 //NFC Forum Type 1,2,3,4
425 // b7, b6 major version
426 // b5, b4 minor version
428 // 00 always, 01 rfu, 10 proprietary, 11 rfu
430 // 00 always, 01 rfo, 10 proprietary, 11 never
431 uint8_t cc_write
= data
[1] & 0x03;
432 uint8_t cc_read
= (data
[1] & 0x0C) >> 2;
433 uint8_t cc_minor
= (data
[1] & 0x30) >> 4;
434 uint8_t cc_major
= (data
[1] & 0xC0) >> 6;
437 memset(wStr
, 0, sizeof(wStr
));
440 sprintf(wStr
, "Write access granted without any security");
443 sprintf(wStr
, "RFU");
446 sprintf(wStr
, "Proprietary");
449 sprintf(wStr
, "No write access");
453 memset(rStr
, 0, sizeof(rStr
));
456 sprintf(rStr
, "Read access granted without any security");
460 sprintf(rStr
, "RFU");
463 sprintf(rStr
, "Proprietary");
468 PrintAndLogEx(NORMAL
, "");
469 PrintAndLogEx(INFO
, "--- " _CYAN_("NDEF Message"));
470 PrintAndLogEx(SUCCESS
, "Capability Container: %s", sprint_hex(data
, 4));
471 PrintAndLogEx(SUCCESS
, " %02X: NDEF Magic Number", data
[0]);
473 // PrintAndLogEx(SUCCESS, " %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0F);
474 PrintAndLogEx(SUCCESS
, " %02X: version %d.%d supported by tag", data
[1], cc_major
, cc_minor
);
475 PrintAndLogEx(SUCCESS
, " : %s / %s", rStr
, wStr
);
477 PrintAndLogEx(SUCCESS
, " %02X: Physical Memory Size: %d bytes", data
[2], data
[2] * 8);
479 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 48);
480 else if (data
[2] == 0x12)
481 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 144);
482 else if (data
[2] == 0x3E)
483 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 496);
484 else if (data
[2] == 0x6D)
485 PrintAndLogEx(SUCCESS
, " %02X: NDEF Memory Size: %d bytes", data
[2], 872);
487 uint8_t msb3
= (data
[3] & 0xE0) >> 5;
488 uint8_t sf
= (data
[3] & 0x10) >> 4;
489 uint8_t lb
= (data
[3] & 0x08) >> 3;
490 uint8_t mlrule
= (data
[3] & 0x06) >> 1;
491 uint8_t mbread
= (data
[3] & 0x01);
493 PrintAndLogEx(SUCCESS
, " Additional feature information");
494 PrintAndLogEx(SUCCESS
, " %02X", data
[3]);
495 PrintAndLogEx(SUCCESS
, " 00000000");
496 PrintAndLogEx(SUCCESS
, " xxx - %02X: RFU (%s)", msb3
, (msb3
== 0) ? _GREEN_("ok") : _RED_("fail"));
497 PrintAndLogEx(SUCCESS
, " x - %02X: %s special frame", sf
, (sf
) ? "support" : "don\'t support");
498 PrintAndLogEx(SUCCESS
, " x - %02X: %s lock block", lb
, (lb
) ? "support" : "don\'t support");
499 PrintAndLogEx(SUCCESS
, " xx - %02X: RFU (%s)", mlrule
, (mlrule
== 0) ? _GREEN_("ok") : _RED_("fail"));
500 PrintAndLogEx(SUCCESS
, " x - %02X: IC %s multiple block reads", mbread
, (mbread
) ? "support" : "don\'t support");
504 int ul_print_type(uint32_t tagtype
, uint8_t spaces
) {
510 memset(typestr
, 0x00, sizeof(typestr
));
513 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight (MF0ICU1)"), spaces
, "");
514 else if (tagtype
& UL_C
)
515 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight C (MF0ULC)"), spaces
, "");
516 else if (tagtype
& UL_NANO_40
)
517 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight Nano 40bytes (MF0UNH00)"), spaces
, "");
518 else if (tagtype
& UL_EV1_48
)
519 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 48bytes (MF0UL1101)"), spaces
, "");
520 else if (tagtype
& UL_EV1_128
)
521 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 128bytes (MF0UL2101)"), spaces
, "");
522 else if (tagtype
& UL_EV1
)
523 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("MIFARE Ultralight EV1 UNKNOWN"), spaces
, "");
524 else if (tagtype
& NTAG
)
525 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG UNKNOWN"), spaces
, "");
526 else if (tagtype
& NTAG_203
)
527 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 203 144bytes (NT2H0301F0DT)"), spaces
, "");
528 else if (tagtype
& NTAG_210u
)
529 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 210u (micro) 48bytes (NT2L1001G0DU)"), spaces
, "");
530 else if (tagtype
& NTAG_210
)
531 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 210 48bytes (NT2L1011G0DU)"), spaces
, "");
532 else if (tagtype
& NTAG_212
)
533 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 212 128bytes (NT2L1211G0DU)"), spaces
, "");
534 else if (tagtype
& NTAG_213
)
535 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces
, "");
536 else if (tagtype
& NTAG_213_F
)
537 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces
, "");
538 else if (tagtype
& NTAG_213_C
)
539 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213C 144bytes (NT2H1311C1DTL)"), spaces
, "");
540 else if (tagtype
& NTAG_213_TT
)
541 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces
, "");
542 else if (tagtype
& NTAG_215
)
543 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces
, "");
544 else if (tagtype
& NTAG_216
)
545 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 216 888bytes (NT2H1611G0DU)"), spaces
, "");
546 else if (tagtype
& NTAG_216_F
)
547 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG 216F 888bytes (NT2H1611F0DTL)"), spaces
, "");
548 else if (tagtype
& NTAG_I2C_1K
)
549 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C 888bytes (NT3H1101FHK)"), spaces
, "");
550 else if (tagtype
& NTAG_I2C_2K
)
551 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C 1904bytes (NT3H1201FHK)"), spaces
, "");
552 else if (tagtype
& NTAG_I2C_1K_PLUS
)
553 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C plus 888bytes (NT3H2111FHK)"), spaces
, "");
554 else if (tagtype
& NTAG_I2C_2K_PLUS
)
555 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("NTAG I2C plus 1912bytes (NT3H2211FHK)"), spaces
, "");
556 else if (tagtype
& MY_D
)
557 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 (SLE 66RxxS)"), spaces
, "");
558 else if (tagtype
& MY_D_NFC
)
559 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 NFC (SLE 66RxxP)"), spaces
, "");
560 else if (tagtype
& MY_D_MOVE
)
561 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move (SLE 66R01P)"), spaces
, "");
562 else if (tagtype
& MY_D_MOVE_NFC
)
563 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move NFC (SLE 66R01P)"), spaces
, "");
564 else if (tagtype
& MY_D_MOVE_LEAN
)
565 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("INFINEON my-d\x99 move lean (SLE 66R01L)"), spaces
, "");
566 else if (tagtype
& FUDAN_UL
)
567 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("FUDAN Ultralight Compatible (or other compatible)"), spaces
, "");
569 snprintf(typestr
, sizeof(typestr
), "%*sTYPE: " _YELLOW_("Unknown %06x"), spaces
, "", tagtype
);
571 bool ismagic
= ((tagtype
& MAGIC
) == MAGIC
);
573 snprintf(typestr
+ strlen(typestr
), 4, " (");
575 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), " %s ", (tagtype
& MAGIC
) ? _GREEN_("magic") : "");
577 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", (tagtype
& MAGIC_1A
) ? _GREEN_("Gen 1a") : "");
578 snprintf(typestr
+ strlen(typestr
), sizeof(typestr
) - strlen(typestr
), "%s", (tagtype
& MAGIC_1B
) ? _GREEN_("Gen 1b") : "");
581 snprintf(typestr
+ strlen(typestr
), 4, " )");
583 PrintAndLogEx(SUCCESS
, "%s", typestr
);
587 static int ulc_print_3deskey(uint8_t *data
) {
588 PrintAndLogEx(INFO
, " deskey1 [44/0x2C]: %s [%s]", sprint_hex(data
, 4), sprint_ascii(data
, 4));
589 PrintAndLogEx(INFO
, " deskey1 [45/0x2D]: %s [%s]", sprint_hex(data
+ 4, 4), sprint_ascii(data
+ 4, 4));
590 PrintAndLogEx(INFO
, " deskey2 [46/0x2E]: %s [%s]", sprint_hex(data
+ 8, 4), sprint_ascii(data
+ 8, 4));
591 PrintAndLogEx(INFO
, " deskey2 [47/0x2F]: %s [%s]", sprint_hex(data
+ 12, 4), sprint_ascii(data
+ 12, 4));
592 PrintAndLogEx(INFO
, "3des key: " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(data
, 16, 8), 16));
596 static int ulc_print_configuration(uint8_t *data
) {
598 PrintAndLogEx(NORMAL
, "\n--- " _CYAN_("UL-C Configuration"));
599 PrintAndLogEx(NORMAL
, " Higher Lockbits [40/0x28]: %s - %s", sprint_hex(data
, 4), sprint_bin(data
, 2));
600 PrintAndLogEx(NORMAL
, " Counter [41/0x29]: %s - %s", sprint_hex(data
+ 4, 4), sprint_bin(data
+ 4, 2));
602 bool validAuth
= (data
[8] >= 0x03 && data
[8] <= 0x30);
604 PrintAndLogEx(NORMAL
, " Auth0 [42/0x2A]: %s page %d/0x%02X and above need authentication", sprint_hex(data
+ 8, 4), data
[8], data
[8]);
607 PrintAndLogEx(NORMAL
, " Auth0 [42/0x2A]: %s default", sprint_hex(data
+ 8, 4));
609 PrintAndLogEx(NORMAL
, " Auth0 [42/0x2A]: %s auth byte is out-of-range", sprint_hex(data
+ 8, 4));
612 PrintAndLogEx(NORMAL
, " Auth1 [43/0x2B]: %s %s",
613 sprint_hex(data
+ 12, 4),
614 (data
[12] & 1) ? "write access restricted" : "read and write access restricted"
619 static int ulev1_print_configuration(uint32_t tagtype
, uint8_t *data
, uint8_t startPage
) {
621 PrintAndLogEx(NORMAL
, "");
622 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Configuration"));
624 bool strg_mod_en
= (data
[0] & 2);
626 uint8_t authlim
= (data
[4] & 0x07);
627 bool nfc_cnf_prot_pwd
= ((data
[4] & 0x08) == 0x08);
628 bool nfc_cnf_en
= ((data
[4] & 0x10) == 0x10);
629 bool cfglck
= ((data
[4] & 0x40) == 0x40);
630 bool prot
= ((data
[4] & 0x80) == 0x80);
632 uint8_t vctid
= data
[5];
634 PrintAndLogEx(INFO
, " cfg0 [%u/0x%02X]: %s", startPage
, startPage
, sprint_hex(data
, 4));
636 if ((tagtype
& (NTAG_213_F
| NTAG_213_TT
| NTAG_216_F
))) {
637 uint8_t mirror_conf
= (data
[0] & 0xC0);
638 uint8_t mirror_byte
= (data
[0] & 0x30);
639 bool sleep_en
= (data
[0] & 0x08);
640 strg_mod_en
= (data
[0] & 0x04);
641 uint8_t fdp_conf
= (data
[0] & 0x03);
643 switch (mirror_conf
) {
645 PrintAndLogEx(INFO
, " - no ASCII mirror");
648 PrintAndLogEx(INFO
, " - UID ASCII mirror");
651 PrintAndLogEx(INFO
, " - NFC counter ASCII mirror");
654 PrintAndLogEx(INFO
, " - UID and NFC counter ASCII mirror");
660 PrintAndLogEx(INFO
, " - SLEEP mode %s", (sleep_en
) ? "enabled" : "disabled");
664 PrintAndLogEx(INFO
, " - no field detect");
667 PrintAndLogEx(INFO
, " - enabled by first State-of-Frame (start of communication)");
670 PrintAndLogEx(INFO
, " - enabled by selection of the tag");
673 PrintAndLogEx(INFO
, " - enabled by field presence");
678 // valid mirror start page and byte position within start page.
679 if ((tagtype
& NTAG_213_F
) || (tagtype
& NTAG_213_TT
)) {
680 switch (mirror_conf
) {
682 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0x24) ? "OK" : "Invalid value"); break;}
684 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0x26) ? "OK" : "Invalid value"); break;}
686 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0x22) ? "OK" : "Invalid value"); break;}
690 } else if (tagtype
& NTAG_216_F
) {
691 switch (mirror_conf
) {
693 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0xDE) ? "OK" : "Invalid value"); break;}
695 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0xE0) ? "OK" : "Invalid value"); break;}
697 { PrintAndLogEx(INFO
, " mirror start block %02X | byte pos %02X - %s", data
[2], mirror_byte
, (data
[2] >= 0x4 && data
[2] <= 0xDC) ? "OK" : "Invalid value"); break;}
703 PrintAndLogEx(INFO
, " - strong modulation mode %s", (strg_mod_en
) ? "enabled" : "disabled");
706 PrintAndLogEx(INFO
, " - page %d and above need authentication", data
[3]);
708 PrintAndLogEx(INFO
, " - pages don't need authentication");
710 PrintAndLogEx(INFO
, " cfg1 [%u/0x%02X]: %s", startPage
+ 1, startPage
+ 1, sprint_hex(data
+ 4, 4));
712 PrintAndLogEx(INFO
, " - " _GREEN_("Unlimited password attempts"));
714 PrintAndLogEx(INFO
, " - Max number of password attempts is " _YELLOW_("%d"), authlim
);
716 PrintAndLogEx(INFO
, " - NFC counter %s", (nfc_cnf_en
) ? "enabled" : "disabled");
717 PrintAndLogEx(INFO
, " - NFC counter %s", (nfc_cnf_prot_pwd
) ? "password protection enabled" : "not protected");
719 PrintAndLogEx(INFO
, " - user configuration %s", cfglck
? "permanently locked" : "writeable");
720 PrintAndLogEx(INFO
, " - %s access is protected with password", prot
? "read and write" : "write");
721 PrintAndLogEx(INFO
, " - %02X, Virtual Card Type Identifier is %sdefault", vctid
, (vctid
== 0x05) ? "" : "not ");
722 PrintAndLogEx(INFO
, " PWD [%u/0x%02X]: %s- (cannot be read)", startPage
+ 2, startPage
+ 2, sprint_hex(data
+ 8, 4));
723 PrintAndLogEx(INFO
, " PACK [%u/0x%02X]: %s - (cannot be read)", startPage
+ 3, startPage
+ 3, sprint_hex(data
+ 12, 2));
724 PrintAndLogEx(INFO
, " RFU [%u/0x%02X]: %s- (cannot be read)", startPage
+ 3, startPage
+ 3, sprint_hex(data
+ 14, 2));
728 static int ulev1_print_counters(void) {
729 PrintAndLogEx(NORMAL
, "");
730 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Counters"));
731 uint8_t tear
[1] = {0};
732 uint8_t counter
[3] = {0, 0, 0};
734 for (uint8_t i
= 0; i
< 3; ++i
) {
735 ulev1_readTearing(i
, tear
, sizeof(tear
));
736 len
= ulev1_readCounter(i
, counter
, sizeof(counter
));
738 PrintAndLogEx(INFO
, " [%0d]: %s", i
, sprint_hex(counter
, 3));
739 PrintAndLogEx(SUCCESS
, " - %02X tearing ( %s )"
741 , (tear
[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
748 static int ulev1_print_signature(TagTypeUL_t tagtype
, uint8_t *uid
, uint8_t *signature
, size_t signature_len
) {
750 #define PUBLIC_ECDA_KEYLEN 33
751 // known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier)
752 // ref: AN11350 NTAG 21x Originality Signature Validation
753 // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation
754 const ecdsa_publickey_t nxp_mfu_public_keys
[] = {
755 {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"},
756 {"Manufacturer MIFARE Classic MFC1C14_x", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"},
757 {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"},
758 {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"},
759 {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"},
760 {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"},
761 {"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"},
765 uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = {
766 // UL, NTAG21x and NDEF
768 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c,
769 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49,
770 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39,
771 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61
775 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b,
776 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8,
777 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72,
778 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8
780 // unknown. Needs identification
782 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57,
783 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35,
784 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2,
785 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF
787 // unknown. Needs identification
789 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE,
790 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1,
791 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA,
792 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC
794 // manufacturer public key
796 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61,
797 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C,
798 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07,
799 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2
801 // MIKRON public key.
803 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8,
804 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07,
805 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7,
806 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2
811 bool is_valid
= false;
812 for (i
= 0; i
< ARRAYLEN(nxp_mfu_public_keys
); i
++) {
815 uint8_t key
[PUBLIC_ECDA_KEYLEN
] = {0};
816 param_gethex_to_eol(nxp_mfu_public_keys
[i
].value
, 0, key
, PUBLIC_ECDA_KEYLEN
, &dl
);
818 int res
= ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1
, key
, uid
, 7, signature
, signature_len
, false);
820 is_valid
= (res
== 0);
825 PrintAndLogEx(NORMAL
, "");
826 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Signature"));
827 if (is_valid
== false || i
== ARRAYLEN(nxp_mfu_public_keys
)) {
828 PrintAndLogEx(INFO
, " Elliptic curve parameters: NID_secp128r1");
829 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, signature_len
));
830 PrintAndLogEx(SUCCESS
, " Signature verification ( " _RED_("fail") " )");
834 PrintAndLogEx(INFO
, " IC signature public key name: %s", nxp_mfu_public_keys
[i
].desc
);
835 PrintAndLogEx(INFO
, "IC signature public key value: %s", nxp_mfu_public_keys
[i
].value
);
836 PrintAndLogEx(INFO
, " Elliptic curve parameters: NID_secp128r1");
837 PrintAndLogEx(INFO
, " TAG IC Signature: %s", sprint_hex_inrow(signature
, signature_len
));
838 PrintAndLogEx(SUCCESS
, " Signature verification ( " _GREEN_("successful") " )");
842 static int ulev1_print_version(uint8_t *data
) {
843 PrintAndLogEx(NORMAL
, "");
844 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Version"));
845 PrintAndLogEx(INFO
, " Raw bytes: %s", sprint_hex(data
, 8));
846 PrintAndLogEx(INFO
, " Vendor ID: %02X, %s", data
[1], getTagInfo(data
[1]));
847 PrintAndLogEx(INFO
, " Product type: %s", getProductTypeStr(data
[2]));
848 PrintAndLogEx(INFO
, " Product subtype: %02X, %s", data
[3], (data
[3] == 1) ? "17 pF" : "50pF");
849 PrintAndLogEx(INFO
, " Major version: %02X", data
[4]);
850 PrintAndLogEx(INFO
, " Minor version: %02X", data
[5]);
851 PrintAndLogEx(INFO
, " Size: %s", getUlev1CardSizeStr(data
[6]));
852 PrintAndLogEx(INFO
, " Protocol type: %02X%s", data
[7], (data
[7] == 0x3) ? ", ISO14443-3 Compliant" : "");
856 static int ntag_print_counter(void) {
857 // NTAG has one counter/tearing. At address 0x02.
858 PrintAndLogEx(NORMAL
, "");
859 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Counter"));
860 uint8_t tear
[1] = {0};
861 uint8_t counter
[3] = {0, 0, 0};
863 len
= ulev1_readTearing(0x02, tear
, sizeof(tear
));
865 len
= ulev1_readCounter(0x02, counter
, sizeof(counter
));
867 PrintAndLogEx(INFO
, " [02]: %s", sprint_hex(counter
, 3));
868 PrintAndLogEx(SUCCESS
, " - %02X tearing ( %s )"
870 , (tear
[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
876 static int ulc_magic_test(){
877 // Magic Ultralight test
878 // Magic UL-C, by observation,
879 // 1) it seems to have a static nonce response to 0x1A command.
880 // 2) the deskey bytes is not-zero:d out on as datasheet states.
881 // 3) UID - changeable, not only, but pages 0-1-2-3.
882 // 4) use the ul_magic_test ! magic tags answers specially!
883 int returnValue = UL_ERROR;
884 iso14a_card_select_t card;
885 uint8_t nonce1[11] = {0x00};
886 uint8_t nonce2[11] = {0x00};
887 if ( !ul_select(&card) ){
890 int status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
892 status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
893 returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C;
901 static int ul_magic_test(void) {
902 // Magic Ultralight tests
903 // 1) take present UID, and try to write it back. OBSOLETE
904 // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
906 iso14a_card_select_t card
;
907 if (ul_select(&card
) == false)
910 int status
= ul_comp_write(0, NULL
, 0);
915 // check for GEN1A, GEN1B and NTAG21x
916 uint8_t is_generation
= 0;
917 PacketResponseNG resp
;
918 clearCommandBuffer();
919 uint8_t payload
[] = { 0 };
920 SendCommandNG(CMD_HF_MIFARE_CIDENT
, payload
, sizeof(payload
));
921 if (WaitForResponseTimeout(CMD_HF_MIFARE_CIDENT
, &resp
, 1500)) {
922 if (resp
.status
== PM3_SUCCESS
)
923 is_generation
= resp
.data
.asBytes
[0];
925 switch (is_generation
) {
938 static char *GenerateFilename(const char *prefix
, const char *suffix
) {
939 iso14a_card_select_t card
;
940 if (ul_select(&card
) == false) {
941 PrintAndLogEx(WARNING
, "No tag found.");
945 char *fptr
= calloc(sizeof(char) * (strlen(prefix
) + strlen(suffix
)) + sizeof(card
.uid
) * 2 + 1, sizeof(uint8_t));
946 strcpy(fptr
, prefix
);
947 FillFileNameByUID(fptr
, card
.uid
, suffix
, card
.uidlen
);
951 //------------------------------------
953 static int mfu_decrypt_amiibo(uint8_t *encrypted, uint16_t elen, uint8_t *decrypted, uint16_t *dlen) {
955 if (elen < NFC3D_AMIIBO_SIZE / 4) {
956 PrintAndLogEx(ERR, "ERR, data wrong length, got %zu , expected %zu", elen, (NFC3D_AMIIBO_SIZE / 4));
960 nfc3d_amiibo_keys amiibo_keys = {0};
961 if (nfc3d_amiibo_load_keys(&amiibo_keys) == false) {
965 if (nfc3d_amiibo_unpack(&amiibo_keys, encrypted, decrypted) == false) {
966 PrintAndLogEx(ERR, "WARNING, Tag signature was NOT valid");
969 *dlen = NFC3D_AMIIBO_SIZE;
972 static int mfu_dump_tag(uint16_t pages, void **pdata, uint16_t *len) {
974 int res = PM3_SUCCESS;
975 uint16_t maxbytes = (pages * 4);
977 *pdata = calloc(maxbytes, sizeof(uint8_t));
978 if (*pdata == NULL) {
979 PrintAndLogEx(FAILED, "error, cannot allocate memory");
984 clearCommandBuffer();
985 SendCommandMIX(CMD_HF_MIFAREU_READCARD, 0, pages, 0, NULL, 0);
986 PacketResponseNG resp;
987 if (WaitForResponseTimeout(CMD_ACK, &resp, 2500) == false) {
988 PrintAndLogEx(WARNING, "Command execute time-out");
994 if (resp.oldarg[0] != 1) {
995 PrintAndLogEx(WARNING, "Failed reading card");
1002 uint32_t startindex = resp.oldarg[2];
1003 uint32_t buffer_size = resp.oldarg[1];
1004 if (buffer_size > maxbytes) {
1005 PrintAndLogEx(FAILED, "Data exceeded buffer size!");
1006 buffer_size = maxbytes;
1009 if (!GetFromDevice(BIG_BUF, *pdata, buffer_size, startindex, NULL, 0, NULL, 2500, false)) {
1010 PrintAndLogEx(WARNING, "command execution time out");
1025 Version: 00 04 04 02 01 00 0F 03
1029 E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E
1034 const char *version
;
1038 uint32_t (*Pwd
)(uint8_t *uid
);
1039 uint16_t (*Pack
)(uint8_t *uid
);
1041 } PACKED mfu_identify_t
;
1043 static mfu_identify_t mfu_ident_table
[] = {
1045 "Jooki", "0004040201000F03",
1046 12, 32, "E11012000103A00C340329D101255504732E6A6F6F6B692E726F636B732F732F",
1047 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1048 "hf jooki decode -r"
1051 "Lego Dimensions", "0004040201000F03",
1052 12, 18, "E11012000103A00C340313D1010F5402656E",
1053 ul_ev1_pwdgenC
, ul_ev1_packgenC
,
1054 "hf mfu dump -k %08x"
1057 "Hotwheels", "0004040201000F03",
1059 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1060 "hf mfu dump -k %08x"
1063 "Minecraft Earth", "0004040201000F03",
1064 9, 26, "48F6FFE1101200037C91012C55027069642E6D617474656C2F4167",
1065 ul_ev1_pwdgen_def
, ul_ev1_packgen_def
,
1066 "hf mfu dump -k %08x"
1069 "Snackworld", "0004040101000B03",
1070 9, 7, "483000E1100600",
1072 "hf mfu dump -k %08x"
1075 "Amiibo", "0004040201001103",
1076 9, 9, "480FE0F110FFEEA500",
1077 ul_ev1_pwdgenB
, ul_ev1_packgenB
,
1078 "hf mfu dump -k %08x"
1080 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
, NULL
}
1083 static mfu_identify_t
*mfu_match_fingerprint(uint8_t *version
, uint8_t *data
) {
1088 uint8_t vtmp
[10] = {0};
1089 param_gethex_to_eol(mfu_ident_table
[i
].version
, 0, vtmp
, sizeof(vtmp
), &vl
);
1091 bool m1
= (memcmp(vtmp
, version
, vl
) == 0);
1093 PrintAndLogEx(DEBUG
, "(fingerprint) wrong version");
1098 uint8_t mtmp
[40] = {0};
1099 param_gethex_to_eol(mfu_ident_table
[i
].match
, 0, mtmp
, sizeof(mtmp
), &ml
);
1101 bool m2
= (memcmp(mtmp
, data
+ mfu_ident_table
[i
].mpos
, mfu_ident_table
[i
].mlen
) == 0);
1103 PrintAndLogEx(DEBUG
, "(fingerprint) found %s", mfu_ident_table
[i
].desc
);
1104 return &mfu_ident_table
[i
];
1106 } while (mfu_ident_table
[++i
].desc
);
1110 static uint8_t mfu_max_len(void) {
1111 uint8_t n
= 0, i
= 0;
1113 uint8_t tmp
= mfu_ident_table
[i
].mpos
+ mfu_ident_table
[i
].mlen
;
1117 } while (mfu_ident_table
[++i
].desc
);
1121 static int mfu_get_version_uid(uint8_t *version
, uint8_t *uid
) {
1122 iso14a_card_select_t card
;
1123 if (ul_select(&card
) == false)
1126 uint8_t v
[10] = {0x00};
1127 int len
= ulev1_getVersion(v
, sizeof(v
));
1129 if (len
!= sizeof(v
))
1132 memcpy(version
, v
, 8);
1133 memcpy(uid
, card
.uid
, 7);
1137 static int mfu_fingerprint(void) {
1139 uint8_t *data
= NULL
;
1140 int res
= PM3_SUCCESS
;
1141 PrintAndLogEx(INFO
, "------------------------ " _CYAN_("Fingerprint") " -----------------------");
1142 uint8_t maxbytes
= mfu_max_len();
1143 if (maxbytes
== 0) {
1144 PrintAndLogEx(ERR
, "fingerprint table wrong");
1149 maxbytes
= ((maxbytes
/ 4) + 1) * 4;
1150 data
= calloc(maxbytes
, sizeof(uint8_t));
1152 PrintAndLogEx(ERR
, "failed to allocate memory");
1157 uint8_t pages
= (maxbytes
/ 4);
1158 PrintAndLogEx(INFO
, "Reading tag memory...");
1160 clearCommandBuffer();
1161 SendCommandMIX(CMD_HF_MIFAREU_READCARD
, 0, pages
, 0, NULL
, 0);
1162 PacketResponseNG resp
;
1163 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
1164 PrintAndLogEx(WARNING
, "Command execute time-out");
1169 if (resp
.oldarg
[0] != 1) {
1170 PrintAndLogEx(WARNING
, "Failed reading card");
1176 uint32_t startindex
= resp
.oldarg
[2];
1177 uint32_t buffer_size
= resp
.oldarg
[1];
1178 if (buffer_size
> maxbytes
) {
1179 PrintAndLogEx(FAILED
, "Data exceeded buffer size!");
1180 buffer_size
= maxbytes
;
1183 if (!GetFromDevice(BIG_BUF
, data
, buffer_size
, startindex
, NULL
, 0, NULL
, 2500, false)) {
1184 PrintAndLogEx(WARNING
, "command execution time out");
1189 uint8_t version
[8] = {0};
1190 uint8_t uid
[7] = {0};
1191 if (mfu_get_version_uid(version
, uid
) == PM3_SUCCESS
) {
1192 mfu_identify_t
*item
= mfu_match_fingerprint(version
, data
);
1194 PrintAndLogEx(SUCCESS
, "Found " _GREEN_("%s"), item
->desc
);
1198 sprintf(s
, item
->hint
, item
->Pwd(uid
));
1199 PrintAndLogEx(HINT
, "Use `" _YELLOW_("%s") "`", s
);
1201 PrintAndLogEx(HINT
, "Use `" _YELLOW_("%s") "`", item
->hint
);
1208 PrintAndLogEx(INFO
, "------------------------------------------------------------");
1212 uint32_t GetHF14AMfU_Type(void) {
1214 TagTypeUL_t tagtype
= UNKNOWN
;
1215 iso14a_card_select_t card
;
1217 if (ul_select(&card
) == false)
1220 // Ultralight - ATQA / SAK
1221 if (card
.atqa
[1] != 0x00 || card
.atqa
[0] != 0x44 || card
.sak
!= 0x00) {
1222 //PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
1227 if (card
.uid
[0] != 0x05) {
1229 uint8_t version
[10] = {0x00};
1230 int len
= ulev1_getVersion(version
, sizeof(version
));
1236 MF0UL1001DUx 0004030100000B03
1237 MF0UL1101DUx 0004030101000B03
1238 MF0ULH1101DUx 0004030201000B03
1239 MF0UL1141DUF 0004030301000B03
1240 MF0UL2101Dxy 0004030101000E03
1241 MF0UL2101DUx 0004030201000E03
1242 MF0UL3101DUx 0004030101001103
1243 MF0ULH3101DUx 0004030201001103
1244 MF0UL5101DUx 0004030101001303
1245 NT2L1011F0DUx 0004040101000B03
1246 NT2H1011G0DUD 0004040201000B03
1247 NT2L1211F0DUx 0004040101000E03
1248 NT2H1311G0DUx 0004040201000F03
1249 NT2H1311F0Dxy 0004040401000F03
1250 NT2H1411G0DUx 0004040201011103
1251 NT2H1511G0DUx 0004040201001103
1252 NT2H1511F0Dxy 0004040401001103
1253 NT2H1611G0DUx 0004040201001303
1254 NT2H1611F0Dxy 0004040401001303
1255 NT2H1311C1DTL 0004040201010F03
1256 NT2H1311TTDUx 0004040203000F03
1257 NT3H1101W0FHK 0004040502001303
1258 NT3H1201W0FHK 0004040502001503
1259 NT3H1101W0FHK_Variant 0004040502011303
1260 NT3H1201 0004040502011503
1261 NT3H2111 0004040502021303
1262 NT3H2211 0004040502021503
1263 nhs 0004040600001303
1264 MF0UN0001DUx 0004030102000B03
1265 MF0UNH0001DUx 0004030202000B03
1266 MF0UN1001DUx 0004030103000B03
1267 MF0UNH1001DUx 0004030203000B03
1268 NT2L1001G0DUx 0004040102000B03
1269 NT2H1001G0DUx 0004040202000B03
1270 NT2H1311TTDUx 0004040203000F03
1271 Micron UL 0034210101000E03
1274 if (memcmp(version
, "\x00\x04\x03\x01\x01\x00\x0B", 7) == 0) { tagtype
= UL_EV1_48
; break; }
1275 else if (memcmp(version
, "\x00\x04\x03\x01\x02\x00\x0B", 7) == 0) { tagtype
= UL_NANO_40
; break; }
1276 else if (memcmp(version
, "\x00\x04\x03\x02\x01\x00\x0B", 7) == 0) { tagtype
= UL_EV1_48
; break; }
1277 else if (memcmp(version
, "\x00\x04\x03\x01\x01\x00\x0E", 7) == 0) { tagtype
= UL_EV1_128
; break; }
1278 else if (memcmp(version
, "\x00\x04\x03\x02\x01\x00\x0E", 7) == 0) { tagtype
= UL_EV1_128
; break; }
1279 else if (memcmp(version
, "\x00\x34\x21\x01\x01\x00\x0E", 7) == 0) { tagtype
= UL_EV1_128
; break; } // Mikron JSC Russia EV1 41 pages tag
1280 else if (memcmp(version
, "\x00\x04\x04\x01\x01\x00\x0B", 7) == 0) { tagtype
= NTAG_210
; break; }
1281 else if (memcmp(version
, "\x00\x04\x04\x01\x02\x00\x0B", 7) == 0) { tagtype
= NTAG_210u
; break; }
1282 else if (memcmp(version
, "\x00\x04\x04\x01\x01\x00\x0E", 7) == 0) { tagtype
= NTAG_212
; break; }
1283 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x00\x0F", 7) == 0) { tagtype
= NTAG_213
; break; }
1284 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x01\x0F", 7) == 0) { tagtype
= NTAG_213_C
; break; }
1285 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x00\x11", 7) == 0) { tagtype
= NTAG_215
; break; }
1286 else if (memcmp(version
, "\x00\x04\x04\x02\x01\x00\x13", 7) == 0) { tagtype
= NTAG_216
; break; }
1287 else if (memcmp(version
, "\x00\x04\x04\x04\x01\x00\x0F", 7) == 0) { tagtype
= NTAG_213_F
; break; }
1288 else if (memcmp(version
, "\x00\x04\x04\x04\x01\x00\x13", 7) == 0) { tagtype
= NTAG_216_F
; break; }
1289 else if (memcmp(version
, "\x00\x04\x04\x02\x03\x00\x0F", 7) == 0) { tagtype
= NTAG_213_TT
; break; }
1290 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x01\x13", 7) == 0) { tagtype
= NTAG_I2C_1K
; break; }
1291 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype
= NTAG_I2C_2K
; break; }
1292 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype
= NTAG_I2C_1K_PLUS
; break; }
1293 else if (memcmp(version
, "\x00\x04\x04\x05\x02\x02\x15", 7) == 0) { tagtype
= NTAG_I2C_2K_PLUS
; break; }
1294 else if (version
[2] == 0x04) { tagtype
= NTAG
; break; }
1295 else if (version
[2] == 0x03) { tagtype
= UL_EV1
; }
1305 tagtype
= (UL
| UL_C
| NTAG_203
);
1306 break; // could be UL | UL_C magic tags
1312 // UL vs UL-C vs ntag203 test
1313 if (tagtype
& (UL
| UL_C
| NTAG_203
)) {
1314 if (!ul_select(&card
)) return UL_ERROR
;
1316 // do UL_C check first...
1317 uint8_t nonce
[11] = {0x00};
1318 int status
= ulc_requestAuthentication(nonce
, sizeof(nonce
));
1323 // need to re-select after authentication error
1324 if (ul_select(&card
) == false)
1327 uint8_t data
[16] = {0x00};
1328 // read page 0x26-0x29 (last valid ntag203 page)
1329 status
= ul_read(0x26, data
, sizeof(data
));
1333 // read page 0x30 (should error if it is a ntag203)
1334 status
= ul_read(0x30, data
, sizeof(data
));
1345 tagtype
= ul_fudan_check();
1350 // Infinition MY-D tests Exam high nibble
1351 uint8_t nib
= (card
.uid
[1] & 0xf0) >> 4;
1353 // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
1356 break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
1358 tagtype
= (MY_D_NFC
);
1359 break; // or SLE 66RxxP ... up to 512 pages of 8 user bytes... (or in nfc mode FF pages of 4 bytes)
1361 tagtype
= (MY_D_MOVE
| MY_D_MOVE_NFC
);
1362 break; // or SLE 66R01P // 38 pages of 4 bytes //notice: we can not currently distinguish between these two
1364 tagtype
= MY_D_MOVE_LEAN
;
1365 break; // or SLE 66R01L // 16 pages of 4 bytes
1369 tagtype
|= ul_magic_test();
1370 if (tagtype
== (UNKNOWN
| MAGIC
)) {
1371 tagtype
= (UL_MAGIC
);
1376 // extended tag information
1378 static int CmdHF14AMfUInfo(const char *Cmd
) {
1380 CLIParserContext
*ctx
;
1381 CLIParserInit(&ctx
, "hf mfu info",
1382 "Get info about MIFARE Ultralight Family styled tag.\n"
1383 "Sometimes the tags are locked down, and you may need a key to be able to read the information",
1385 "hf mfu info -k AABBCCDD\n"
1386 "hf mfu info --key 00112233445566778899AABBCCDDEEFF"
1389 void *argtable
[] = {
1391 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
1392 arg_lit0("l", NULL
, "swap entered key's endianness"),
1395 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
1398 uint8_t authenticationkey
[16] = {0x00};
1399 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
1400 bool swap_endian
= arg_get_lit(ctx
, 2);
1404 if (ak_len
!= 16 && ak_len
!= 4) {
1405 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
1410 bool has_auth_key
= false;
1412 has_auth_key
= true;
1414 uint8_t authlim
= 0xff;
1415 uint8_t data
[16] = {0x00};
1416 iso14a_card_select_t card
;
1418 uint8_t *authkeyptr
= authenticationkey
;
1419 uint8_t pwd
[4] = {0, 0, 0, 0};
1421 uint8_t pack
[4] = {0, 0, 0, 0};
1424 TagTypeUL_t tagtype
= GetHF14AMfU_Type();
1425 if (tagtype
== UL_ERROR
)
1428 PrintAndLogEx(NORMAL
, "");
1429 PrintAndLogEx(INFO
, "--- " _CYAN_("Tag Information") " --------------------------");
1430 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
1431 ul_print_type(tagtype
, 6);
1434 if (swap_endian
&& has_auth_key
) {
1435 authkeyptr
= SwapEndian64(authenticationkey
, ak_len
, (ak_len
== 16) ? 8 : 4);
1438 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1442 bool locked
= false;
1443 // read pages 0,1,2,3 (should read 4pages)
1444 status
= ul_read(0, data
, sizeof(data
));
1447 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ");
1449 } else if (status
== 16) {
1450 ul_print_default(data
, card
.uid
);
1451 ndef_print_CC(data
+ 12);
1457 if ((tagtype
& UL_C
)) {
1459 // read pages 0x28, 0x29, 0x2A, 0x2B
1460 uint8_t ulc_conf
[16] = {0x00};
1461 status
= ul_read(0x28, ulc_conf
, sizeof(ulc_conf
));
1463 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ UL-C");
1468 ulc_print_configuration(ulc_conf
);
1472 if ((tagtype
& MAGIC
)) {
1474 uint8_t ulc_deskey
[16] = {0x00};
1475 status
= ul_read(0x2C, ulc_deskey
, sizeof(ulc_deskey
));
1478 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ magic");
1482 ulc_print_3deskey(ulc_deskey
);
1487 // if we called info with key, just return
1492 // also try to diversify default keys.. look into CmdHF14AMfGenDiverseKeys
1493 if (try_default_3des_keys(&key
) == PM3_SUCCESS
) {
1494 PrintAndLogEx(SUCCESS
, "Found default 3des key: ");
1495 uint8_t keySwap
[16];
1496 memcpy(keySwap
, SwapEndian64(key
, 16, 8), 16);
1497 ulc_print_3deskey(keySwap
);
1503 // do counters and signature first (don't neet auth)
1505 // ul counters are different than ntag counters
1506 if ((tagtype
& (UL_EV1_48
| UL_EV1_128
| UL_EV1
))) {
1507 if (ulev1_print_counters() != 3) {
1508 // failed - re-select
1509 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1516 if ((tagtype
& (NTAG_213
| NTAG_213_F
| NTAG_213_C
| NTAG_213_TT
| NTAG_215
| NTAG_216
))) {
1517 if (ntag_print_counter()) {
1518 // failed - re-select
1519 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1526 if ((tagtype
& (UL_EV1_48
| UL_EV1_128
| UL_EV1
| UL_NANO_40
| NTAG_210u
| NTAG_213
| NTAG_213_F
| NTAG_213_C
| NTAG_213_TT
| NTAG_215
| NTAG_216
| NTAG_216_F
| NTAG_I2C_1K
| NTAG_I2C_2K
| NTAG_I2C_1K_PLUS
| NTAG_I2C_2K_PLUS
))) {
1527 uint8_t ulev1_signature
[32] = {0x00};
1528 status
= ulev1_readSignature(ulev1_signature
, sizeof(ulev1_signature
));
1530 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ SIGNATURE");
1535 ulev1_print_signature(tagtype
, card
.uid
, ulev1_signature
, sizeof(ulev1_signature
));
1538 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1544 uint8_t version
[10] = {0x00};
1545 status
= ulev1_getVersion(version
, sizeof(version
));
1547 PrintAndLogEx(ERR
, "Error: tag didn't answer to GETVERSION");
1550 } else if (status
== 10) {
1551 ulev1_print_version(version
);
1554 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1559 uint8_t startconfigblock
= 0;
1560 uint8_t ulev1_conf
[16] = {0x00};
1562 // config blocks always are last 4 pages
1563 for (uint8_t i
= 0; i
< ARRAYLEN(UL_TYPES_ARRAY
); i
++) {
1564 if (tagtype
& UL_TYPES_ARRAY
[i
]) {
1565 startconfigblock
= UL_MEMORY_ARRAY
[i
] - 3;
1570 if (startconfigblock
) { // if we know where the config block is...
1571 status
= ul_read(startconfigblock
, ulev1_conf
, sizeof(ulev1_conf
));
1573 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ EV1");
1576 } else if (status
== 16) {
1577 // save AUTHENTICATION LIMITS for later:
1578 authlim
= (ulev1_conf
[4] & 0x07);
1579 // add pwd / pack if used from cli
1581 memcpy(ulev1_conf
+ 8, authkeyptr
, 4);
1582 memcpy(ulev1_conf
+ 12, pack
, 2);
1584 ulev1_print_configuration(tagtype
, ulev1_conf
, startconfigblock
);
1588 // AUTHLIMIT, (number of failed authentications)
1590 // 1-7 = limit. No automatic tries then.
1591 // hasAuthKey, if we was called with key, skip test.
1592 if (!authlim
&& !has_auth_key
) {
1593 PrintAndLogEx(NORMAL
, "");
1594 PrintAndLogEx(SUCCESS
, "--- " _CYAN_("Known EV1/NTAG passwords"));
1596 num_to_bytes(ul_ev1_pwdgenA(card
.uid
), 4, key
);
1597 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
1599 PrintAndLogEx(SUCCESS
, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key
, 4), pack
[0], pack
[1]);
1603 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1608 num_to_bytes(ul_ev1_pwdgenB(card
.uid
), 4, key
);
1609 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
1611 PrintAndLogEx(SUCCESS
, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key
, 4), pack
[0], pack
[1]);
1615 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1620 num_to_bytes(ul_ev1_pwdgenC(card
.uid
), 4, key
);
1621 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
1623 PrintAndLogEx(SUCCESS
, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key
, 4), pack
[0], pack
[1]);
1627 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1632 num_to_bytes(ul_ev1_pwdgenD(card
.uid
), 4, key
);
1633 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
1635 PrintAndLogEx(SUCCESS
, "Found default password" _GREEN_("%s") " pack %02X %02X", sprint_hex(key
, 4), pack
[0], pack
[1]);
1639 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1643 for (uint8_t i
= 0; i
< ARRAYLEN(default_pwd_pack
); ++i
) {
1644 key
= default_pwd_pack
[i
];
1645 len
= ulev1_requestAuthentication(key
, pack
, sizeof(pack
));
1647 PrintAndLogEx(SUCCESS
, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key
, 4), pack
[0], pack
[1]);
1650 if (ul_auth_select(&card
, tagtype
, has_auth_key
, authkeyptr
, pack
, sizeof(pack
)) == PM3_ESOFT
) {
1656 PrintAndLogEx(WARNING
, _YELLOW_("password not known"));
1657 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
1660 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
1669 PrintAndLogEx(INFO
, "\nTag appears to be locked, try using a key to get more info");
1670 PrintAndLogEx(HINT
, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
1672 PrintAndLogEx(NORMAL
, "");
1677 // Write Single Block
1679 static int CmdHF14AMfUWrBl(const char *Cmd
) {
1681 CLIParserContext
*ctx
;
1682 CLIParserInit(&ctx
, "hf mfu wrbl",
1683 "Write a block. It autodetects card type.",
1684 "hf mfu wrbl -b 0 -d 01234567\n"
1685 "hf mfu wrbl -b 0 -d 01234567 -k AABBCCDD\n"
1686 "hf mfu wrbl -b 0 -d 01234567 -k 00112233445566778899AABBCCDDEEFF"
1689 void *argtable
[] = {
1691 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
1692 arg_lit0("l", NULL
, "swap entered key's endianness"),
1693 arg_int1("b", "block", "<dec>", "block number to write"),
1694 arg_str1("d", "data", "<hex>", "block data (4 or 16 hex bytes, 16 hex bytes will do a compatibility write)"),
1697 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1700 uint8_t authenticationkey
[16] = {0x00};
1701 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
1702 bool swap_endian
= arg_get_lit(ctx
, 2);
1704 int blockno
= arg_get_int_def(ctx
, 3, -1);
1707 uint8_t data
[16] = {0x00};
1708 CLIGetHexWithReturn(ctx
, 4, data
, &datalen
);
1711 bool has_auth_key
= false;
1712 bool has_pwd
= false;
1714 has_auth_key
= true;
1715 } else if (ak_len
== 4) {
1717 } else if (ak_len
!= 0) {
1718 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
1723 PrintAndLogEx(WARNING
, "Wrong block number");
1727 if (datalen
!= 16 && datalen
!= 4) {
1728 PrintAndLogEx(WARNING
, "Wrong data length. Expect 16 or 4, got %d", datalen
);
1732 uint8_t *authKeyPtr
= authenticationkey
;
1734 // starting with getting tagtype
1735 TagTypeUL_t tagtype
= GetHF14AMfU_Type();
1736 if (tagtype
== UL_ERROR
)
1739 uint8_t maxblockno
= 0;
1740 for (uint8_t idx
= 0; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
1741 if (tagtype
& UL_TYPES_ARRAY
[idx
]) {
1742 maxblockno
= UL_MEMORY_ARRAY
[idx
];
1746 if (blockno
> maxblockno
) {
1747 PrintAndLogEx(WARNING
, "block number too large. Max block is %u/0x%02X \n", maxblockno
, maxblockno
);
1754 authKeyPtr
= SwapEndian64(authenticationkey
, 16, 8);
1757 authKeyPtr
= SwapEndian64(authenticationkey
, 4, 4);
1761 PrintAndLogEx(INFO
, "Special block: %0d (0x%02X) [ %s]", blockno
, blockno
, sprint_hex(data
, datalen
));
1763 PrintAndLogEx(INFO
, "Block: %0d (0x%02X) [ %s]", blockno
, blockno
, sprint_hex(data
, datalen
));
1766 PrintAndLogEx(INFO
, "Using %s " _GREEN_("%s"), (ak_len
== 16) ? "3des" : "pwd", sprint_hex(authenticationkey
, ak_len
));
1772 uint8_t cmddata
[32];
1773 memcpy(cmddata
, data
, datalen
);
1775 // 0 - no pwd/key, no authentication
1776 // 1 - 3des key (16 bytes)
1777 // 2 - pwd (4 bytes)
1778 uint8_t keytype
= 0;
1779 size_t cmdlen
= datalen
;
1782 memcpy(cmddata
+ datalen
, authKeyPtr
, 16);
1784 } else if (has_pwd
) {
1786 memcpy(cmddata
+ datalen
, authKeyPtr
, 4);
1790 clearCommandBuffer();
1791 if (datalen
== 16) {
1792 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT
, blockno
, keytype
, 0, cmddata
, cmdlen
);
1794 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, blockno
, keytype
, 0, cmddata
, cmdlen
);
1796 PacketResponseNG resp
;
1797 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
1798 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
1799 PrintAndLogEx(SUCCESS
, "isOk:%02x", isOK
);
1801 PrintAndLogEx(WARNING
, "Command execute timeout");
1807 // Read Single Block
1809 static int CmdHF14AMfURdBl(const char *Cmd
) {
1811 CLIParserContext
*ctx
;
1812 CLIParserInit(&ctx
, "hf mfu rdbl",
1813 "Read a block and print. It autodetects card type.",
1814 "hf mfu rdbl -b 0\n"
1815 "hf mfu rdbl -b 0 -k AABBCCDD\n"
1816 "hf mfu rdbl -b 0 --key 00112233445566778899AABBCCDDEEFF"
1819 void *argtable
[] = {
1821 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
1822 arg_lit0("l", NULL
, "swap entered key's endianness"),
1823 arg_int1("b", "block", "<dec>", "block number to write"),
1826 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
1829 uint8_t authenticationkey
[16] = {0x00};
1830 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
1831 bool swap_endian
= arg_get_lit(ctx
, 2);
1832 int blockno
= arg_get_int_def(ctx
, 3, -1);
1835 bool has_auth_key
= false;
1836 bool has_pwd
= false;
1838 has_auth_key
= true;
1839 } else if (ak_len
== 4) {
1841 } else if (ak_len
!= 0) {
1842 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
1847 PrintAndLogEx(WARNING
, "Wrong block number");
1851 uint8_t *authKeyPtr
= authenticationkey
;
1853 // start with getting tagtype
1854 TagTypeUL_t tagtype
= GetHF14AMfU_Type();
1855 if (tagtype
== UL_ERROR
)
1858 uint8_t maxblockno
= 0;
1859 for (uint8_t idx
= 0; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
1860 if (tagtype
& UL_TYPES_ARRAY
[idx
]) {
1861 maxblockno
= UL_MEMORY_ARRAY
[idx
];
1865 if (blockno
> maxblockno
) {
1866 PrintAndLogEx(WARNING
, "block number to large. Max block is %u/0x%02X \n", maxblockno
, maxblockno
);
1873 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 8);
1876 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 4);
1880 PrintAndLogEx(INFO
, "Using %s " _GREEN_("%s"), (ak_len
== 16) ? "3des" : "pwd", sprint_hex(authenticationkey
, ak_len
));
1884 uint8_t keytype
= 0;
1885 uint8_t datalen
= 0;
1889 } else if (has_pwd
) {
1894 clearCommandBuffer();
1895 SendCommandMIX(CMD_HF_MIFAREU_READBL
, blockno
, keytype
, 0, authKeyPtr
, datalen
);
1896 PacketResponseNG resp
;
1897 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
1898 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
1900 uint8_t *d
= resp
.data
.asBytes
;
1901 PrintAndLogEx(NORMAL
, "");
1902 PrintAndLogEx(INFO
, "Block# | Data | Ascii");
1903 PrintAndLogEx(INFO
, "-----------------------------");
1904 PrintAndLogEx(INFO
, "%02d/0x%02X | %s| %s\n", blockno
, blockno
, sprint_hex(d
, 4), sprint_ascii(d
, 4));
1906 PrintAndLogEx(WARNING
, "Failed reading block: ( %02x )", isOK
);
1909 PrintAndLogEx(WARNING
, "Command execute time-out");
1914 void printMFUdumpEx(mfu_dump_t
*card
, uint16_t pages
, uint8_t startpage
) {
1916 PrintAndLogEx(INFO
, _CYAN_("MFU dump file information"));
1917 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
1918 PrintAndLogEx(INFO
, " Version | " _YELLOW_("%s"), sprint_hex(card
->version
, sizeof(card
->version
)));
1919 PrintAndLogEx(INFO
, " TBD 0 | %s", sprint_hex(card
->tbo
, sizeof(card
->tbo
)));
1920 PrintAndLogEx(INFO
, " TBD 1 | %s", sprint_hex(card
->tbo1
, sizeof(card
->tbo1
)));
1921 PrintAndLogEx(INFO
, " Signature | %s", sprint_hex(card
->signature
, sizeof(card
->signature
)));
1922 for (uint8_t i
= 0; i
< 3; i
++) {
1923 PrintAndLogEx(INFO
, " Counter %d | %s", i
, sprint_hex(card
->counter_tearing
[i
], 3));
1924 PrintAndLogEx(INFO
, " Tearing %d | %s", i
, sprint_hex(card
->counter_tearing
[i
] + 3, 1));
1927 PrintAndLogEx(INFO
, "Max data page | " _YELLOW_("%d") " (" _YELLOW_("%d") " bytes)", card
->pages
- 1, card
->pages
* 4);
1928 PrintAndLogEx(INFO
, " Header size | %d", MFU_DUMP_PREFIX_LENGTH
);
1929 PrintAndLogEx(INFO
, "-------------------------------------------------------------");
1930 PrintAndLogEx(INFO
, "block# | data |lck| ascii");
1931 PrintAndLogEx(INFO
, "---------+-------------+---+------");
1934 bool lckbit
= false;
1935 uint8_t *data
= card
->data
;
1937 uint8_t lockbytes_sta
[] = {0, 0};
1938 uint8_t lockbytes_dyn
[] = {0, 0, 0};
1939 bool bit_stat
[16] = {0};
1940 bool bit_dyn
[16] = {0};
1942 // Load static lock bytes.
1943 memcpy(lockbytes_sta
, data
+ 10, sizeof(lockbytes_sta
));
1944 for (j
= 0; j
< 16; j
++) {
1945 bit_stat
[j
] = lockbytes_sta
[j
/ 8] & (1 << (7 - j
% 8));
1948 // Load dynamic lockbytes if available
1949 // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG
1952 memcpy(lockbytes_dyn
, data
+ (40 * 4), sizeof(lockbytes_dyn
));
1954 for (j
= 0; j
< 16; j
++) {
1955 bit_dyn
[j
] = lockbytes_dyn
[j
/ 8] & (1 << (7 - j
% 8));
1957 PrintAndLogEx(INFO
, "DYNAMIC LOCK: %s", sprint_hex(lockbytes_dyn
, 3));
1960 for (uint8_t i
= 0; i
< pages
; ++i
) {
1962 PrintAndLogEx(INFO
, "%3d/0x%02X | %s| | %s", i
+ startpage
, i
+ startpage
, sprint_hex(data
+ i
* 4, 4), sprint_ascii(data
+ i
* 4, 4));
1967 lckbit
= bit_stat
[4];
1970 lckbit
= bit_stat
[3];
1973 lckbit
= bit_stat
[2];
1976 lckbit
= bit_stat
[1];
1979 lckbit
= bit_stat
[0];
1982 lckbit
= bit_stat
[15];
1985 lckbit
= bit_stat
[14];
1988 lckbit
= bit_stat
[13];
1991 lckbit
= bit_stat
[12];
1994 lckbit
= bit_stat
[11];
1997 lckbit
= bit_stat
[10];
2000 lckbit
= bit_stat
[9];
2003 lckbit
= bit_stat
[8];
2009 lckbit
= bit_dyn
[6];
2015 lckbit
= bit_dyn
[5];
2021 lckbit
= bit_dyn
[4];
2027 lckbit
= bit_dyn
[2];
2033 lckbit
= bit_dyn
[1];
2039 lckbit
= bit_dyn
[0];
2042 lckbit
= bit_dyn
[12];
2045 lckbit
= bit_dyn
[11];
2048 lckbit
= bit_dyn
[10];
2051 lckbit
= bit_dyn
[9];
2056 PrintAndLogEx(INFO
, "%3d/0x%02X | %s| %s | %s", i
+ startpage
, i
+ startpage
, sprint_hex(data
+ i
* 4, 4), (lckbit
) ? _RED_("1") : "0", sprint_ascii(data
+ i
* 4, 4));
2058 PrintAndLogEx(INFO
, "---------------------------------");
2062 // Mifare Ultralight / Ultralight-C / Ultralight-EV1
2063 // Read and Dump Card Contents, using auto detection of tag size.
2064 static int CmdHF14AMfUDump(const char *Cmd
) {
2066 CLIParserContext
*ctx
;
2067 CLIParserInit(&ctx
, "hf mfu dump",
2068 "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1\n"
2069 "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216\n"
2070 "and saves data into binary/json files.\n"
2071 "It autodetects card type.",
2072 "hf mfu dump -f myfile -> dump whole tag, save to `myfile.bin`\n"
2073 "hf mfu dump -k AABBCCDD -> dump whole tag using pwd AABBCCDD\n"
2074 "hf mfu dump -p 10 -> start at page 10 and dump rest of blocks\n"
2075 "hf mfu dump -p 10 -q 2 -> start at page 10 and dump two blocks\n"
2076 "hf mfu dump --key 00112233445566778899AABBCCDDEEFF"
2079 void *argtable
[] = {
2081 arg_str0("f", "file", "<fn>", "specify a filename for dump file"),
2082 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2083 arg_lit0("l", NULL
, "swap entered key's endianness"),
2084 arg_int0("p", "page", "<dec>", "manually set start page number to start from"),
2085 arg_int0("q", "qty", "<dec>", "manually set number of pages to dump"),
2088 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2091 char filename
[FILE_PATH_SIZE
] = {0};
2092 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
2095 uint8_t authenticationkey
[16] = {0x00};
2096 uint8_t *authKeyPtr
= authenticationkey
;
2097 CLIGetHexWithReturn(ctx
, 2, authenticationkey
, &ak_len
);
2098 bool swap_endian
= arg_get_lit(ctx
, 3);
2099 int start_page
= arg_get_int_def(ctx
, 4, 0);
2100 int pages
= arg_get_int_def(ctx
, 5, 16);
2103 bool has_auth_key
= false;
2104 bool has_pwd
= false;
2106 has_auth_key
= true;
2107 } else if (ak_len
== 4) {
2109 } else if (ak_len
!= 0) {
2110 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
2114 bool manual_pages
= false;
2116 manual_pages
= true;
2119 manual_pages
= true;
2121 uint8_t card_mem_size
= 0;
2126 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 8);
2129 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, 4);
2132 TagTypeUL_t tagtype
= GetHF14AMfU_Type();
2133 if (tagtype
== UL_ERROR
)
2136 //get number of pages to read
2137 if (manual_pages
== false) {
2138 for (uint8_t idx
= 0; idx
< ARRAYLEN(UL_TYPES_ARRAY
); idx
++) {
2139 if (tagtype
& UL_TYPES_ARRAY
[idx
]) {
2140 //add one as maxblks starts at 0
2141 card_mem_size
= pages
= UL_MEMORY_ARRAY
[idx
] + 1;
2146 ul_print_type(tagtype
, 0);
2147 PrintAndLogEx(SUCCESS
, "Reading tag memory...");
2148 uint8_t keytype
= 0;
2151 keytype
= 1; //UL_C auth
2153 keytype
= 2; //UL_EV1/NTAG auth
2156 clearCommandBuffer();
2157 SendCommandMIX(CMD_HF_MIFAREU_READCARD
, start_page
, pages
, keytype
, authKeyPtr
, ak_len
);
2159 PacketResponseNG resp
;
2160 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 2500)) {
2161 PrintAndLogEx(WARNING
, "Command execute time-out");
2162 return PM3_ETIMEOUT
;
2165 if (resp
.oldarg
[0] != 1) {
2166 PrintAndLogEx(WARNING
, "Failed dumping card");
2171 uint8_t data
[1024] = {0x00};
2172 memset(data
, 0x00, sizeof(data
));
2174 uint32_t startindex
= resp
.oldarg
[2];
2175 uint32_t buffer_size
= resp
.oldarg
[1];
2176 if (buffer_size
> sizeof(data
)) {
2177 PrintAndLogEx(FAILED
, "Data exceeded Buffer size!");
2178 buffer_size
= sizeof(data
);
2181 if (!GetFromDevice(BIG_BUF
, data
, buffer_size
, startindex
, NULL
, 0, NULL
, 2500, false)) {
2182 PrintAndLogEx(WARNING
, "command execution time out");
2183 return PM3_ETIMEOUT
;
2186 bool is_partial
= (pages
!= buffer_size
/ 4);
2188 pages
= buffer_size
/ 4;
2190 iso14a_card_select_t card
;
2191 mfu_dump_t dump_file_data
;
2192 memset(&dump_file_data
, 0, sizeof(dump_file_data
));
2193 uint8_t get_version
[] = {0, 0, 0, 0, 0, 0, 0, 0};
2194 uint8_t get_counter_tearing
[][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
2195 uint8_t get_signature
[32];
2196 memset(get_signature
, 0, sizeof(get_signature
));
2198 // not ul_c and not std ul then attempt to collect info like
2199 // VERSION, SIGNATURE, COUNTERS, TEARING, PACK,
2200 if (!(tagtype
& UL_C
|| tagtype
& UL
|| tagtype
& MY_D_MOVE
|| tagtype
& MY_D_MOVE_LEAN
)) {
2201 //attempt to read pack
2202 uint8_t get_pack
[] = {0, 0};
2203 if (ul_auth_select(&card
, tagtype
, true, authKeyPtr
, get_pack
, sizeof(get_pack
)) != PM3_SUCCESS
) {
2210 // only add pack if not partial read, and complete pages read.
2211 if (!is_partial
&& pages
== card_mem_size
) {
2213 // add pack to block read
2214 memcpy(data
+ (pages
* 4) - 4, get_pack
, sizeof(get_pack
));
2218 uint8_t dummy_pack
[] = {0, 0};
2219 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
2224 ulev1_getVersion(get_version
, sizeof(get_version
));
2226 // ULEV-1 has 3 counters
2229 // NTAG has 1 counter, at 0x02
2230 if ((tagtype
& (NTAG_213
| NTAG_213_F
| NTAG_213_C
| NTAG_213_TT
| NTAG_215
| NTAG_216
))) {
2234 // NTAG can have nfc counter pwd protection enabled
2235 for (; n
< 3; n
++) {
2238 uint8_t dummy_pack
[] = {0, 0};
2239 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
2243 ulev1_readCounter(n
, &get_counter_tearing
[n
][0], 3);
2246 uint8_t dummy_pack
[] = {0, 0};
2247 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
2251 ulev1_readTearing(n
, &get_counter_tearing
[n
][3], 1);
2257 uint8_t dummy_pack
[] = {0, 0};
2258 ul_auth_select(&card
, tagtype
, has_auth_key
, authKeyPtr
, dummy_pack
, sizeof(dummy_pack
));
2262 ulev1_readSignature(get_signature
, sizeof(get_signature
));
2266 // format and add keys to block dump output
2267 // only add keys if not partial read, and complete pages read
2268 if (!is_partial
&& pages
== card_mem_size
&& has_auth_key
) {
2269 // if we didn't swapendian before - do it now for the sprint_hex call
2270 // NOTE: default entry is bigendian (unless swapped), sprint_hex outputs little endian
2271 // need to swap to keep it the same
2272 if (swap_endian
== false) {
2273 authKeyPtr
= SwapEndian64(authenticationkey
, ak_len
, (ak_len
== 16) ? 8 : 4);
2275 authKeyPtr
= authenticationkey
;
2278 if (tagtype
& UL_C
) { //add 4 pages
2279 memcpy(data
+ pages
* 4, authKeyPtr
, ak_len
);
2280 pages
+= ak_len
/ 4;
2281 } else { // 2nd page from end
2282 memcpy(data
+ (pages
* 4) - 8, authenticationkey
, ak_len
);
2286 //add *special* blocks to dump
2287 // pack and pwd saved into last pages of dump, if was not partial read
2288 dump_file_data
.pages
= pages
- 1;
2289 memcpy(dump_file_data
.version
, get_version
, sizeof(dump_file_data
.version
));
2290 memcpy(dump_file_data
.signature
, get_signature
, sizeof(dump_file_data
.signature
));
2291 memcpy(dump_file_data
.counter_tearing
, get_counter_tearing
, sizeof(dump_file_data
.counter_tearing
));
2292 memcpy(dump_file_data
.data
, data
, pages
* 4);
2294 printMFUdumpEx(&dump_file_data
, pages
, start_page
);
2296 // user supplied filename?
2299 PrintAndLogEx(INFO
, "Using UID as filename");
2300 uint8_t uid
[7] = {0};
2301 memcpy(uid
, (uint8_t *)&dump_file_data
.data
, 3);
2302 memcpy(uid
+ 3, (uint8_t *)&dump_file_data
.data
+ 4, 4);
2303 strcat(filename
, "hf-mfu-");
2304 FillFileNameByUID(filename
, uid
, "-dump", sizeof(uid
));
2306 uint16_t datalen
= pages
* 4 + MFU_DUMP_PREFIX_LENGTH
;
2307 saveFile(filename
, ".bin", (uint8_t *)&dump_file_data
, datalen
);
2308 saveFileJSON(filename
, jsfMfuMemory
, (uint8_t *)&dump_file_data
, datalen
, NULL
);
2311 PrintAndLogEx(WARNING
, "Partial dump created. (%d of %d blocks)", pages
, card_mem_size
);
2316 static void wait4response(uint8_t b
) {
2317 PacketResponseNG resp
;
2318 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2319 uint8_t isOK
= resp
.oldarg
[0] & 0xff;
2321 PrintAndLogEx(WARNING
, "failed to write block %d", b
);
2323 PrintAndLogEx(WARNING
, "Command execute timeout");
2328 // Restore dump file onto tag
2330 static int CmdHF14AMfURestore(const char *Cmd
) {
2331 CLIParserContext
*ctx
;
2332 CLIParserInit(&ctx
, "hf mfu restore",
2333 "Restore dumpfile onto card.",
2334 "hf mfu restore -f myfile -s -> user specified filename and special write\n"
2335 "hf mfu restore -f myfile -k AABBCCDD -s -> user specified filename, special write and use key\n"
2336 "hf mfu restore -f myfile -k AABBCCDD -ser -> user specified filename, special write, use key, ..."
2339 void *argtable
[] = {
2341 arg_str1("f", "file", "<fn>", "specify a filename to restore"),
2342 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes, EV1/NTAG 4 bytes)"),
2343 arg_lit0("l", NULL
, "swap entered key's endianness"),
2344 arg_lit0("s", NULL
, "enable special write UID -MAGIC TAG ONLY-"),
2345 arg_lit0("e", NULL
, "enable special write version/signature -MAGIC NTAG 21* ONLY-"),
2346 arg_lit0("r", NULL
, "use the password found in dumpfile to configure tag. requires " _YELLOW_("'-e'") " parameter to work"),
2347 arg_lit0("v", "verbose", "verbose"),
2350 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2353 char filename
[FILE_PATH_SIZE
] = {0};
2354 CLIParamStrToBuf(arg_get_str(ctx
, 1), (uint8_t *)filename
, FILE_PATH_SIZE
, &fnlen
);
2357 uint8_t authkey
[16] = {0x00};
2358 uint8_t *p_authkey
= authkey
;
2359 CLIGetHexWithReturn(ctx
, 2, authkey
, &ak_len
);
2361 bool swap_endian
= arg_get_lit(ctx
, 3);
2362 bool write_special
= arg_get_lit(ctx
, 4);
2363 bool write_extra
= arg_get_lit(ctx
, 5);
2364 bool read_key
= arg_get_lit(ctx
, 6);
2365 bool verbose
= arg_get_lit(ctx
, 7);
2369 bool has_key
= false;
2371 if (ak_len
!= 4 && ak_len
!= 16) {
2372 PrintAndLogEx(ERR
, "Wrong key length. expected 4 or 16, got %d", ak_len
);
2379 uint8_t *dump
= NULL
;
2380 size_t bytes_read
= 0;
2383 char *fptr
= GenerateFilename("hf-mfu-", "-dump.bin");
2385 strcpy(filename
, fptr
);
2387 snprintf(filename
, sizeof(filename
), "dumpdata.bin");
2392 if (loadFile_safe(filename
, "", (void **)&dump
, &bytes_read
) != PM3_SUCCESS
) {
2393 PrintAndLogEx(WARNING
, "Could not find file " _YELLOW_("%s"), filename
);
2397 if (bytes_read
< MFU_DUMP_PREFIX_LENGTH
) {
2398 PrintAndLogEx(ERR
, "Error, dump file is too small");
2403 int res
= convert_mfu_dump_format(&dump
, &bytes_read
, verbose
);
2404 if (res
!= PM3_SUCCESS
) {
2405 PrintAndLogEx(FAILED
, "Failed convert on load to new Ultralight/NTAG format");
2410 mfu_dump_t
*mem
= (mfu_dump_t
*)dump
;
2411 uint8_t pages
= (bytes_read
- MFU_DUMP_PREFIX_LENGTH
) / 4;
2413 if (pages
- 1 != mem
->pages
) {
2414 PrintAndLogEx(ERR
, "Error, invalid dump, wrong page count");
2419 PrintAndLogEx(INFO
, "Restoring " _YELLOW_("%s")" to card", filename
);
2422 printMFUdumpEx(mem
, pages
, 0);
2425 if (swap_endian
&& has_key
) {
2427 p_authkey
= SwapEndian64(authkey
, ak_len
, 8);
2429 p_authkey
= SwapEndian64(authkey
, ak_len
, 4);
2432 uint8_t data
[20] = {0};
2433 uint8_t keytype
= 0;
2434 // set key - only once
2436 keytype
= (ak_len
== 16) ? 1 : 2;
2437 memcpy(data
+ 4, p_authkey
, ak_len
);
2440 // write version, signature, pack
2441 // only magic NTAG cards
2444 #define MFU_NTAG_SPECIAL_PWD 0xF0
2445 #define MFU_NTAG_SPECIAL_PACK 0xF1
2446 #define MFU_NTAG_SPECIAL_VERSION 0xFA
2447 #define MFU_NTAG_SPECIAL_SIGNATURE 0xF2
2449 if (has_key
|| read_key
) {
2451 memcpy(data
, p_authkey
, 4);
2453 // try reading key from dump and use.
2454 memcpy(data
, mem
->data
+ (bytes_read
- MFU_DUMP_PREFIX_LENGTH
- 8), 4);
2457 PrintAndLogEx(INFO
, "special PWD block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PWD
, sprint_hex(data
, 4));
2458 clearCommandBuffer();
2459 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, MFU_NTAG_SPECIAL_PWD
, keytype
, 0, data
, sizeof(data
));
2461 wait4response(MFU_NTAG_SPECIAL_PWD
);
2465 memcpy(authkey
, data
, 4);
2466 memcpy(data
+ 4, authkey
, 4);
2470 memcpy(data
, mem
->data
+ (bytes_read
- MFU_DUMP_PREFIX_LENGTH
- 4), 2);
2473 PrintAndLogEx(INFO
, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK
, sprint_hex(data
, 4));
2474 clearCommandBuffer();
2475 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, MFU_NTAG_SPECIAL_PACK
, keytype
, 0, data
, sizeof(data
));
2476 wait4response(MFU_NTAG_SPECIAL_PACK
);
2479 for (uint8_t s
= MFU_NTAG_SPECIAL_SIGNATURE
, i
= 0; s
< MFU_NTAG_SPECIAL_SIGNATURE
+ 8; s
++, i
+= 4) {
2480 memcpy(data
, mem
->signature
+ i
, 4);
2481 PrintAndLogEx(INFO
, "special SIG block written 0x%X - %s\n", s
, sprint_hex(data
, 4));
2482 clearCommandBuffer();
2483 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, s
, keytype
, 0, data
, sizeof(data
));
2488 for (uint8_t s
= MFU_NTAG_SPECIAL_VERSION
, i
= 0; s
< MFU_NTAG_SPECIAL_VERSION
+ 2; s
++, i
+= 4) {
2489 memcpy(data
, mem
->version
+ i
, 4);
2490 PrintAndLogEx(INFO
, "special VERSION block written 0x%X - %s\n", s
, sprint_hex(data
, 4));
2491 clearCommandBuffer();
2492 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, s
, keytype
, 0, data
, sizeof(data
));
2497 PrintAndLogEx(INFO
, "Restoring data blocks.");
2498 PrintAndLogEx(INFO
, "." NOLF
);
2499 // write all other data
2500 // Skip block 0,1,2,3 (only magic tags can write to them)
2501 // Skip last 5 blocks usually is configuration
2502 for (uint8_t b
= 4; b
< pages
- 5; b
++) {
2505 memcpy(data
, mem
->data
+ (b
* 4), 4);
2506 clearCommandBuffer();
2507 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, b
, keytype
, 0, data
, sizeof(data
));
2509 PrintAndLogEx(NORMAL
, "." NOLF
);
2512 PrintAndLogEx(NORMAL
, "");
2514 // write special data last
2515 if (write_special
) {
2517 PrintAndLogEx(INFO
, "Restoring configuration blocks.\n");
2519 PrintAndLogEx(INFO
, "authentication with keytype[%x] %s\n", (uint8_t)(keytype
& 0xff), sprint_hex(p_authkey
, 4));
2521 // otp, uid, lock, cfg1, cfg0, dynlockbits
2522 uint8_t blocks
[] = {3, 0, 1, 2, pages
- 5, pages
- 4, pages
- 3};
2523 for (uint8_t i
= 0; i
< ARRAYLEN(blocks
); i
++) {
2524 uint8_t b
= blocks
[i
];
2525 memcpy(data
, mem
->data
+ (b
* 4), 4);
2526 clearCommandBuffer();
2527 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, b
, keytype
, 0, data
, sizeof(data
));
2529 PrintAndLogEx(INFO
, "special block written %u - %s\n", b
, sprint_hex(data
, 4));
2535 PrintAndLogEx(INFO
, "Restore finished");
2539 // Load emulator with dump file
2541 static int CmdHF14AMfUeLoad(const char *Cmd
) {
2543 CLIParserContext
*ctx
;
2544 CLIParserInit(&ctx
, "hf mfu eload",
2545 "Load emulator memory with data from `filename.eml` dump file\n"
2546 "\nSee `script run data_mfu_bin2eml` to convert the .bin to .eml",
2547 "hf mfu eload --ul -f hf-mfu-04010203040506.eml\n"
2548 "hf mfu eload --ul -f hf-mfu-04010203040506.eml -q 57 -> load 57 blocks from myfile"
2551 void *argtable
[] = {
2553 arg_str1("f", "file", "<fn>", "filename of dump"),
2554 arg_lit1(NULL
, "ul", "MIFARE Ultralight family"),
2555 arg_int0("q", "qty", "<dec>", "number of blocks to load from eml file"),
2558 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2560 return CmdHF14AMfELoad(Cmd
);
2565 static int CmdHF14AMfUSim(const char *Cmd
) {
2566 CLIParserContext
*ctx
;
2567 CLIParserInit(&ctx
, "hf mfu sim",
2568 "Simulate MIFARE Ultralight family type based upon\n"
2569 "ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"
2570 "from emulator memory. See `hf mfu eload` first. \n"
2571 "See `hf 14a sim -h` to see available types. You want 2 or 7 usually.",
2572 "hf mfu sim -t 2 --uid 1122344556677 -> MIFARE Ultralight\n"
2573 "hf mfu sim -t 7 --uid 1122344556677 -n 5 -> AMIIBO (NTAG 215), pack 0x8080"
2576 void *argtable
[] = {
2578 arg_int1("t", "type", "<1-10> ", "Simulation type to use"),
2579 arg_str0("u", "uid", "<hex>", "4, 7 or 10 byte UID"),
2580 arg_int0("n", "num", "<dec>", "Exit simulation after <numreads> blocks have been read by reader. 0 = infinite"),
2581 arg_lit0("v", "verbose", "verbose output"),
2584 CLIExecWithReturn(ctx
, Cmd
, argtable
, false);
2586 return CmdHF14ASim(Cmd
);
2589 //-------------------------------------------------------------------------------
2590 // Ultralight C Methods
2591 //-------------------------------------------------------------------------------
2593 // Ultralight C Authentication
2595 static int CmdHF14AMfUCAuth(const char *Cmd
) {
2596 CLIParserContext
*ctx
;
2597 CLIParserInit(&ctx
, "hf mfu cauth",
2598 "Tests 3DES password on Mifare Ultralight-C tag.\n"
2599 "If password is not specified, a set of known defaults will be tested.",
2601 "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f"
2604 void *argtable
[] = {
2606 arg_str0("k", "key", "<hex>", "key for authentication (UL-C 16 bytes)"),
2607 arg_lit0("l", NULL
, "swap entered key's endianness"),
2608 arg_lit0("k", NULL
, "keep field on (only if a password is provided too)"),
2611 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2614 uint8_t authenticationkey
[16] = {0x00};
2615 uint8_t *authKeyPtr
= authenticationkey
;
2616 CLIGetHexWithReturn(ctx
, 1, authenticationkey
, &ak_len
);
2617 bool swap_endian
= arg_get_lit(ctx
, 2);
2618 bool keep_field_on
= arg_get_lit(ctx
, 3);
2621 if (ak_len
!= 16 && ak_len
!= 0) {
2622 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
2627 if (swap_endian
&& ak_len
) {
2628 authKeyPtr
= SwapEndian64(authenticationkey
, 16, 8);
2633 // If no hex key is specified, try default keys
2635 isok
= (try_default_3des_keys(&authKeyPtr
) == PM3_SUCCESS
);
2637 // try user-supplied
2638 isok
= ulc_authentication(authKeyPtr
, !keep_field_on
);
2642 PrintAndLogEx(SUCCESS
, "Authentication success. 3des key: " _GREEN_("%s"), sprint_hex_inrow(authKeyPtr
, 16));
2644 PrintAndLogEx(WARNING
, "Authentication ( " _RED_("fail") " )");
2650 A test function to validate that the polarssl-function works the same
2651 was as the openssl-implementation.
2652 Commented out, since it requires openssl
2654 static int CmdTestDES(const char * cmd)
2656 uint8_t key[16] = {0x00};
2658 memcpy(key,key3_3des_data,16);
2659 DES_cblock RndA, RndB;
2661 PrintAndLogEx(NORMAL, "----------OpenSSL DES implementation----------");
2663 uint8_t e_RndB[8] = {0x00};
2664 unsigned char RndARndB[16] = {0x00};
2666 DES_cblock iv = { 0 };
2667 DES_key_schedule ks1,ks2;
2668 DES_cblock key1,key2;
2670 memcpy(key,key3_3des_data,16);
2672 memcpy(key2,key+8,8);
2675 DES_set_key((DES_cblock *)key1,&ks1);
2676 DES_set_key((DES_cblock *)key2,&ks2);
2678 DES_random_key(&RndA);
2679 PrintAndLogEx(NORMAL, " RndA:%s",sprint_hex(RndA, 8));
2680 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(e_RndB, 8));
2681 //void DES_ede2_cbc_encrypt(const unsigned char *input,
2682 // unsigned char *output, long length, DES_key_schedule *ks1,
2683 // DES_key_schedule *ks2, DES_cblock *ivec, int enc);
2684 DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
2686 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(RndB, 8));
2688 memcpy(RndARndB,RndA,8);
2689 memcpy(RndARndB+8,RndB,8);
2690 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(RndARndB, 16));
2691 DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
2692 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(RndARndB, 16));
2695 PrintAndLogEx(NORMAL, "----------PolarSSL implementation----------");
2697 uint8_t random_a[8] = { 0 };
2698 uint8_t enc_random_a[8] = { 0 };
2699 uint8_t random_b[8] = { 0 };
2700 uint8_t enc_random_b[8] = { 0 };
2701 uint8_t random_a_and_b[16] = { 0 };
2702 des3_context ctx = { 0 };
2704 memcpy(random_a, RndA,8);
2706 uint8_t output[8] = { 0 };
2707 uint8_t iv[8] = { 0 };
2709 PrintAndLogEx(NORMAL, " RndA :%s",sprint_hex(random_a, 8));
2710 PrintAndLogEx(NORMAL, " e_RndB:%s",sprint_hex(enc_random_b, 8));
2712 des3_set2key_dec(&ctx, key);
2714 des3_crypt_cbc(&ctx // des3_context *ctx
2715 , DES_DECRYPT // int mode
2716 , sizeof(random_b) // size_t length
2717 , iv // unsigned char iv[8]
2718 , enc_random_b // const unsigned char *input
2719 , random_b // unsigned char *output
2722 PrintAndLogEx(NORMAL, " RndB:%s",sprint_hex(random_b, 8));
2725 memcpy(random_a_and_b ,random_a,8);
2726 memcpy(random_a_and_b+8,random_b,8);
2728 PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(random_a_and_b, 16));
2730 des3_set2key_enc(&ctx, key);
2732 des3_crypt_cbc(&ctx // des3_context *ctx
2733 , DES_ENCRYPT // int mode
2734 , sizeof(random_a_and_b) // size_t length
2735 , enc_random_b // unsigned char iv[8]
2736 , random_a_and_b // const unsigned char *input
2737 , random_a_and_b // unsigned char *output
2740 PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
2747 // Mifare Ultralight C - Set password
2749 static int CmdHF14AMfUCSetPwd(const char *Cmd
) {
2750 CLIParserContext
*ctx
;
2751 CLIParserInit(&ctx
, "hf mfu setpwd",
2752 "Set the 3DES key on MIFARE Ultralight-C tag. ",
2753 "hf mfu setpwd --key 000102030405060708090a0b0c0d0e0f"
2756 void *argtable
[] = {
2758 arg_str0("k", "key", "<hex>", "New key (16 bytes)"),
2761 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2764 uint8_t key
[16] = {0x00};
2765 CLIGetHexWithReturn(ctx
, 1, key
, &k_len
);
2769 PrintAndLogEx(WARNING
, "Key must be 16 hex bytes");
2773 clearCommandBuffer();
2774 SendCommandMIX(CMD_HF_MIFAREUC_SETPWD
, 0, 0, 0, key
, sizeof(key
));
2776 PacketResponseNG resp
;
2777 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2778 if ((resp
.oldarg
[0] & 0xff) == 1) {
2779 PrintAndLogEx(INFO
, "Ultralight-C new key: %s", sprint_hex(key
, sizeof(key
)));
2781 PrintAndLogEx(WARNING
, "Failed writing at block %u", (uint8_t)(resp
.oldarg
[1] & 0xFF));
2785 PrintAndLogEx(WARNING
, "command execution time out");
2786 return PM3_ETIMEOUT
;
2792 // Magic UL / UL-C tags - Set UID
2794 static int CmdHF14AMfUCSetUid(const char *Cmd
) {
2796 CLIParserContext
*ctx
;
2797 CLIParserInit(&ctx
, "hf mfu setuid",
2798 "Set uid on MIFARE Ultralight tag.\n"
2799 "This only works for `magic Ultralight` tags.",
2800 "hf mfu setuid --uid 11223344556677"
2803 void *argtable
[] = {
2805 arg_str0("u", "uid", "<hex>", "new uid (7 bytes)"),
2808 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2811 uint8_t uid
[7] = {0x00};
2812 CLIGetHexWithReturn(ctx
, 1, uid
, &u_len
);
2816 PrintAndLogEx(WARNING
, "UID must be 7 hex bytes");
2820 PrintAndLogEx(INFO
, "Please ignore possible transient BCC warnings");
2823 PacketResponseNG resp
;
2824 clearCommandBuffer();
2825 SendCommandMIX(CMD_HF_MIFAREU_READBL
, 2, 0, 0, NULL
, 0);
2826 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2827 PrintAndLogEx(WARNING
, "Command execute timeout");
2828 return PM3_ETIMEOUT
;
2832 uint8_t oldblock2
[4] = {0x00};
2833 memcpy(resp
.data
.asBytes
, oldblock2
, 4);
2835 // Enforce bad BCC handling temporarily as BCC will be wrong between
2836 // block 1 write and block2 write
2837 hf14a_config config
;
2838 SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG
, NULL
, 0);
2839 if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG
, &resp
, 2000)) {
2840 PrintAndLogEx(WARNING
, "command execution time out");
2841 return PM3_ETIMEOUT
;
2843 memcpy(&config
, resp
.data
.asBytes
, sizeof(hf14a_config
));
2844 int8_t oldconfig_bcc
= config
.forcebcc
;
2845 if (oldconfig_bcc
!= 2) {
2846 config
.forcebcc
= 2;
2847 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG
, (uint8_t *)&config
, sizeof(hf14a_config
));
2855 data
[3] = 0x88 ^ uid
[0] ^ uid
[1] ^ uid
[2];
2856 clearCommandBuffer();
2857 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, 0, 0, 0, data
, sizeof(data
));
2858 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2859 PrintAndLogEx(WARNING
, "Command execute timeout");
2860 return PM3_ETIMEOUT
;
2868 clearCommandBuffer();
2869 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, 1, 0, 0, data
, sizeof(data
));
2870 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2871 PrintAndLogEx(WARNING
, "Command execute timeout");
2872 return PM3_ETIMEOUT
;
2876 data
[0] = uid
[3] ^ uid
[4] ^ uid
[5] ^ uid
[6];
2877 data
[1] = oldblock2
[1];
2878 data
[2] = oldblock2
[2];
2879 data
[3] = oldblock2
[3];
2880 clearCommandBuffer();
2881 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, 2, 0, 0, data
, sizeof(data
));
2882 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
2883 PrintAndLogEx(WARNING
, "Command execute timeout");
2884 return PM3_ETIMEOUT
;
2887 // restore BCC config
2888 if (oldconfig_bcc
!= 2) {
2889 config
.forcebcc
= oldconfig_bcc
;
2890 SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG
, (uint8_t *)&config
, sizeof(hf14a_config
));
2895 static int CmdHF14AMfUGenDiverseKeys(const char *Cmd
) {
2896 CLIParserContext
*ctx
;
2897 CLIParserInit(&ctx
, "hf mfu keygen",
2898 "Set the 3DES key on MIFARE Ultralight-C tag. ",
2899 "hf mfu keygen -r\n"
2900 "hf mfu keygen --uid 11223344556677"
2903 void *argtable
[] = {
2905 arg_str0("u", "uid", "<hex>", "<4|7> hex byte UID"),
2906 arg_lit0("r", NULL
, "read UID from tag"),
2909 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
2913 CLIGetHexWithReturn(ctx
, 1, uid
, &ulen
);
2914 bool read_tag
= arg_get_lit(ctx
, 2);
2918 // read uid from tag
2919 clearCommandBuffer();
2920 SendCommandMIX(CMD_HF_ISO14443A_READER
, ISO14A_CONNECT
| ISO14A_NO_RATS
, 0, 0, NULL
, 0);
2921 PacketResponseNG resp
;
2922 WaitForResponse(CMD_ACK
, &resp
);
2923 iso14a_card_select_t card
;
2924 memcpy(&card
, (iso14a_card_select_t
*)resp
.data
.asBytes
, sizeof(iso14a_card_select_t
));
2926 uint64_t select_status
= resp
.oldarg
[0];
2927 // 0: couldn't read,
2930 // 3: proprietary Anticollision
2932 if (select_status
== 0) {
2933 PrintAndLogEx(WARNING
, "iso14443a card select failed");
2937 if (card
.uidlen
!= 4 && card
.uidlen
!= 7) {
2938 PrintAndLogEx(WARNING
, "Wrong sized UID, expected 4|7 bytes got %d", card
.uidlen
);
2942 memcpy(uid
, card
.uid
, card
.uidlen
);
2944 if (ulen
!= 4 && ulen
!= 7) {
2945 PrintAndLogEx(ERR
, "Must supply 4 or 7 hex byte uid");
2950 uint8_t iv
[8] = { 0x00 };
2951 uint8_t block
= 0x01;
2953 uint8_t mifarekeyA
[] = { 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5 };
2954 uint8_t mifarekeyB
[] = { 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5 };
2955 uint8_t dkeyA
[8] = { 0x00 };
2956 uint8_t dkeyB
[8] = { 0x00 };
2958 uint8_t masterkey
[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
2959 uint8_t mix
[8] = { 0x00 };
2960 uint8_t divkey
[8] = { 0x00 };
2962 memcpy(mix
, mifarekeyA
, 4);
2964 mix
[4] = mifarekeyA
[4] ^ uid
[0];
2965 mix
[5] = mifarekeyA
[5] ^ uid
[1];
2966 mix
[6] = block
^ uid
[2];
2969 mbedtls_des3_context ctx_des3
;
2970 mbedtls_des3_set2key_enc(&ctx_des3
, masterkey
);
2972 mbedtls_des3_crypt_cbc(&ctx_des3
// des3_context
2973 , MBEDTLS_DES_ENCRYPT
// int mode
2974 , sizeof(mix
) // length
2980 PrintAndLogEx(SUCCESS
, "-- 3DES version");
2981 PrintAndLogEx(SUCCESS
, "Masterkey......... %s", sprint_hex(masterkey
, sizeof(masterkey
)));
2982 PrintAndLogEx(SUCCESS
, "UID............... %s", sprint_hex(uid
, ulen
));
2983 PrintAndLogEx(SUCCESS
, "block............. %0d", block
);
2984 PrintAndLogEx(SUCCESS
, "Mifare key........ %s", sprint_hex(mifarekeyA
, sizeof(mifarekeyA
)));
2985 PrintAndLogEx(SUCCESS
, "Message........... %s", sprint_hex(mix
, sizeof(mix
)));
2986 PrintAndLogEx(SUCCESS
, "Diversified key... %s", sprint_hex(divkey
+ 1, 6));
2988 for (int i
= 0; i
< ARRAYLEN(mifarekeyA
); ++i
) {
2989 dkeyA
[i
] = (mifarekeyA
[i
] << 1) & 0xff;
2990 dkeyA
[6] |= ((mifarekeyA
[i
] >> 7) & 1) << (i
+ 1);
2993 for (int i
= 0; i
< ARRAYLEN(mifarekeyB
); ++i
) {
2994 dkeyB
[1] |= ((mifarekeyB
[i
] >> 7) & 1) << (i
+ 1);
2995 dkeyB
[2 + i
] = (mifarekeyB
[i
] << 1) & 0xff;
2998 uint8_t zeros
[8] = {0x00};
2999 uint8_t newpwd
[8] = {0x00};
3000 uint8_t dmkey
[24] = {0x00};
3001 memcpy(dmkey
, dkeyA
, 8);
3002 memcpy(dmkey
+ 8, dkeyB
, 8);
3003 memcpy(dmkey
+ 16, dkeyA
, 8);
3004 memset(iv
, 0x00, 8);
3006 mbedtls_des3_set3key_enc(&ctx_des3
, dmkey
);
3008 mbedtls_des3_crypt_cbc(&ctx_des3
// des3_context
3009 , MBEDTLS_DES_ENCRYPT
// int mode
3010 , sizeof(newpwd
) // length
3016 PrintAndLogEx(SUCCESS
, "\n-- DES version");
3017 PrintAndLogEx(SUCCESS
, "MIFARE dkeyA...... %s", sprint_hex(dkeyA
, sizeof(dkeyA
)));
3018 PrintAndLogEx(SUCCESS
, "MIFARE dkeyB...... %s", sprint_hex(dkeyB
, sizeof(dkeyB
)));
3019 PrintAndLogEx(SUCCESS
, "MIFARE ABA........ %s", sprint_hex(dmkey
, sizeof(dmkey
)));
3020 PrintAndLogEx(SUCCESS
, "MIFARE PWD........ %s", sprint_hex(newpwd
, sizeof(newpwd
)));
3022 mbedtls_des3_free(&ctx_des3
);
3024 mbedtls_aes_context ctx_aes
;
3025 uint8_t aes_iv
[16] = { 0x00 };
3026 uint8_t aes_masterkey
[] = { 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
3027 uint8_t aes_input
[16] = {0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80, 0x01, 0x04, 0x2A, 0x2E, 0x19, 0x70, 0x1C, 0x80};
3028 uint8_t aes_output
[16] = {0x00};
3029 mbedtls_aes_setkey_enc(&ctx_aes
, aes_masterkey
, 128);
3030 mbedtls_aes_crypt_cbc(&ctx_aes
, MBEDTLS_AES_ENCRYPT
, 16, aes_iv
, aes_input
, aes_output
);
3031 mbedtls_aes_free(&ctx_aes
);
3033 PrintAndLogEx(SUCCESS
, "\n-- AES version");
3034 PrintAndLogEx(SUCCESS
, "MIFARE AES mk..... %s", sprint_hex(aes_masterkey
, sizeof(aes_masterkey
)));
3035 PrintAndLogEx(SUCCESS
, "MIFARE Div........ %s", sprint_hex(aes_output
, sizeof(aes_output
)));
3037 // next. from the diversify_key method.
3041 static int CmdHF14AMfUPwdGen(const char *Cmd
) {
3042 CLIParserContext
*ctx
;
3043 CLIParserInit(&ctx
, "hf mfu pwdgen",
3044 "Generate different passwords from known pwdgen algos",
3045 "hf mfu pwdgen -r\n"
3046 "hf mfu pwdgen -t\n"
3047 "hf mfu pwdgen --uid 11223344556677"
3050 void *argtable
[] = {
3052 arg_str0("u", "uid", "<hex>", "uid (7 bytes)"),
3053 arg_lit0("r", NULL
, "read uid from tag"),
3054 arg_lit0("t", NULL
, "selftest"),
3057 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3060 uint8_t uid
[7] = {0x00};
3061 CLIGetHexWithReturn(ctx
, 1, uid
, &u_len
);
3062 bool use_tag
= arg_get_lit(ctx
, 2);
3063 bool selftest
= arg_get_lit(ctx
, 3);
3067 return generator_selftest();
3070 // read uid from tag
3071 int res
= ul_read_uid(uid
);
3072 if (res
!= PM3_SUCCESS
) {
3078 PrintAndLogEx(WARNING
, "Key must be 7 hex bytes");
3083 PrintAndLogEx(INFO
, "---------------------------------");
3084 PrintAndLogEx(INFO
, " Using UID : %s", sprint_hex(uid
, 7));
3085 PrintAndLogEx(INFO
, "---------------------------------");
3086 PrintAndLogEx(INFO
, " algo | pwd | pack");
3087 PrintAndLogEx(INFO
, "----------------+----------+-----");
3088 PrintAndLogEx(INFO
, " EV1 | %08X | %04X", ul_ev1_pwdgenA(uid
), ul_ev1_packgenA(uid
));
3089 PrintAndLogEx(INFO
, " Amiibo | %08X | %04X", ul_ev1_pwdgenB(uid
), ul_ev1_packgenB(uid
));
3090 PrintAndLogEx(INFO
, " Lego Dimension | %08X | %04X", ul_ev1_pwdgenC(uid
), ul_ev1_packgenC(uid
));
3091 PrintAndLogEx(INFO
, " XYZ 3D printer | %08X | %04X", ul_ev1_pwdgenD(uid
), ul_ev1_packgenD(uid
));
3092 PrintAndLogEx(INFO
, "----------------+----------+-----");
3093 PrintAndLogEx(INFO
, " Vingcard algo");
3094 PrintAndLogEx(INFO
, "---------------------------------");
3099 // MFU TearOff against OTP
3102 static int CmdHF14AMfuOtpTearoff(const char *Cmd
) {
3103 CLIParserContext
*ctx
;
3104 CLIParserInit(&ctx
, "hf mfu otptear",
3105 "Tear-off test against OTP block",
3106 "hf mfu otptear -b 3\n"
3107 "hf mfu otptear -b 3 -i 100 -s 1000\n"
3108 "hf mfu otptear -b 3 -i 1 -e 200\n"
3109 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE\n"
3110 "hf mfu otptear -b 3 -i 100 -s 200 -e 2500 -d FFFFFFFF -t EEEEEEEE -m 00000000 -> quit when OTP is reset"
3113 void *argtable
[] = {
3115 arg_u64_0("b", "blk", "<dec>", "target block (def 8)"),
3116 arg_u64_0("i", "inc", "<dec>", "increase time steps (def 500 us)"),
3117 arg_u64_0("e", "end", "<dec>", "end time (def 3000 us)"),
3118 arg_u64_0("s", "start", "<dec>", "start time (def 0 us)"),
3119 arg_str0("d", "data", "<hex>", "initialise data before run (4 bytes)"),
3120 arg_str0("t", "test", "<hex>", "test write data (4 bytes, 00000000 by default)"),
3121 arg_str0("m", "match", "<hex>", "exit criteria, if block matches this value (4 bytes)"),
3124 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3126 uint8_t blockno
= arg_get_u32_def(ctx
, 1, 8);
3127 uint32_t steps
= arg_get_u32_def(ctx
, 2, 500);
3128 uint32_t end
= arg_get_u32_def(ctx
, 3, 3000);
3129 uint32_t start
= arg_get_u32_def(ctx
, 4, 0);
3132 uint8_t data
[4] = {0x00};
3133 CLIGetHexWithReturn(ctx
, 5, data
, &d_len
);
3134 bool use_data
= (d_len
> 0);
3137 uint8_t test
[4] = {0x00};
3138 CLIGetHexWithReturn(ctx
, 6, test
, &t_len
);
3141 uint8_t match
[4] = {0x00};
3142 CLIGetHexWithReturn(ctx
, 7, match
, &m_len
);
3143 bool use_match
= (m_len
> 0);
3147 PrintAndLogEx(WARNING
, "Block number must be larger than 2.");
3151 PrintAndLogEx(WARNING
, "end time smaller than increase value");
3155 PrintAndLogEx(WARNING
, "end time - out of 1 .. 43000 range");
3158 if (start
> (end
- steps
)) {
3159 PrintAndLogEx(WARNING
, "Start time larger than (end time + steps)");
3163 if (d_len
&& d_len
!= 4) {
3164 PrintAndLogEx(WARNING
, "data must be 4 hex bytes");
3168 if (t_len
&& t_len
!= 4) {
3169 PrintAndLogEx(WARNING
, "test data must be 4 hex bytes");
3173 if (m_len
&& m_len
!= 4) {
3174 PrintAndLogEx(WARNING
, "match data must be 4 hex bytes");
3178 uint8_t teardata
[4] = {0x00};
3179 memcpy(teardata
, test
, sizeof(test
));
3181 PrintAndLogEx(INFO
, "----------------- " _CYAN_("MFU Tear off") " ---------------------");
3182 PrintAndLogEx(INFO
, "Starting Tear-off test");
3183 PrintAndLogEx(INFO
, "Target block no: %u", blockno
);
3185 PrintAndLogEx(INFO
, "Target inital block data : %s", sprint_hex_inrow(data
, 4));
3187 PrintAndLogEx(INFO
, "Target write block data : %s", sprint_hex_inrow(teardata
, 4));
3189 PrintAndLogEx(INFO
, "Target match block data : %s", sprint_hex_inrow(match
, 4));
3191 PrintAndLogEx(INFO
, "----------------------------------------------------");
3193 bool lock_on
= false;
3194 uint8_t pre
[4] = {0};
3195 uint8_t post
[4] = {0};
3196 uint32_t current
= start
;
3197 int phase_begin_clear
= -1;
3198 int phase_end_clear
= -1;
3199 int phase_begin_newwr
= -1;
3200 int phase_end_newwr
= -1;
3201 bool skip_phase1
= false;
3202 uint8_t retries
= 0;
3203 uint8_t error_retries
= 0;
3205 while ((current
<= (end
- steps
)) && (error_retries
< 10)) {
3207 if (kbd_enter_pressed()) {
3208 PrintAndLogEx(WARNING
, "\naborted via keyboard!\n");
3212 PrintAndLogEx(INFO
, "Using tear-off delay " _GREEN_("%" PRIu32
) " us", current
);
3214 clearCommandBuffer();
3215 PacketResponseNG resp
;
3218 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL
, blockno
, 0, 0, data
, d_len
);
3219 bool got_written
= false;
3220 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
3221 isOK
= resp
.oldarg
[0] & 0xff;
3226 if (! got_written
) {
3227 PrintAndLogEx(FAILED
, "Failed to write block BEFORE");
3229 continue; // try again
3233 SendCommandMIX(CMD_HF_MIFAREU_READBL
, blockno
, 0, 0, NULL
, 0);
3235 bool got_pre
= false;
3236 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
3237 isOK
= resp
.oldarg
[0] & 0xFF;
3239 memcpy(pre
, resp
.data
.asBytes
, sizeof(pre
));
3244 PrintAndLogEx(FAILED
, "Failed to read block BEFORE");
3246 continue; // try again
3248 clearCommandBuffer();
3249 SendCommandMIX(CMD_HF_MFU_OTP_TEAROFF
, blockno
, current
, 0, teardata
, sizeof(teardata
));
3251 // we be getting ACK that we are silently ignoring here..
3253 if (!WaitForResponseTimeout(CMD_HF_MFU_OTP_TEAROFF
, &resp
, 2000)) {
3254 PrintAndLogEx(WARNING
, "Failed");
3258 if (resp
.status
!= PM3_SUCCESS
) {
3259 PrintAndLogEx(WARNING
, "Tear off reporting failure to select tag");
3264 bool got_post
= false;
3265 clearCommandBuffer();
3266 SendCommandMIX(CMD_HF_MIFAREU_READBL
, blockno
, 0, 0, NULL
, 0);
3267 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 1500)) {
3268 isOK
= resp
.oldarg
[0] & 0xFF;
3270 memcpy(post
, resp
.data
.asBytes
, sizeof(post
));
3275 PrintAndLogEx(FAILED
, "Failed to read block BEFORE");
3277 continue; // try again
3280 char prestr
[20] = {0};
3281 snprintf(prestr
, sizeof(prestr
), "%s", sprint_hex_inrow(pre
, sizeof(pre
)));
3282 char poststr
[20] = {0};
3283 snprintf(poststr
, sizeof(poststr
), "%s", sprint_hex_inrow(post
, sizeof(post
)));
3285 if (memcmp(pre
, post
, sizeof(pre
)) == 0) {
3287 PrintAndLogEx(INFO
, "Current : %02d (0x%02X) %s"
3293 PrintAndLogEx(INFO
, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s")
3302 uint32_t post32
= bytes_to_num(post
, 4);
3303 uint32_t pre32
= bytes_to_num(pre
, 4);
3305 if ((phase_begin_clear
== -1) && (bitcount32(pre32
) > bitcount32(post32
)))
3306 phase_begin_clear
= current
;
3308 if ((phase_begin_clear
> -1) && (phase_end_clear
== -1) && (bitcount32(post32
) == 0))
3309 phase_end_clear
= current
;
3311 if ((current
== start
) && (phase_end_clear
> -1))
3313 // new write phase must be atleast 100us later..
3314 if (((bitcount32(pre32
) == 0) || (phase_end_clear
> -1)) && (phase_begin_newwr
== -1) && (bitcount32(post32
) != 0) && (skip_phase1
|| (current
> (phase_end_clear
+ 100))))
3315 phase_begin_newwr
= current
;
3317 if ((phase_begin_newwr
> -1) && (phase_end_newwr
== -1) && (memcmp(post
, teardata
, sizeof(teardata
)) == 0))
3318 phase_end_newwr
= current
;
3321 if (use_match
&& memcmp(post
, match
, sizeof(post
)) == 0) {
3322 PrintAndLogEx(SUCCESS
, "Block matches stop condition!\n");
3326 /* TEMPORALLY DISABLED
3327 uint8_t d0, d1, d2, d3;
3328 d0 = *resp.data.asBytes;
3329 d1 = *(resp.data.asBytes + 1);
3330 d2 = *(resp.data.asBytes + 2);
3331 d3 = *(resp.data.asBytes + 3);
3332 if ((d0 != 0xFF) || (d1 != 0xFF) || (d2 != 0xFF) || (d3 = ! 0xFF)) {
3333 PrintAndLogEx(NORMAL, "---------------------------------");
3334 PrintAndLogEx(NORMAL, " EFFECT AT: %d us", actualTime);
3335 PrintAndLogEx(NORMAL, "---------------------------------\n");
3341 if (lock_on
== false) {
3342 if (++retries
== 20) {
3347 PrintAndLogEx(INFO
, _CYAN_("Retried %u times, increased delay with 1us"), retries
);
3353 PrintAndLogEx(INFO
, "----------------------------------------------------");
3354 if ((phase_begin_clear
> - 1) && (phase_begin_clear
!= start
)) {
3355 PrintAndLogEx(INFO
, "Erase phase start boundary around " _YELLOW_("%5d") " us", phase_begin_clear
);
3357 if ((phase_end_clear
> - 1) && (phase_end_clear
!= start
)) {
3358 PrintAndLogEx(INFO
, "Erase phase end boundary around " _YELLOW_("%5d") " us", phase_end_clear
);
3360 if (phase_begin_newwr
> - 1) {
3361 PrintAndLogEx(INFO
, "Write phase start boundary around " _YELLOW_("%5d") " us", phase_begin_newwr
);
3363 if (phase_end_newwr
> - 1) {
3364 PrintAndLogEx(INFO
, "Write phase end boundary around " _YELLOW_("%5d") " us", phase_end_newwr
);
3366 PrintAndLogEx(NORMAL
, "");
3371 static int counter_reset_tear(iso14a_card_select_t *card, uint8_t cnt_no) {
3373 PrintAndLogEx(INFO, "Reset tear check");
3375 uint8_t cw[6] = { MIFARE_ULEV1_INCR_CNT, cnt_no, 0x00, 0x00, 0x00, 0x00};
3376 uint8_t ct[1] = {0};
3377 uint8_t resp[10] = {0};
3379 if (ul_select(card) == false) {
3380 PrintAndLogEx(FAILED, "failed to select card, exiting...");
3383 if (ul_send_cmd_raw(cw, sizeof(cw), resp, sizeof(resp)) < 0) {
3384 PrintAndLogEx(FAILED, "failed to write all ZEROS");
3387 if (ulev1_readTearing(cnt_no, ct, sizeof(ct)) < 0) {
3388 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
3393 if (ct[0] != 0xBD) {
3394 PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
3402 static int CmdHF14AMfuEv1CounterTearoff(const char *Cmd) {
3404 CLIParserContext *ctx;
3405 CLIParserInit(&ctx, "hf mfu countertear",
3406 "Tear-off test against a Ev1 counter",
3407 "hf mfu countertear\n"
3408 "hf mfu countertear -s 200 -l 2500 -> target counter 0, start delay 200\n"
3409 "hf mfu countertear -i 2 -s 200 -l 400 -> target counter 0, start delay 200\n"
3412 void *argtable[] = {
3414 arg_int0("c", "cnt", "<0,1,2>", "Target this EV1 counter (0,1,2)"),
3415 arg_int0("i", "inc", "<dec>", "time interval to increase in each iteration - default 10 us"),
3416 arg_int0("l", "limit", "<dec>", "test upper limit time - default 3000 us"),
3417 arg_int0("s", "start", "<dec>", "test start time - default 0 us"),
3418 arg_int0(NULL, "fix", "<dec>", "test fixed loop delay"),
3419 arg_str0("x", "hex", NULL, "3 byte hex to increase counter with"),
3422 CLIExecWithReturn(ctx, Cmd, argtable, false);
3425 int time_limit, start_time = 0;
3426 int counter = arg_get_int_def(ctx, 1, 0);
3427 int fixed = arg_get_int_def(ctx, 5, -1);
3429 if ( fixed == -1 ) {
3430 interval = arg_get_int_def(ctx, 2, 10);
3431 time_limit = arg_get_int_def(ctx, 3, 3000);
3432 start_time = arg_get_int_def(ctx, 4, 0);
3439 uint8_t newvalue[5] = {0};
3440 int newvaluelen = 0;
3441 CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
3445 if (start_time > (time_limit - interval)) {
3446 PrintAndLogEx(WARNING, "Wrong start time number");
3449 if (time_limit < interval) {
3450 PrintAndLogEx(WARNING, "Wrong time limit number");
3453 if (time_limit > 43000) {
3454 PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
3458 if (counter < 0 || counter > 2) {
3459 PrintAndLogEx(WARNING, "Counter must 0, 1 or 2");
3463 cnt_no = (uint8_t)counter;
3465 iso14a_card_select_t card;
3467 // reset counter tear
3468 counter_reset_tear(&card, cnt_no);
3470 if (ul_select(&card) == false) {
3471 PrintAndLogEx(INFO, "failed to select card, exiting...");
3475 uint8_t inital_cnt[3] = {0, 0, 0};
3476 int len = ulev1_readCounter(cnt_no, inital_cnt, sizeof(inital_cnt));
3477 if ( len != sizeof(inital_cnt) ) {
3478 PrintAndLogEx(WARNING, "failed to read counter");
3482 uint8_t inital_tear[1] = {0};
3483 len = ulev1_readTearing(cnt_no, inital_tear, sizeof(inital_tear));
3485 if ( len != sizeof(inital_tear) ) {
3486 PrintAndLogEx(WARNING, "failed to read ANTITEAR, exiting... %d", len);
3490 uint32_t wr_value = ( newvalue[0] | newvalue[1] << 8 | newvalue[2] << 16 );
3491 uint32_t inital_value = ( inital_cnt[0] | inital_cnt[1] << 8 | inital_cnt[2] << 16 );;
3493 PrintAndLogEx(INFO, "----------------- " _CYAN_("MFU Ev1 Counter Tear off") " ---------------------");
3494 PrintAndLogEx(INFO, "Target counter no [ " _GREEN_("%u") " ]", counter);
3495 PrintAndLogEx(INFO, " counter value [ " _GREEN_("%s") " ]", sprint_hex_inrow(inital_cnt, sizeof(inital_cnt)));
3496 PrintAndLogEx(INFO, " anti-tear value [ " _GREEN_("%02X") " ]", inital_tear[0]);
3497 PrintAndLogEx(INFO, " increase value [ " _GREEN_("%s") " ]", sprint_hex_inrow(newvalue, newvaluelen));
3498 PrintAndLogEx(INFO, "----------------------------------------------------");
3500 uint8_t pre_tear = 0, post_tear = 0;
3501 uint8_t pre[3] = {0};
3502 uint8_t post[3] = {0};
3503 uint32_t actual_time = start_time;
3504 uint32_t a = 0, b = 0;
3509 while (actual_time <= (time_limit - interval)) {
3515 if (kbd_enter_pressed()) {
3516 PrintAndLogEx(INFO, "\naborted via keyboard!\n");
3520 PrintAndLogEx(INPLACE, "Using tear-off delay " _GREEN_("%" PRIu32) " µs (attempt %u)", actual_time, loop);
3522 if (ul_select(&card) == false) {
3523 PrintAndLogEx(FAILED, "BEFORE, failed to select card, looping...");
3527 uint8_t cntresp[3] = {0, 0, 0};
3528 int rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
3529 if ( rlen == sizeof(cntresp) ) {
3530 memcpy(pre, cntresp, sizeof(pre));
3532 PrintAndLogEx(NORMAL, "");
3533 PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
3537 uint8_t tear[1] = {0};
3538 int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
3539 if ( tlen == sizeof(tear) ) {
3542 PrintAndLogEx(NORMAL, "");
3543 PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
3551 uint32_t tearoff_time;
3554 payload.counter = cnt_no;
3555 payload.tearoff_time = actual_time;
3556 memcpy(payload.value, newvalue, sizeof(payload.value));
3558 clearCommandBuffer();
3559 PacketResponseNG resp;
3560 SendCommandNG(CMD_HF_MFU_COUNTER_TEAROFF, (uint8_t*)&payload, sizeof(payload));
3561 if (!WaitForResponseTimeout(CMD_HF_MFU_COUNTER_TEAROFF, &resp, 2000)) {
3562 PrintAndLogEx(WARNING, "\ntear off command failed");
3566 if (ul_select(&card) == false) {
3567 PrintAndLogEx(FAILED, "AFTER, failed to select card, exiting...");
3571 rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
3572 if ( rlen == sizeof(cntresp) ) {
3573 memcpy(post, cntresp, sizeof(post));
3575 PrintAndLogEx(NORMAL, "");
3576 PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
3581 tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
3582 if ( tlen == sizeof(tear) ) {
3583 post_tear = tear[0];
3585 PrintAndLogEx(NORMAL, "");
3586 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
3592 char prestr[20] = {0};
3593 snprintf(prestr, sizeof(prestr), "%s", sprint_hex_inrow(pre, sizeof(pre)));
3594 char poststr[20] = {0};
3595 snprintf(poststr, sizeof(poststr), "%s", sprint_hex_inrow(post, sizeof(post)));
3597 bool post_tear_check = (post_tear == 0xBD);
3598 a = (pre[0] | pre[1] << 8 | pre[2] << 16);
3599 b = (post[0] | post[1] << 8 | post[2] << 16);
3602 if (memcmp(pre, post, sizeof(pre)) != 0) {
3605 PrintAndLogEx(NORMAL, "");
3607 if (inital_value != a ) {
3609 if ( inital_value != b )
3610 PrintAndLogEx(INFO, "pre %08x, post %08x != inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
3612 PrintAndLogEx(INFO, "pre %08x != inital and post %08x == inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
3615 if ( inital_value != b )
3616 PrintAndLogEx(INFO, "pre %08x == inital and post %08x != inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
3620 PrintAndLogEx(INFO, _CYAN_("Tear off occured (ZEROS value!) -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
3625 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3631 PrintAndLogEx(INFO, _CYAN_("Tear off occured " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
3636 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3640 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
3641 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
3645 uint32_t bar = (0x1000000 - b) + 2;
3647 // newvalue[0] = (bar) & 0xFF;
3648 // newvalue[1] = ((bar >> 8) & 0xFF);
3649 // newvalue[2] = ((bar >> 16) & 0xFF);
3656 PrintAndLogEx(INFO, " 0x1000000 - 0x%x == 0x%x", b, bar);
3657 PrintAndLogEx(INFO, " new increase value 0x%x" , wr_value);
3658 PrintAndLogEx(INFO, " because BAR + post == 0x%x" , bar + b);
3660 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
3664 PrintAndLogEx(NORMAL, "");
3665 PrintAndLogEx(INFO, _CYAN_("Tear off occured (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
3670 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3673 if ( post_tear_check && b == inital_value) {
3674 PrintAndLogEx(INFO, "Reverted to previous value");
3677 if ( wr_value != 0 ) {
3679 //uint32_t bar = (0x1000000 - b) + 2;
3685 if ( b >= (inital_value + (2 * wr_value))) {
3686 PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
3690 // newvalue[0] = (bar) & 0xFF;
3691 // newvalue[1] = ((bar >> 8) & 0xFF);
3692 // newvalue[2] = ((bar >> 16) & 0xFF);
3696 // newvalue[0] = (bar) & 0xFF;
3697 // newvalue[1] = ((bar >> 8) & 0xFF);
3698 // newvalue[2] = ((bar >> 16) & 0xFF);
3706 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
3712 PrintAndLogEx(NORMAL, "");
3713 PrintAndLogEx(INFO, _CYAN_("Status: same value! -> ") "%s == %s Tear: 0x%02X == 0x%02X ( %s )"
3718 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3721 if ( post_tear_check ) {
3727 if ( b == inital_value ) {
3728 PrintAndLogEx(INFO, "Reverted to previous value");
3733 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
3734 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
3741 actual_time += interval;
3746 PrintAndLogEx(INFO, " Sent %u tear offs ", loop);
3748 counter_reset_tear(&card, cnt_no);
3750 PrintAndLogEx(INFO, "hf 14a raw -s -c 3900 --> read counter 0");
3751 PrintAndLogEx(INFO, "hf 14a raw -s -c 3e00 --> read tearing 0");
3752 PrintAndLogEx(NORMAL, "");
3753 char read_cnt_str[30];
3754 sprintf(read_cnt_str, "hf 14a raw -s -c 39%02x", counter);
3755 CommandReceived(read_cnt_str);
3756 char read_tear_str[30];
3757 sprintf(read_tear_str, "hf 14a raw -s -c 3e%02x", counter);
3758 CommandReceived(read_tear_str);
3765 // name, identifying bytes, decode function, hints text
3767 // 1. getversion data must match.
3768 // 2. magic bytes in the readable payload
3771 int CmdHF14MfuNDEFRead(const char *Cmd
) {
3774 int maxsize
= 16, status
;
3775 bool hasAuthKey
= false;
3776 bool swapEndian
= false;
3778 iso14a_card_select_t card
;
3779 uint8_t data
[16] = {0x00};
3780 uint8_t key
[16] = {0x00};
3781 uint8_t *p_key
= key
;
3782 uint8_t pack
[4] = {0, 0, 0, 0};
3784 CLIParserContext
*ctx
;
3785 CLIParserInit(&ctx
, "hf mfu ndefread",
3786 "Prints NFC Data Exchange Format (NDEF)",
3787 "hf mfu ndefread -> shows NDEF data\n"
3788 "hf mfu ndefread -k ffffffff -> shows NDEF data with key");
3790 void *argtable
[] = {
3792 arg_str0("k", "key", "replace default key for NDEF", NULL
),
3793 arg_lit0("l", NULL
, "swap entered key's endianness"),
3796 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3797 CLIGetHexWithReturn(ctx
, 1, key
, &keylen
);
3798 swapEndian
= arg_get_lit(ctx
, 2);
3809 PrintAndLogEx(WARNING
, "ERROR: Key is incorrect length\n");
3814 TagTypeUL_t tagtype
= GetHF14AMfU_Type();
3815 if (tagtype
== UL_ERROR
) {
3816 PrintAndLogEx(WARNING
, "No Ultraligth / NTAG based tag found");
3823 if (swapEndian
&& hasAuthKey
) p_key
= SwapEndian64(key
, keylen
, (keylen
== 16) ? 8 : 4);
3826 if (ul_auth_select(&card
, tagtype
, hasAuthKey
, p_key
, pack
, sizeof(pack
)) == PM3_ESOFT
) return PM3_ESOFT
;
3828 // read pages 0,1,2,3 (should read 4pages)
3829 status
= ul_read(0, data
, sizeof(data
));
3832 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ");
3834 } else if (status
== 16) {
3836 status
= ndef_print_CC(data
+ 12);
3837 if (status
== PM3_ESOFT
) {
3839 PrintAndLogEx(ERR
, "Error: tag didn't contain a NDEF Container");
3844 maxsize
= ndef_get_maxsize(data
+ 12);
3847 // iceman: maybe always take MIN of tag identified size vs NDEF reported size?
3848 // fix: UL_EV1 48bytes != NDEF reported size
3849 for (uint8_t i
= 0; i
< ARRAYLEN(UL_TYPES_ARRAY
); i
++) {
3850 if (tagtype
& UL_TYPES_ARRAY
[i
]) {
3852 if (maxsize
!= (UL_MEMORY_ARRAY
[i
] * 4)) {
3853 PrintAndLogEx(INFO
, "Tag reported size vs NDEF reported size mismatch. Using smallest value");
3855 maxsize
= MIN(maxsize
, (UL_MEMORY_ARRAY
[i
] * 4));
3861 uint8_t *records
= calloc(maxsize
, sizeof(uint8_t));
3862 if (records
== NULL
) {
3867 // read NDEF records.
3868 for (uint16_t i
= 0, j
= 0; i
< maxsize
; i
+= 16, j
+= 4) {
3869 status
= ul_read(4 + j
, records
+ i
, 16);
3872 PrintAndLogEx(ERR
, "Error: tag didn't answer to READ");
3879 status
= NDEFRecordsDecodeAndPrint(records
, (size_t)maxsize
);
3880 if (status
!= PM3_SUCCESS
) {
3881 status
= NDEFDecodeAndPrint(records
, (size_t)maxsize
, true);
3884 char *jooki
= strstr((char *)records
, "s.jooki.rocks/s/?s=");
3888 if ((*jooki
) != '=')
3893 strncpy(s
, jooki
, 16);
3894 PrintAndLogEx(HINT
, "Use `" _YELLOW_("hf jooki decode -d %s") "` to decode", s
);
3899 char *mattel
= strstr((char *)records
, ".pid.mattel/");
3903 if ((*mattel
) != '/')
3908 strncpy(b64
, mattel
, 32);
3909 uint8_t arr
[24] = {0};
3911 mbedtls_base64_decode(arr
, sizeof(arr
), &arrlen
, (const unsigned char *)b64
, 32);
3913 PrintAndLogEx(INFO
, "decoded... %s", sprint_hex(arr
, arrlen
));
3923 static int CmdHF14AMfuEView(const char *Cmd
) {
3924 CLIParserContext
*ctx
;
3925 CLIParserInit(&ctx
, "hf mfu eview",
3926 "It displays emulator memory",
3930 void *argtable
[] = {
3934 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
3937 uint16_t blocks
= 0xFF;
3938 uint16_t bytes
= blocks
* 4;
3940 uint8_t *dump
= calloc(bytes
, sizeof(uint8_t));
3942 PrintAndLogEx(WARNING
, "Fail, cannot allocate memory");
3946 PrintAndLogEx(INFO
, "downloading from emulator memory");
3947 if (!GetFromDevice(BIG_BUF_EML
, dump
, bytes
, 0, NULL
, 0, NULL
, 2500, false)) {
3948 PrintAndLogEx(WARNING
, "Fail, transfer from device time-out");
3950 return PM3_ETIMEOUT
;
3953 PrintAndLogEx(NORMAL
, "");
3954 PrintAndLogEx(INFO
, "----+-------------+-------");
3955 PrintAndLogEx(INFO
, "blk | data | ascii");
3956 PrintAndLogEx(INFO
, "----+-------------+-------");
3957 for (uint16_t i
= 0; i
< blocks
; i
++) {
3958 PrintAndLogEx(INFO
, "%03d | %s ", i
, sprint_hex_ascii(dump
+ (i
* 4), 4));
3960 PrintAndLogEx(INFO
, "----+-------------+-------");
3961 PrintAndLogEx(NORMAL
, "");
3967 static int CmdHF14AMfUCDecryptAmiibo(const char *Cmd){
3969 CLIParserContext *ctx;
3970 CLIParserInit(&ctx, "hf mfu decrypt",
3971 "Tries to read all memory from amiibo tag and decrypt it",
3975 void *argtable[] = {
3979 CLIExecWithReturn(ctx, Cmd, argtable, true);
3982 uint16_t elen = 0, dlen = 0;
3983 uint8_t *encrypted = NULL;
3985 int res = mfu_dump_tag( MAX_NTAG_215, (void **)&encrypted, &elen);
3986 if (res == PM3_SUCCESS) {
3988 PrintAndLogEx(INFO, "32 first bytes of tag dump");
3989 PrintAndLogEx(INFO, "%s", sprint_hex(encrypted, 32));
3990 PrintAndLogEx(INFO, "-----------------------");
3992 uint8_t decrypted[NFC3D_AMIIBO_SIZE] = {0};
3993 res = mfu_decrypt_amiibo(encrypted, elen, decrypted, &dlen);
3994 if ( res == PM3_SUCCESS) {
3996 for (uint8_t i = 0; i < dlen/16; i++ ) {
3997 PrintAndLogEx(INFO, "[%d] %s", i, sprint_hex_ascii(decrypted + (i * 16), 16));
4006 //------------------------------------
4008 //------------------------------------
4009 static command_t CommandTable
[] = {
4010 {"help", CmdHelp
, AlwaysAvailable
, "This help"},
4011 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("recovery") " -------------------------"},
4012 {"keygen", CmdHF14AMfUGenDiverseKeys
, AlwaysAvailable
, "Generate 3DES MIFARE diversified keys"},
4013 {"pwdgen", CmdHF14AMfUPwdGen
, AlwaysAvailable
, "Generate pwd from known algos"},
4014 {"otptear", CmdHF14AMfuOtpTearoff
, IfPm3Iso14443a
, "Tear-off test on OTP bits"},
4015 // {"tear_cnt", CmdHF14AMfuEv1CounterTearoff, IfPm3Iso14443a, "Tear-off test on Ev1/NTAG Counter bits"},
4016 {"-----------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("operations") " -----------------------"},
4017 {"cauth", CmdHF14AMfUCAuth
, IfPm3Iso14443a
, "Authentication - Ultralight-C"},
4018 {"dump", CmdHF14AMfUDump
, IfPm3Iso14443a
, "Dump MIFARE Ultralight family tag to binary file"},
4019 {"info", CmdHF14AMfUInfo
, IfPm3Iso14443a
, "Tag information"},
4020 {"ndefread", CmdHF14MfuNDEFRead
, IfPm3Iso14443a
, "Prints NDEF records from card"},
4021 {"rdbl", CmdHF14AMfURdBl
, IfPm3Iso14443a
, "Read block"},
4022 {"restore", CmdHF14AMfURestore
, IfPm3Iso14443a
, "Restore a dump onto a MFU MAGIC tag"},
4023 {"wrbl", CmdHF14AMfUWrBl
, IfPm3Iso14443a
, "Write block"},
4024 {"---------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("simulation") " -----------------------"},
4025 {"eload", CmdHF14AMfUeLoad
, IfPm3Iso14443a
, "load Ultralight .eml dump file into emulator memory"},
4026 {"eview", CmdHF14AMfuEView
, IfPm3Iso14443a
, "View emulator memory"},
4027 {"sim", CmdHF14AMfUSim
, IfPm3Iso14443a
, "Simulate MIFARE Ultralight from emulator memory"},
4028 {"---------", CmdHelp
, IfPm3Iso14443a
, "----------------------- " _CYAN_("magic") " ----------------------------"},
4029 {"setpwd", CmdHF14AMfUCSetPwd
, IfPm3Iso14443a
, "Set 3DES key - Ultralight-C"},
4030 {"setuid", CmdHF14AMfUCSetUid
, IfPm3Iso14443a
, "Set UID - MAGIC tags only"},
4031 // {"---------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("amiibo") " ----------------------------"},
4032 // {"decrypt", CmdHF14AMfUCDecryptAmiibo, IfPm3Iso14443a, "Decrypt a amiibo tag"},
4033 {NULL
, NULL
, NULL
, NULL
}
4036 static int CmdHelp(const char *Cmd
) {
4037 (void)Cmd
; // Cmd is not used so far
4038 CmdsHelp(CommandTable
);
4042 int CmdHFMFUltra(const char *Cmd
) {
4043 clearCommandBuffer();
4044 return CmdsParse(CommandTable
, Cmd
);