textual
[RRG-proxmark3.git] / client / src / cmdhfmfu.c
blob146fd0121fd0c235d9d6489ce3e0388732d09f71
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
6 // the license.
7 //-----------------------------------------------------------------------------
8 // High frequency MIFARE ULTRALIGHT (C) commands
9 //-----------------------------------------------------------------------------
10 #include "cmdhfmfu.h"
11 #include <ctype.h>
12 #include "cmdparser.h"
13 #include "commonutil.h"
14 #include "crypto/libpcrypto.h"
15 #include "des.h"
16 #include "aes.h"
17 #include "cmdhfmf.h"
18 #include "cmdhf14a.h"
19 #include "comms.h"
20 #include "fileutils.h"
21 #include "protocols.h"
22 #include "generator.h"
23 #include "nfc/ndef.h"
24 #include "cliparser.h"
25 #include "cmdmain.h"
26 #include "amiibo.h" // amiiboo fcts
27 #include "base64.h"
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,
67 NTAG_213_C, NTAG_210u
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) {
82 static char buf[20];
83 char *retStr = buf;
85 switch (id) {
86 case 3:
87 sprintf(retStr, "%02X, Ultralight", id);
88 break;
89 case 4:
90 sprintf(retStr, "%02X, NTAG", id);
91 break;
92 default:
93 sprintf(retStr, "%02X, unknown", id);
94 break;
96 return buf;
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) {
106 static char buf[40];
107 char *retStr = buf;
108 memset(buf, 0, sizeof(buf));
110 uint16_t usize = 1 << ((fsize >> 1) + 1);
111 uint16_t lsize = 1 << (fsize >> 1);
113 // is LSB set?
114 if (fsize & 1)
115 sprintf(retStr, "%02X, (%u <-> %u bytes)", fsize, usize, lsize);
116 else
117 sprintf(retStr, "%02X, (%u bytes)", fsize, lsize);
118 return buf;
121 int ul_read_uid(uint8_t *uid) {
122 if (uid == NULL) {
123 PrintAndLogEx(WARNING, "NUll parameter UID");
124 return PM3_ESOFT;
126 // read uid from tag
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];
135 // 0: couldn't read
136 // 1: OK with ATS
137 // 2: OK, no ATS
138 // 3: proprietary Anticollision
139 if (select_status == 0) {
140 PrintAndLogEx(WARNING, "iso14443a card select failed");
141 return PM3_ESOFT;
143 if (card.uidlen != 7) {
144 PrintAndLogEx(WARNING, "Wrong sized UID, expected 7bytes got %d", card.uidlen);
145 return PM3_ESOFT;
147 memcpy(uid, card.uid, 7);
148 return PM3_SUCCESS;
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);
165 return 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.");
175 DropField();
176 return false;
177 } else {
179 uint16_t len = (resp.oldarg[1] & 0xFFFF);
180 if (len == 0) {
181 PrintAndLogEx(WARNING, "iso14443a card select failed");
182 DropField();
183 return false;
186 if (card)
187 memcpy(card, resp.data.asBytes, sizeof(iso14a_card_select_t));
189 return true;
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);
197 return len;
200 static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) {
202 if (data == NULL)
203 return -1;
205 uint8_t cmd[18];
206 memset(cmd, 0x00, sizeof(cmd));
207 datalen = (datalen > 16) ? 16 : datalen;
209 cmd[0] = ISO14443A_CMD_WRITEBLOCK;
210 cmd[1] = page;
211 memcpy(cmd + 2, data, datalen);
213 uint8_t response[1] = {0xFF};
214 ul_send_cmd_raw(cmd, 2 + datalen, response, sizeof(response));
215 // ACK
216 if (response[0] == 0x0a) return 0;
217 // NACK
218 return -1;
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);
225 return len;
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;
236 return 0;
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)) {
244 *correct_key = key;
245 return PM3_SUCCESS;
248 return PM3_ESOFT;
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.
256 // ACK == 0xA
257 if (len == 1 && pack[0] <= 0x09)
258 return -1;
259 return len;
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");
267 return PM3_ESOFT;
269 } else {
270 if (!ul_select(card)) return PM3_ESOFT;
272 if (hasAuthKey) {
273 if (ulev1_requestAuthentication(authkey, pack, packSize) == -1) {
274 DropField();
275 PrintAndLogEx(WARNING, "Authentication Failed UL-EV1/NTAG");
276 return PM3_ESOFT;
280 return PM3_SUCCESS;
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);
286 return len;
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);
293 return len;
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);
300 return len;
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);
307 return len;
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:
313 // send a0 + crc
314 // UL responds with 00, fudan doesn't respond
315 // or
316 // send a200 + crc
317 // UL doesn't respond, fudan responds with 00
318 // or
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))
326 return UL_ERROR;
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) {
340 uint8_t uid[7];
341 uid[0] = data[0];
342 uid[1] = data[1];
343 uid[2] = data[2];
344 uid[3] = data[4];
345 uid[4] = data[5];
346 uid[5] = data[6];
347 uid[6] = data[7];
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
357 switch (chip) {
358 case 0xC2:
359 PrintAndLogEx(SUCCESS, " IC type: SLE 66R04P 770 Bytes");
360 break; //77 pages
361 case 0xC4:
362 PrintAndLogEx(SUCCESS, " IC type: SLE 66R16P 2560 Bytes");
363 break; //256 pages
364 case 0xC6:
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];
372 if (data[3] == crc0)
373 PrintAndLogEx(SUCCESS, " BCC0: %02X (" _GREEN_("ok") ")", data[3]);
374 else
375 PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0);
377 int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6];
378 if (data[8] == crc1)
379 PrintAndLogEx(SUCCESS, " BCC1: %02X (" _GREEN_("ok") ")", data[8]);
380 else
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"));
383 } else {
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)
397 return PM3_SUCCESS;
400 static int ndef_get_maxsize(uint8_t *data) {
401 // no NDEF message
402 if (data[0] != 0xE1)
403 return 0;
405 if (data[2] == 0x06)
406 return 48;
407 else if (data[2] == 0x12)
408 return 144;
409 else if (data[2] == 0x3E)
410 return 496;
411 else if (data[2] == 0x6D)
412 return 872;
413 return 0;
416 static int ndef_print_CC(uint8_t *data) {
417 // no NDEF message
418 if (data[0] != 0xE1)
419 return PM3_ESOFT;
421 //NFC Forum Type 1,2,3,4
423 // 4 has 1.1 (11)
425 // b7, b6 major version
426 // b5, b4 minor version
427 // b3, b2 read
428 // 00 always, 01 rfu, 10 proprietary, 11 rfu
429 // b1, b0 write
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;
436 char wStr[50];
437 memset(wStr, 0, sizeof(wStr));
438 switch (cc_write) {
439 case 0:
440 sprintf(wStr, "Write access granted without any security");
441 break;
442 case 1:
443 sprintf(wStr, "RFU");
444 break;
445 case 2:
446 sprintf(wStr, "Proprietary");
447 break;
448 case 3:
449 sprintf(wStr, "No write access");
450 break;
452 char rStr[46];
453 memset(rStr, 0, sizeof(rStr));
454 switch (cc_read) {
455 case 0:
456 sprintf(rStr, "Read access granted without any security");
457 break;
458 case 1:
459 case 3:
460 sprintf(rStr, "RFU");
461 break;
462 case 2:
463 sprintf(rStr, "Proprietary");
464 break;
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);
478 if (data[2] == 0x06)
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");
501 return PM3_SUCCESS;
504 int ul_print_type(uint32_t tagtype, uint8_t spaces) {
506 if (spaces > 10)
507 spaces = 10;
509 char typestr[100];
510 memset(typestr, 0x00, sizeof(typestr));
512 if (tagtype & UL)
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, "");
568 else
569 snprintf(typestr, sizeof(typestr), "%*sTYPE: " _YELLOW_("Unknown %06x"), spaces, "", tagtype);
571 bool ismagic = ((tagtype & MAGIC) == MAGIC);
572 if (ismagic)
573 snprintf(typestr + strlen(typestr), 4, " (");
575 snprintf(typestr + strlen(typestr), sizeof(typestr) - strlen(typestr), " %s ", (tagtype & MAGIC) ? _GREEN_("magic") : "");
576 tagtype &= ~(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") : "");
580 if (ismagic)
581 snprintf(typestr + strlen(typestr), 4, " )");
583 PrintAndLogEx(SUCCESS, "%s", typestr);
584 return PM3_SUCCESS;
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));
593 return PM3_SUCCESS;
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);
603 if (validAuth)
604 PrintAndLogEx(NORMAL, " Auth0 [42/0x2A]: %s page %d/0x%02X and above need authentication", sprint_hex(data + 8, 4), data[8], data[8]);
605 else {
606 if (data[8] == 0) {
607 PrintAndLogEx(NORMAL, " Auth0 [42/0x2A]: %s default", sprint_hex(data + 8, 4));
608 } else {
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"
616 return PM3_SUCCESS;
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) {
644 case 0:
645 PrintAndLogEx(INFO, " - no ASCII mirror");
646 break;
647 case 1:
648 PrintAndLogEx(INFO, " - UID ASCII mirror");
649 break;
650 case 2:
651 PrintAndLogEx(INFO, " - NFC counter ASCII mirror");
652 break;
653 case 3:
654 PrintAndLogEx(INFO, " - UID and NFC counter ASCII mirror");
655 break;
656 default:
657 break;
660 PrintAndLogEx(INFO, " - SLEEP mode %s", (sleep_en) ? "enabled" : "disabled");
662 switch (fdp_conf) {
663 case 0:
664 PrintAndLogEx(INFO, " - no field detect");
665 break;
666 case 1:
667 PrintAndLogEx(INFO, " - enabled by first State-of-Frame (start of communication)");
668 break;
669 case 2:
670 PrintAndLogEx(INFO, " - enabled by selection of the tag");
671 break;
672 case 3:
673 PrintAndLogEx(INFO, " - enabled by field presence");
674 break;
675 default:
676 break;
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) {
681 case 1:
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;}
683 case 2:
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;}
685 case 3:
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;}
687 default:
688 break;
690 } else if (tagtype & NTAG_216_F) {
691 switch (mirror_conf) {
692 case 1:
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;}
694 case 2:
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;}
696 case 3:
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;}
698 default:
699 break;
703 PrintAndLogEx(INFO, " - strong modulation mode %s", (strg_mod_en) ? "enabled" : "disabled");
705 if (data[3] < 0xff)
706 PrintAndLogEx(INFO, " - page %d and above need authentication", data[3]);
707 else
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));
711 if (authlim == 0)
712 PrintAndLogEx(INFO, " - " _GREEN_("Unlimited password attempts"));
713 else
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));
725 return PM3_SUCCESS;
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};
733 int len = 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));
737 if (len == 3) {
738 PrintAndLogEx(INFO, " [%0d]: %s", i, sprint_hex(counter, 3));
739 PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
740 , tear[0]
741 , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
745 return len;
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
773 // UL EV1
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
810 uint8_t i;
811 bool is_valid = false;
812 for (i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) {
814 int dl = 0;
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);
821 if (is_valid)
822 break;
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") " )");
831 return PM3_ESOFT;
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") " )");
839 return PM3_SUCCESS;
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" : "");
853 return PM3_SUCCESS;
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};
862 uint16_t len;
863 len = ulev1_readTearing(0x02, tear, sizeof(tear));
864 (void)len;
865 len = ulev1_readCounter(0x02, counter, sizeof(counter));
866 (void)len;
867 PrintAndLogEx(INFO, " [02]: %s", sprint_hex(counter, 3));
868 PrintAndLogEx(SUCCESS, " - %02X tearing ( %s )"
869 , tear[0]
870 , (tear[0] == 0xBD) ? _GREEN_("ok") : _RED_("fail")
872 return len;
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) ){
888 return UL_ERROR;
890 int status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
891 if ( status > 0 ) {
892 status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
893 returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C;
894 } else {
895 returnValue = UL;
897 DropField();
898 return returnValue;
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)
908 return UL_ERROR;
910 int status = ul_comp_write(0, NULL, 0);
911 DropField();
912 if (status == 0)
913 return MAGIC;
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) {
926 case MAGIC_GEN_1A:
927 return MAGIC_1A;
928 case MAGIC_GEN_1B:
929 return MAGIC_1B;
930 case MAGIC_NTAG21X:
931 return MAGIC_NTAG;
932 default:
933 break;
935 return 0;
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.");
942 return NULL;
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);
948 return fptr;
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));
957 return PM3_ESOFT;
960 nfc3d_amiibo_keys amiibo_keys = {0};
961 if (nfc3d_amiibo_load_keys(&amiibo_keys) == false) {
962 return PM3_ESOFT;
965 if (nfc3d_amiibo_unpack(&amiibo_keys, encrypted, decrypted) == false) {
966 PrintAndLogEx(ERR, "WARNING, Tag signature was NOT valid");
969 *dlen = NFC3D_AMIIBO_SIZE;
970 return PM3_SUCCESS;
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");
980 res = PM3_EMALLOC;
981 goto out;
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");
989 free(*pdata);
990 res = PM3_ETIMEOUT;
991 goto out;
994 if (resp.oldarg[0] != 1) {
995 PrintAndLogEx(WARNING, "Failed reading card");
996 free(*pdata);
997 res = PM3_ESOFT;
998 goto out;
1001 // read all memory
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");
1011 free(*pdata);
1012 res = PM3_ETIMEOUT;
1013 goto out;
1016 if (len)
1017 *len = buffer_size;
1019 out:
1020 return res;
1024 Lego Dimensions,
1025 Version: 00 04 04 02 01 00 0F 03
1027 matching bytes:
1028 index 12 ( 3 * 4 )
1029 E1 10 12 00 01 03 A0 0C 34 03 13 D1 01 0F 54 02 65 6E
1032 typedef struct {
1033 const char *desc;
1034 const char *version;
1035 uint8_t mpos;
1036 uint8_t mlen;
1037 const char *match;
1038 uint32_t (*Pwd)(uint8_t *uid);
1039 uint16_t (*Pack)(uint8_t *uid);
1040 const char *hint;
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",
1058 9, 9, "E110120F",
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",
1071 NULL, NULL,
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) {
1084 uint8_t i = 0;
1085 do {
1087 int vl = 0;
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);
1092 if (m1 == false) {
1093 PrintAndLogEx(DEBUG, "(fingerprint) wrong version");
1094 continue;
1097 int ml = 0;
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);
1102 if (m2) {
1103 PrintAndLogEx(DEBUG, "(fingerprint) found %s", mfu_ident_table[i].desc);
1104 return &mfu_ident_table[i];
1106 } while (mfu_ident_table[++i].desc);
1107 return NULL;
1110 static uint8_t mfu_max_len(void) {
1111 uint8_t n = 0, i = 0;
1112 do {
1113 uint8_t tmp = mfu_ident_table[i].mpos + mfu_ident_table[i].mlen;
1114 if (tmp > n) {
1115 n = tmp;
1117 } while (mfu_ident_table[++i].desc);
1118 return n;
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)
1124 return PM3_ESOFT;
1126 uint8_t v[10] = {0x00};
1127 int len = ulev1_getVersion(v, sizeof(v));
1128 DropField();
1129 if (len != sizeof(v))
1130 return PM3_ESOFT;
1132 memcpy(version, v, 8);
1133 memcpy(uid, card.uid, 7);
1134 return PM3_SUCCESS;
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");
1145 res = PM3_ESOFT;
1146 goto out;
1149 maxbytes = ((maxbytes / 4) + 1) * 4;
1150 data = calloc(maxbytes, sizeof(uint8_t));
1151 if (data == NULL) {
1152 PrintAndLogEx(ERR, "failed to allocate memory");
1153 res = PM3_EMALLOC;
1154 goto out;
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");
1165 res = PM3_ETIMEOUT;
1166 goto out;
1169 if (resp.oldarg[0] != 1) {
1170 PrintAndLogEx(WARNING, "Failed reading card");
1171 res = PM3_ESOFT;
1172 goto out;
1175 // read all memory
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");
1185 res = PM3_ETIMEOUT;
1186 goto 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);
1193 if (item) {
1194 PrintAndLogEx(SUCCESS, "Found " _GREEN_("%s"), item->desc);
1196 if (item->Pwd) {
1197 char s[40] = {0};
1198 sprintf(s, item->hint, item->Pwd(uid));
1199 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", s);
1200 } else {
1201 PrintAndLogEx(HINT, "Use `" _YELLOW_("%s") "`", item->hint);
1206 out:
1207 free(data);
1208 PrintAndLogEx(INFO, "------------------------------------------------------------");
1209 return res;
1212 uint32_t GetHF14AMfU_Type(void) {
1214 TagTypeUL_t tagtype = UNKNOWN;
1215 iso14a_card_select_t card;
1217 if (ul_select(&card) == false)
1218 return UL_ERROR;
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);
1223 DropField();
1224 return UL_ERROR;
1227 if (card.uid[0] != 0x05) {
1229 uint8_t version[10] = {0x00};
1230 int len = ulev1_getVersion(version, sizeof(version));
1231 DropField();
1233 switch (len) {
1234 case 0x0A: {
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; }
1296 break;
1298 case 0x01:
1299 tagtype = UL_C;
1300 break;
1301 case 0x00:
1302 tagtype = UL;
1303 break;
1304 case -1 :
1305 tagtype = (UL | UL_C | NTAG_203);
1306 break; // could be UL | UL_C magic tags
1307 default :
1308 tagtype = UNKNOWN;
1309 break;
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));
1319 DropField();
1320 if (status > 1) {
1321 tagtype = UL_C;
1322 } else {
1323 // need to re-select after authentication error
1324 if (ul_select(&card) == false)
1325 return UL_ERROR;
1327 uint8_t data[16] = {0x00};
1328 // read page 0x26-0x29 (last valid ntag203 page)
1329 status = ul_read(0x26, data, sizeof(data));
1330 if (status <= 1) {
1331 tagtype = UL;
1332 } else {
1333 // read page 0x30 (should error if it is a ntag203)
1334 status = ul_read(0x30, data, sizeof(data));
1335 if (status <= 1) {
1336 tagtype = NTAG_203;
1337 } else {
1338 tagtype = UNKNOWN;
1341 DropField();
1344 if (tagtype & UL) {
1345 tagtype = ul_fudan_check();
1346 DropField();
1348 } else {
1349 DropField();
1350 // Infinition MY-D tests Exam high nibble
1351 uint8_t nib = (card.uid[1] & 0xf0) >> 4;
1352 switch (nib) {
1353 // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k
1354 case 1:
1355 tagtype = MY_D;
1356 break; // or SLE 66RxxS ... up to 512 pages of 8 user bytes...
1357 case 2:
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)
1360 case 3:
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
1363 case 7:
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);
1373 return tagtype;
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",
1384 "hf mfu info\n"
1385 "hf mfu info -k AABBCCDD\n"
1386 "hf mfu info --key 00112233445566778899AABBCCDDEEFF"
1389 void *argtable[] = {
1390 arg_param_begin,
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"),
1393 arg_param_end
1395 CLIExecWithReturn(ctx, Cmd, argtable, true);
1397 int ak_len = 0;
1398 uint8_t authenticationkey[16] = {0x00};
1399 CLIGetHexWithReturn(ctx, 1, authenticationkey, &ak_len);
1400 bool swap_endian = arg_get_lit(ctx, 2);
1401 CLIParserFree(ctx);
1403 if (ak_len) {
1404 if (ak_len != 16 && ak_len != 4) {
1405 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
1406 return PM3_EINVARG;
1410 bool has_auth_key = false;
1411 if (ak_len > 0)
1412 has_auth_key = true;
1414 uint8_t authlim = 0xff;
1415 uint8_t data[16] = {0x00};
1416 iso14a_card_select_t card;
1417 int status;
1418 uint8_t *authkeyptr = authenticationkey;
1419 uint8_t pwd[4] = {0, 0, 0, 0};
1420 uint8_t *key = pwd;
1421 uint8_t pack[4] = {0, 0, 0, 0};
1422 int len;
1424 TagTypeUL_t tagtype = GetHF14AMfU_Type();
1425 if (tagtype == UL_ERROR)
1426 return PM3_ESOFT;
1428 PrintAndLogEx(NORMAL, "");
1429 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " --------------------------");
1430 PrintAndLogEx(INFO, "-------------------------------------------------------------");
1431 ul_print_type(tagtype, 6);
1433 // Swap endianness
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) {
1439 return PM3_ESOFT;
1442 bool locked = false;
1443 // read pages 0,1,2,3 (should read 4pages)
1444 status = ul_read(0, data, sizeof(data));
1445 if (status == -1) {
1446 DropField();
1447 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
1448 return PM3_ESOFT;
1449 } else if (status == 16) {
1450 ul_print_default(data, card.uid);
1451 ndef_print_CC(data + 12);
1452 } else {
1453 locked = true;
1456 // UL_C Specific
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));
1462 if (status == -1) {
1463 PrintAndLogEx(ERR, "Error: tag didn't answer to READ UL-C");
1464 DropField();
1465 return PM3_ESOFT;
1467 if (status == 16)
1468 ulc_print_configuration(ulc_conf);
1469 else
1470 locked = true;
1472 if ((tagtype & MAGIC)) {
1473 //just read key
1474 uint8_t ulc_deskey[16] = {0x00};
1475 status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
1476 if (status == -1) {
1477 DropField();
1478 PrintAndLogEx(ERR, "Error: tag didn't answer to READ magic");
1479 return PM3_ESOFT;
1481 if (status == 16) {
1482 ulc_print_3deskey(ulc_deskey);
1485 } else {
1486 DropField();
1487 // if we called info with key, just return
1488 if (has_auth_key) {
1489 return PM3_SUCCESS;
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);
1499 return PM3_SUCCESS;
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) {
1510 return PM3_ESOFT;
1515 // NTAG counters?
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) {
1520 return PM3_ESOFT;
1525 // Read signature
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));
1529 if (status == -1) {
1530 PrintAndLogEx(ERR, "Error: tag didn't answer to READ SIGNATURE");
1531 DropField();
1532 return PM3_ESOFT;
1534 if (status == 32) {
1535 ulev1_print_signature(tagtype, card.uid, ulev1_signature, sizeof(ulev1_signature));
1536 } else {
1537 // re-select
1538 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1539 return PM3_ESOFT;
1543 // Get Version
1544 uint8_t version[10] = {0x00};
1545 status = ulev1_getVersion(version, sizeof(version));
1546 if (status == -1) {
1547 PrintAndLogEx(ERR, "Error: tag didn't answer to GETVERSION");
1548 DropField();
1549 return PM3_ESOFT;
1550 } else if (status == 10) {
1551 ulev1_print_version(version);
1552 } else {
1553 locked = true;
1554 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1555 return 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;
1566 break;
1570 if (startconfigblock) { // if we know where the config block is...
1571 status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
1572 if (status == -1) {
1573 PrintAndLogEx(ERR, "Error: tag didn't answer to READ EV1");
1574 DropField();
1575 return PM3_ESOFT;
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
1580 if (has_auth_key) {
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)
1589 // 0 = limitless.
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"));
1595 // test pwd gen A
1596 num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key);
1597 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
1598 if (len > -1) {
1599 PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
1600 goto out;
1603 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1604 return PM3_ESOFT;
1607 // test pwd gen B
1608 num_to_bytes(ul_ev1_pwdgenB(card.uid), 4, key);
1609 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
1610 if (len > -1) {
1611 PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
1612 goto out;
1615 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1616 return PM3_ESOFT;
1619 // test pwd gen C
1620 num_to_bytes(ul_ev1_pwdgenC(card.uid), 4, key);
1621 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
1622 if (len > -1) {
1623 PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
1624 goto out;
1627 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1628 return PM3_ESOFT;
1631 // test pwd gen D
1632 num_to_bytes(ul_ev1_pwdgenD(card.uid), 4, key);
1633 len = ulev1_requestAuthentication(key, pack, sizeof(pack));
1634 if (len > -1) {
1635 PrintAndLogEx(SUCCESS, "Found default password" _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
1636 goto out;
1639 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1640 return 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));
1646 if (len > -1) {
1647 PrintAndLogEx(SUCCESS, "Found default password " _GREEN_("%s") " pack %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
1648 break;
1649 } else {
1650 if (ul_auth_select(&card, tagtype, has_auth_key, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) {
1651 return PM3_ESOFT;
1655 if (len < 1) {
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");
1659 } else {
1660 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu pwdgen -r`") " to get see known pwd gen algo suggestions");
1664 mfu_fingerprint();
1666 out:
1667 DropField();
1668 if (locked) {
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, "");
1673 return PM3_SUCCESS;
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[] = {
1690 arg_param_begin,
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)"),
1695 arg_param_end
1697 CLIExecWithReturn(ctx, Cmd, argtable, false);
1699 int ak_len = 0;
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);
1706 int datalen = 0;
1707 uint8_t data[16] = {0x00};
1708 CLIGetHexWithReturn(ctx, 4, data, &datalen);
1709 CLIParserFree(ctx);
1711 bool has_auth_key = false;
1712 bool has_pwd = false;
1713 if (ak_len == 16) {
1714 has_auth_key = true;
1715 } else if (ak_len == 4) {
1716 has_pwd = true;
1717 } else if (ak_len != 0) {
1718 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
1719 return PM3_EINVARG;
1722 if (blockno < 0) {
1723 PrintAndLogEx(WARNING, "Wrong block number");
1724 return PM3_EINVARG;
1727 if (datalen != 16 && datalen != 4) {
1728 PrintAndLogEx(WARNING, "Wrong data length. Expect 16 or 4, got %d", datalen);
1729 return PM3_EINVARG;
1732 uint8_t *authKeyPtr = authenticationkey;
1734 // starting with getting tagtype
1735 TagTypeUL_t tagtype = GetHF14AMfU_Type();
1736 if (tagtype == UL_ERROR)
1737 return PM3_ESOFT;
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];
1743 break;
1746 if (blockno > maxblockno) {
1747 PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
1748 return PM3_EINVARG;
1751 // Swap endianness
1752 if (swap_endian) {
1753 if (has_auth_key)
1754 authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
1756 if (has_pwd)
1757 authKeyPtr = SwapEndian64(authenticationkey, 4, 4);
1760 if (blockno <= 3)
1761 PrintAndLogEx(INFO, "Special block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen));
1762 else
1763 PrintAndLogEx(INFO, "Block: %0d (0x%02X) [ %s]", blockno, blockno, sprint_hex(data, datalen));
1765 if (ak_len) {
1766 PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
1769 //Send write Block
1771 // 4 or 16.
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;
1780 if (has_auth_key) {
1781 keytype = 1;
1782 memcpy(cmddata + datalen, authKeyPtr, 16);
1783 cmdlen += 16;
1784 } else if (has_pwd) {
1785 keytype = 2;
1786 memcpy(cmddata + datalen, authKeyPtr, 4);
1787 cmdlen += 4;
1790 clearCommandBuffer();
1791 if (datalen == 16) {
1792 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL_COMPAT, blockno, keytype, 0, cmddata, cmdlen);
1793 } else {
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);
1800 } else {
1801 PrintAndLogEx(WARNING, "Command execute timeout");
1804 return PM3_SUCCESS;
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[] = {
1820 arg_param_begin,
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"),
1824 arg_param_end
1826 CLIExecWithReturn(ctx, Cmd, argtable, false);
1828 int ak_len = 0;
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);
1833 CLIParserFree(ctx);
1835 bool has_auth_key = false;
1836 bool has_pwd = false;
1837 if (ak_len == 16) {
1838 has_auth_key = true;
1839 } else if (ak_len == 4) {
1840 has_pwd = true;
1841 } else if (ak_len != 0) {
1842 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
1843 return PM3_EINVARG;
1846 if (blockno < 0) {
1847 PrintAndLogEx(WARNING, "Wrong block number");
1848 return PM3_EINVARG;
1851 uint8_t *authKeyPtr = authenticationkey;
1853 // start with getting tagtype
1854 TagTypeUL_t tagtype = GetHF14AMfU_Type();
1855 if (tagtype == UL_ERROR)
1856 return PM3_ESOFT;
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];
1862 break;
1865 if (blockno > maxblockno) {
1866 PrintAndLogEx(WARNING, "block number to large. Max block is %u/0x%02X \n", maxblockno, maxblockno);
1867 return PM3_EINVARG;
1870 // Swap endianness
1871 if (swap_endian) {
1872 if (has_auth_key)
1873 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
1875 if (has_pwd)
1876 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
1879 if (ak_len) {
1880 PrintAndLogEx(INFO, "Using %s " _GREEN_("%s"), (ak_len == 16) ? "3des" : "pwd", sprint_hex(authenticationkey, ak_len));
1883 //Read Block
1884 uint8_t keytype = 0;
1885 uint8_t datalen = 0;
1886 if (has_auth_key) {
1887 keytype = 1;
1888 datalen = 16;
1889 } else if (has_pwd) {
1890 keytype = 2;
1891 datalen = 4;
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;
1899 if (isOK) {
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));
1905 } else {
1906 PrintAndLogEx(WARNING, "Failed reading block: ( %02x )", isOK);
1908 } else {
1909 PrintAndLogEx(WARNING, "Command execute time-out");
1911 return PM3_SUCCESS;
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, "---------+-------------+---+------");
1933 uint8_t j = 0;
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
1950 if (pages == 44) {
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) {
1961 if (i < 3) {
1962 PrintAndLogEx(INFO, "%3d/0x%02X | %s| | %s", i + startpage, i + startpage, sprint_hex(data + i * 4, 4), sprint_ascii(data + i * 4, 4));
1963 continue;
1965 switch (i) {
1966 case 3:
1967 lckbit = bit_stat[4];
1968 break;
1969 case 4:
1970 lckbit = bit_stat[3];
1971 break;
1972 case 5:
1973 lckbit = bit_stat[2];
1974 break;
1975 case 6:
1976 lckbit = bit_stat[1];
1977 break;
1978 case 7:
1979 lckbit = bit_stat[0];
1980 break;
1981 case 8:
1982 lckbit = bit_stat[15];
1983 break;
1984 case 9:
1985 lckbit = bit_stat[14];
1986 break;
1987 case 10:
1988 lckbit = bit_stat[13];
1989 break;
1990 case 11:
1991 lckbit = bit_stat[12];
1992 break;
1993 case 12:
1994 lckbit = bit_stat[11];
1995 break;
1996 case 13:
1997 lckbit = bit_stat[10];
1998 break;
1999 case 14:
2000 lckbit = bit_stat[9];
2001 break;
2002 case 15:
2003 lckbit = bit_stat[8];
2004 break;
2005 case 16:
2006 case 17:
2007 case 18:
2008 case 19:
2009 lckbit = bit_dyn[6];
2010 break;
2011 case 20:
2012 case 21:
2013 case 22:
2014 case 23:
2015 lckbit = bit_dyn[5];
2016 break;
2017 case 24:
2018 case 25:
2019 case 26:
2020 case 27:
2021 lckbit = bit_dyn[4];
2022 break;
2023 case 28:
2024 case 29:
2025 case 30:
2026 case 31:
2027 lckbit = bit_dyn[2];
2028 break;
2029 case 32:
2030 case 33:
2031 case 34:
2032 case 35:
2033 lckbit = bit_dyn[1];
2034 break;
2035 case 36:
2036 case 37:
2037 case 38:
2038 case 39:
2039 lckbit = bit_dyn[0];
2040 break;
2041 case 40:
2042 lckbit = bit_dyn[12];
2043 break;
2044 case 41:
2045 lckbit = bit_dyn[11];
2046 break;
2047 case 42:
2048 lckbit = bit_dyn[10];
2049 break; //auth0
2050 case 43:
2051 lckbit = bit_dyn[9];
2052 break; //auth1
2053 default:
2054 break;
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[] = {
2080 arg_param_begin,
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"),
2086 arg_param_end
2088 CLIExecWithReturn(ctx, Cmd, argtable, true);
2090 int fnlen = 0;
2091 char filename[FILE_PATH_SIZE] = {0};
2092 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2094 int ak_len = 0;
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);
2101 CLIParserFree(ctx);
2103 bool has_auth_key = false;
2104 bool has_pwd = false;
2105 if (ak_len == 16) {
2106 has_auth_key = true;
2107 } else if (ak_len == 4) {
2108 has_pwd = true;
2109 } else if (ak_len != 0) {
2110 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2111 return PM3_EINVARG;
2114 bool manual_pages = false;
2115 if (start_page > 0)
2116 manual_pages = true;
2118 if (pages != 16)
2119 manual_pages = true;
2121 uint8_t card_mem_size = 0;
2123 // Swap endianness
2124 if (swap_endian) {
2125 if (has_auth_key)
2126 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 8);
2128 if (has_pwd)
2129 authKeyPtr = SwapEndian64(authenticationkey, ak_len, 4);
2132 TagTypeUL_t tagtype = GetHF14AMfU_Type();
2133 if (tagtype == UL_ERROR)
2134 return PM3_ESOFT;
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;
2142 break;
2146 ul_print_type(tagtype, 0);
2147 PrintAndLogEx(SUCCESS, "Reading tag memory...");
2148 uint8_t keytype = 0;
2149 if (has_auth_key) {
2150 if (tagtype & UL_C)
2151 keytype = 1; //UL_C auth
2152 else
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");
2167 return PM3_ESOFT;
2170 // read all memory
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) {
2204 //reset pack
2205 get_pack[0] = 0;
2206 get_pack[1] = 0;
2208 DropField();
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));
2217 if (has_auth_key) {
2218 uint8_t dummy_pack[] = {0, 0};
2219 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
2220 } else {
2221 ul_select(&card);
2224 ulev1_getVersion(get_version, sizeof(get_version));
2226 // ULEV-1 has 3 counters
2227 uint8_t n = 0;
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))) {
2231 n = 2;
2234 // NTAG can have nfc counter pwd protection enabled
2235 for (; n < 3; n++) {
2237 if (has_auth_key) {
2238 uint8_t dummy_pack[] = {0, 0};
2239 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
2240 } else {
2241 ul_select(&card);
2243 ulev1_readCounter(n, &get_counter_tearing[n][0], 3);
2245 if (has_auth_key) {
2246 uint8_t dummy_pack[] = {0, 0};
2247 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
2248 } else {
2249 ul_select(&card);
2251 ulev1_readTearing(n, &get_counter_tearing[n][3], 1);
2254 DropField();
2256 if (has_auth_key) {
2257 uint8_t dummy_pack[] = {0, 0};
2258 ul_auth_select(&card, tagtype, has_auth_key, authKeyPtr, dummy_pack, sizeof(dummy_pack));
2259 } else
2260 ul_select(&card);
2262 ulev1_readSignature(get_signature, sizeof(get_signature));
2263 DropField();
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);
2274 } else {
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?
2297 if (fnlen < 1) {
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);
2310 if (is_partial)
2311 PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size);
2313 return PM3_SUCCESS;
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;
2320 if (!isOK)
2321 PrintAndLogEx(WARNING, "failed to write block %d", b);
2322 } else {
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[] = {
2340 arg_param_begin,
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"),
2348 arg_param_end
2350 CLIExecWithReturn(ctx, Cmd, argtable, false);
2352 int fnlen = 0;
2353 char filename[FILE_PATH_SIZE] = {0};
2354 CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
2356 int ak_len = 0;
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);
2366 CLIParserFree(ctx);
2369 bool has_key = false;
2370 if (ak_len > 0) {
2371 if (ak_len != 4 && ak_len != 16) {
2372 PrintAndLogEx(ERR, "Wrong key length. expected 4 or 16, got %d", ak_len);
2373 return PM3_EINVARG;
2374 } else {
2375 has_key = true;
2379 uint8_t *dump = NULL;
2380 size_t bytes_read = 0;
2382 if (fnlen == 0) {
2383 char *fptr = GenerateFilename("hf-mfu-", "-dump.bin");
2384 if (fptr != NULL) {
2385 strcpy(filename, fptr);
2386 } else {
2387 snprintf(filename, sizeof(filename), "dumpdata.bin");
2389 free(fptr);
2392 if (loadFile_safe(filename, "", (void **)&dump, &bytes_read) != PM3_SUCCESS) {
2393 PrintAndLogEx(WARNING, "Could not find file " _YELLOW_("%s"), filename);
2394 return PM3_EIO;
2397 if (bytes_read < MFU_DUMP_PREFIX_LENGTH) {
2398 PrintAndLogEx(ERR, "Error, dump file is too small");
2399 free(dump);
2400 return PM3_ESOFT;
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");
2406 free(dump);
2407 return res;
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");
2415 free(dump);
2416 return PM3_ESOFT;
2419 PrintAndLogEx(INFO, "Restoring " _YELLOW_("%s")" to card", filename);
2421 // print dump
2422 printMFUdumpEx(mem, pages, 0);
2424 // Swap endianness
2425 if (swap_endian && has_key) {
2426 if (ak_len == 16)
2427 p_authkey = SwapEndian64(authkey, ak_len, 8);
2428 else
2429 p_authkey = SwapEndian64(authkey, ak_len, 4);
2432 uint8_t data[20] = {0};
2433 uint8_t keytype = 0;
2434 // set key - only once
2435 if (has_key) {
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
2442 if (write_extra) {
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
2448 // pwd
2449 if (has_key || read_key) {
2451 memcpy(data, p_authkey, 4);
2452 if (read_key) {
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);
2463 // copy the new key
2464 keytype = 2;
2465 memcpy(authkey, data, 4);
2466 memcpy(data + 4, authkey, 4);
2469 // pack
2470 memcpy(data, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2);
2471 data[2] = 0;
2472 data[3] = 0;
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);
2478 // Signature
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));
2484 wait4response(s);
2487 // Version
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));
2493 wait4response(s);
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++) {
2504 //Send write Block
2505 memcpy(data, mem->data + (b * 4), 4);
2506 clearCommandBuffer();
2507 SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data));
2508 wait4response(b);
2509 PrintAndLogEx(NORMAL, "." NOLF);
2510 fflush(stdout);
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));
2528 wait4response(b);
2529 PrintAndLogEx(INFO, "special block written %u - %s\n", b, sprint_hex(data, 4));
2533 DropField();
2534 free(dump);
2535 PrintAndLogEx(INFO, "Restore finished");
2536 return PM3_SUCCESS;
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[] = {
2552 arg_param_begin,
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"),
2556 arg_param_end
2558 CLIExecWithReturn(ctx, Cmd, argtable, false);
2559 CLIParserFree(ctx);
2560 return CmdHF14AMfELoad(Cmd);
2563 // Simulate tag
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[] = {
2577 arg_param_begin,
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"),
2582 arg_param_end
2584 CLIExecWithReturn(ctx, Cmd, argtable, false);
2585 CLIParserFree(ctx);
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.",
2600 "hf mfu cauth\n"
2601 "hf mfu cauth --key 000102030405060708090a0b0c0d0e0f"
2604 void *argtable[] = {
2605 arg_param_begin,
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)"),
2609 arg_param_end
2611 CLIExecWithReturn(ctx, Cmd, argtable, true);
2613 int ak_len = 0;
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);
2619 CLIParserFree(ctx);
2621 if (ak_len != 16 && ak_len != 0) {
2622 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
2623 return PM3_EINVARG;
2626 // Swap endianness
2627 if (swap_endian && ak_len) {
2628 authKeyPtr = SwapEndian64(authenticationkey, 16, 8);
2631 bool isok = false;
2633 // If no hex key is specified, try default keys
2634 if (ak_len == 0) {
2635 isok = (try_default_3des_keys(&authKeyPtr) == PM3_SUCCESS);
2636 } else {
2637 // try user-supplied
2638 isok = ulc_authentication(authKeyPtr, !keep_field_on);
2641 if (isok)
2642 PrintAndLogEx(SUCCESS, "Authentication success. 3des key: " _GREEN_("%s"), sprint_hex_inrow(authKeyPtr, 16));
2643 else
2644 PrintAndLogEx(WARNING, "Authentication ( " _RED_("fail") " )");
2646 return PM3_SUCCESS;
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);
2671 memcpy(key1,key,8);
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));
2687 rol(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));
2724 rol(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));
2742 return 0;
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[] = {
2757 arg_param_begin,
2758 arg_str0("k", "key", "<hex>", "New key (16 bytes)"),
2759 arg_param_end
2761 CLIExecWithReturn(ctx, Cmd, argtable, true);
2763 int k_len = 0;
2764 uint8_t key[16] = {0x00};
2765 CLIGetHexWithReturn(ctx, 1, key, &k_len);
2766 CLIParserFree(ctx);
2768 if (k_len != 16) {
2769 PrintAndLogEx(WARNING, "Key must be 16 hex bytes");
2770 return PM3_EINVARG;
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)));
2780 } else {
2781 PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xFF));
2782 return PM3_ESOFT;
2784 } else {
2785 PrintAndLogEx(WARNING, "command execution time out");
2786 return PM3_ETIMEOUT;
2788 return PM3_SUCCESS;
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[] = {
2804 arg_param_begin,
2805 arg_str0("u", "uid", "<hex>", "new uid (7 bytes)"),
2806 arg_param_end
2808 CLIExecWithReturn(ctx, Cmd, argtable, true);
2810 int u_len = 0;
2811 uint8_t uid[7] = {0x00};
2812 CLIGetHexWithReturn(ctx, 1, uid, &u_len);
2813 CLIParserFree(ctx);
2815 if (u_len != 7) {
2816 PrintAndLogEx(WARNING, "UID must be 7 hex bytes");
2817 return PM3_EINVARG;
2820 PrintAndLogEx(INFO, "Please ignore possible transient BCC warnings");
2822 // read block2.
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;
2831 // save old block2.
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));
2850 // block 0.
2851 uint8_t data[4];
2852 data[0] = uid[0];
2853 data[1] = uid[1];
2854 data[2] = uid[2];
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;
2863 // block 1.
2864 data[0] = uid[3];
2865 data[1] = uid[4];
2866 data[2] = uid[5];
2867 data[3] = uid[6];
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;
2875 // block 2.
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));
2892 return PM3_SUCCESS;
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[] = {
2904 arg_param_begin,
2905 arg_str0("u", "uid", "<hex>", "<4|7> hex byte UID"),
2906 arg_lit0("r", NULL, "read UID from tag"),
2907 arg_param_end
2909 CLIExecWithReturn(ctx, Cmd, argtable, true);
2911 int ulen = 0;
2912 uint8_t uid[7];
2913 CLIGetHexWithReturn(ctx, 1, uid, &ulen);
2914 bool read_tag = arg_get_lit(ctx, 2);
2915 CLIParserFree(ctx);
2917 if (read_tag) {
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,
2928 // 1: OK, with ATS
2929 // 2: OK, no ATS
2930 // 3: proprietary Anticollision
2932 if (select_status == 0) {
2933 PrintAndLogEx(WARNING, "iso14443a card select failed");
2934 return PM3_ESOFT;
2937 if (card.uidlen != 4 && card.uidlen != 7) {
2938 PrintAndLogEx(WARNING, "Wrong sized UID, expected 4|7 bytes got %d", card.uidlen);
2939 return PM3_ESOFT;
2941 ulen = card.uidlen;
2942 memcpy(uid, card.uid, card.uidlen);
2943 } else {
2944 if (ulen != 4 && ulen != 7) {
2945 PrintAndLogEx(ERR, "Must supply 4 or 7 hex byte uid");
2946 return PM3_EINVARG;
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];
2967 mix[7] = uid[3];
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
2975 , iv // iv[8]
2976 , mix // input
2977 , divkey // output
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
3011 , iv // iv[8]
3012 , zeros // input
3013 , newpwd // output
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.
3038 return PM3_SUCCESS;
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[] = {
3051 arg_param_begin,
3052 arg_str0("u", "uid", "<hex>", "uid (7 bytes)"),
3053 arg_lit0("r", NULL, "read uid from tag"),
3054 arg_lit0("t", NULL, "selftest"),
3055 arg_param_end
3057 CLIExecWithReturn(ctx, Cmd, argtable, true);
3059 int u_len = 0;
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);
3064 CLIParserFree(ctx);
3066 if (selftest)
3067 return generator_selftest();
3069 if (use_tag) {
3070 // read uid from tag
3071 int res = ul_read_uid(uid);
3072 if (res != PM3_SUCCESS) {
3073 return res;
3076 } else {
3077 if (u_len != 7) {
3078 PrintAndLogEx(WARNING, "Key must be 7 hex bytes");
3079 return PM3_EINVARG;
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, "---------------------------------");
3095 return PM3_SUCCESS;
3099 // MFU TearOff against OTP
3100 // Moebius et al
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[] = {
3114 arg_param_begin,
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)"),
3122 arg_param_end
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);
3131 int d_len = 0;
3132 uint8_t data[4] = {0x00};
3133 CLIGetHexWithReturn(ctx, 5, data, &d_len);
3134 bool use_data = (d_len > 0);
3136 int t_len = 0;
3137 uint8_t test[4] = {0x00};
3138 CLIGetHexWithReturn(ctx, 6, test, &t_len);
3140 int m_len = 0;
3141 uint8_t match[4] = {0x00};
3142 CLIGetHexWithReturn(ctx, 7, match, &m_len);
3143 bool use_match = (m_len > 0);
3144 CLIParserFree(ctx);
3146 if (blockno < 2) {
3147 PrintAndLogEx(WARNING, "Block number must be larger than 2.");
3148 return PM3_EINVARG;
3150 if (end < steps) {
3151 PrintAndLogEx(WARNING, "end time smaller than increase value");
3152 return PM3_EINVARG;
3154 if (end > 43000) {
3155 PrintAndLogEx(WARNING, "end time - out of 1 .. 43000 range");
3156 return PM3_EINVARG;
3158 if (start > (end - steps)) {
3159 PrintAndLogEx(WARNING, "Start time larger than (end time + steps)");
3160 return PM3_EINVARG;
3163 if (d_len && d_len != 4) {
3164 PrintAndLogEx(WARNING, "data must be 4 hex bytes");
3165 return PM3_EINVARG;
3168 if (t_len && t_len != 4) {
3169 PrintAndLogEx(WARNING, "test data must be 4 hex bytes");
3170 return PM3_EINVARG;
3173 if (m_len && m_len != 4) {
3174 PrintAndLogEx(WARNING, "match data must be 4 hex bytes");
3175 return PM3_EINVARG;
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);
3184 if (use_data) {
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));
3188 if (use_match) {
3189 PrintAndLogEx(INFO, "Target match block data : %s", sprint_hex_inrow(match, 4));
3191 PrintAndLogEx(INFO, "----------------------------------------------------");
3192 uint8_t isOK;
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");
3209 break;
3212 PrintAndLogEx(INFO, "Using tear-off delay " _GREEN_("%" PRIu32) " us", current);
3214 clearCommandBuffer();
3215 PacketResponseNG resp;
3217 if (use_data) {
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;
3222 if (isOK) {
3223 got_written = true;
3226 if (! got_written) {
3227 PrintAndLogEx(FAILED, "Failed to write block BEFORE");
3228 error_retries++;
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;
3238 if (isOK) {
3239 memcpy(pre, resp.data.asBytes, sizeof(pre));
3240 got_pre = true;
3243 if (! got_pre) {
3244 PrintAndLogEx(FAILED, "Failed to read block BEFORE");
3245 error_retries++;
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");
3255 return PM3_ESOFT;
3258 if (resp.status != PM3_SUCCESS) {
3259 PrintAndLogEx(WARNING, "Tear off reporting failure to select tag");
3260 error_retries++;
3261 continue;
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;
3269 if (isOK) {
3270 memcpy(post, resp.data.asBytes, sizeof(post));
3271 got_post = true;
3274 if (! got_post) {
3275 PrintAndLogEx(FAILED, "Failed to read block BEFORE");
3276 error_retries++;
3277 continue; // try again
3279 error_retries = 0;
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"
3288 , blockno
3289 , blockno
3290 , poststr
3292 } else {
3293 PrintAndLogEx(INFO, _CYAN_("Tear off occurred") " : %02d (0x%02X) %s => " _RED_("%s")
3294 , blockno
3295 , blockno
3296 , prestr
3297 , poststr
3300 lock_on = true;
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))
3312 skip_phase1 = true;
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");
3323 break;
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");
3338 if (start != end) {
3339 current += steps;
3340 } else {
3341 if (lock_on == false) {
3342 if (++retries == 20) {
3343 current++;
3344 end++;
3345 start++;
3346 retries = 0;
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, "");
3367 return PM3_SUCCESS;
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...");
3381 return PM3_ESOFT;
3383 if (ul_send_cmd_raw(cw, sizeof(cw), resp, sizeof(resp)) < 0) {
3384 PrintAndLogEx(FAILED, "failed to write all ZEROS");
3385 return PM3_ESOFT;
3387 if (ulev1_readTearing(cnt_no, ct, sizeof(ct)) < 0) {
3388 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
3389 return PM3_ESOFT;
3391 DropField();
3393 if (ct[0] != 0xBD) {
3394 PrintAndLogEx(INFO, "Resetting seem to have failed, WHY!?");
3395 return PM3_ESOFT;
3397 return PM3_SUCCESS;
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[] = {
3413 arg_param_begin,
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"),
3420 arg_param_end
3422 CLIExecWithReturn(ctx, Cmd, argtable, false);
3424 int interval = 0;
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);
3433 } else {
3434 start_time = fixed;
3435 interval = 0;
3436 time_limit = fixed;
3439 uint8_t newvalue[5] = {0};
3440 int newvaluelen = 0;
3441 CLIGetHexWithReturn(ctx, 6, newvalue, &newvaluelen);
3442 CLIParserFree(ctx);
3444 // Validations
3445 if (start_time > (time_limit - interval)) {
3446 PrintAndLogEx(WARNING, "Wrong start time number");
3447 return PM3_EINVARG;
3449 if (time_limit < interval) {
3450 PrintAndLogEx(WARNING, "Wrong time limit number");
3451 return PM3_EINVARG;
3453 if (time_limit > 43000) {
3454 PrintAndLogEx(WARNING, "You can't set delay out of 1..43000 range!");
3455 return PM3_EINVARG;
3457 uint8_t cnt_no = 0;
3458 if (counter < 0 || counter > 2) {
3459 PrintAndLogEx(WARNING, "Counter must 0, 1 or 2");
3460 return PM3_EINVARG;
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...");
3472 return PM3_ESOFT;
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");
3479 return PM3_ESOFT;
3482 uint8_t inital_tear[1] = {0};
3483 len = ulev1_readTearing(cnt_no, inital_tear, sizeof(inital_tear));
3484 DropField();
3485 if ( len != sizeof(inital_tear) ) {
3486 PrintAndLogEx(WARNING, "failed to read ANTITEAR, exiting... %d", len);
3487 return PM3_ESOFT;
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;
3505 uint32_t loop = 0;
3507 uint16_t late = 0;
3509 while (actual_time <= (time_limit - interval)) {
3511 DropField();
3513 loop++;
3515 if (kbd_enter_pressed()) {
3516 PrintAndLogEx(INFO, "\naborted via keyboard!\n");
3517 break;
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...");
3524 continue;
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));
3531 } else {
3532 PrintAndLogEx(NORMAL, "");
3533 PrintAndLogEx(FAILED, "BEFORE, failed to read COUNTER, exiting...");
3534 break;
3537 uint8_t tear[1] = {0};
3538 int tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
3539 if ( tlen == sizeof(tear) ) {
3540 pre_tear = tear[0];
3541 } else {
3542 PrintAndLogEx(NORMAL, "");
3543 PrintAndLogEx(FAILED, "BEFORE, failed to read ANTITEAR, exiting... %d", tlen);
3544 break;
3547 DropField();
3549 struct p {
3550 uint8_t counter;
3551 uint32_t tearoff_time;
3552 uint8_t value[3];
3553 } PACKED payload;
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");
3563 continue;
3566 if (ul_select(&card) == false) {
3567 PrintAndLogEx(FAILED, "AFTER, failed to select card, exiting...");
3568 break;
3571 rlen = ulev1_readCounter(cnt_no, cntresp, sizeof(cntresp));
3572 if ( rlen == sizeof(cntresp) ) {
3573 memcpy(post, cntresp, sizeof(post));
3574 } else {
3575 PrintAndLogEx(NORMAL, "");
3576 PrintAndLogEx(FAILED, "AFTER, failed to read COUNTER, exiting...");
3577 break;
3580 tear[0] = 0;
3581 tlen = ulev1_readTearing(cnt_no, tear, sizeof(tear));
3582 if ( tlen == sizeof(tear) ) {
3583 post_tear = tear[0];
3584 } else {
3585 PrintAndLogEx(NORMAL, "");
3586 PrintAndLogEx(FAILED, "AFTER, failed to read ANTITEAR, exiting...");
3587 break;
3590 DropField();
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);
3601 // A != B
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);
3611 else
3612 PrintAndLogEx(INFO, "pre %08x != inital and post %08x == inital %08x | tear: 0x%02X == 0x%02X", a, b, inital_value, pre_tear, post_tear);
3613 } else {
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);
3619 if ( b == 0 ) {
3620 PrintAndLogEx(INFO, _CYAN_("Tear off occured (ZEROS value!) -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
3621 , prestr
3622 , poststr
3623 , pre_tear
3624 , post_tear
3625 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3627 break;
3630 if ( a > b ) {
3631 PrintAndLogEx(INFO, _CYAN_("Tear off occured " _RED_("( LESS )") " -> ") "%s vs " _GREEN_("%s") " Tear status: 0x%02X == 0x%02X ( %s )"
3632 , prestr
3633 , poststr
3634 , pre_tear
3635 , post_tear
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...");
3642 break;
3645 uint32_t bar = (0x1000000 - b) + 2;
3646 // wr_value = bar;
3647 // newvalue[0] = (bar) & 0xFF;
3648 // newvalue[1] = ((bar >> 8) & 0xFF);
3649 // newvalue[2] = ((bar >> 16) & 0xFF);
3651 wr_value = 0;
3652 newvalue[0] = 0;
3653 newvalue[1] = 0;
3654 newvalue[2] = 0;
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));
3661 continue;
3662 } else {
3664 PrintAndLogEx(NORMAL, "");
3665 PrintAndLogEx(INFO, _CYAN_("Tear off occured (+1) (too late) -> ") "%s vs %s Tear: 0x%02X == 0x%02X ( %s )"
3666 , prestr
3667 , poststr
3668 , pre_tear
3669 , post_tear
3670 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3673 if ( post_tear_check && b == inital_value) {
3674 PrintAndLogEx(INFO, "Reverted to previous value");
3675 break;
3677 if ( wr_value != 0 ) {
3679 //uint32_t bar = (0x1000000 - b) + 2;
3680 wr_value = 0;
3681 newvalue[0] = 0;
3682 newvalue[1] = 0;
3683 newvalue[2] = 0;
3685 if ( b >= (inital_value + (2 * wr_value))) {
3686 PrintAndLogEx(INFO, "Large " _YELLOW_("( JUMP )") " detected");
3689 // wr_value = bar;
3690 // newvalue[0] = (bar) & 0xFF;
3691 // newvalue[1] = ((bar >> 8) & 0xFF);
3692 // newvalue[2] = ((bar >> 16) & 0xFF);
3693 } else {
3695 // wr_value = bar;
3696 // newvalue[0] = (bar) & 0xFF;
3697 // newvalue[1] = ((bar >> 8) & 0xFF);
3698 // newvalue[2] = ((bar >> 16) & 0xFF);
3699 // wr_value = 0;
3700 // newvalue[0] = 0;
3701 // newvalue[1] = 0;
3702 // newvalue[2] = 0;
3706 PrintAndLogEx(INFO, "New increase value " _YELLOW_("%s"), sprint_hex_inrow(newvalue, newvaluelen));
3708 //actual_time--;
3709 late++;
3711 } else {
3712 PrintAndLogEx(NORMAL, "");
3713 PrintAndLogEx(INFO, _CYAN_("Status: same value! -> ") "%s == %s Tear: 0x%02X == 0x%02X ( %s )"
3714 , prestr
3715 , poststr
3716 , pre_tear
3717 , post_tear
3718 , post_tear_check ? _GREEN_("OK") : _RED_("DETECTED")
3721 if ( post_tear_check ) {
3722 if ( a == b ) {
3723 //actual_time--;
3724 continue;
3727 if ( b == inital_value ) {
3728 PrintAndLogEx(INFO, "Reverted to previous value");
3729 break;
3731 } else {
3733 if (counter_reset_tear(&card, cnt_no) != PM3_SUCCESS){
3734 PrintAndLogEx(FAILED, "failed to reset tear, exiting...");
3735 break;
3741 actual_time += interval;
3744 DropField();
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);
3759 return PM3_SUCCESS;
3765 // name, identifying bytes, decode function, hints text
3766 // identifying bits
3767 // 1. getversion data must match.
3768 // 2. magic bytes in the readable payload
3771 int CmdHF14MfuNDEFRead(const char *Cmd) {
3773 int keylen;
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[] = {
3791 arg_param_begin,
3792 arg_str0("k", "key", "replace default key for NDEF", NULL),
3793 arg_lit0("l", NULL, "swap entered key's endianness"),
3794 arg_param_end
3796 CLIExecWithReturn(ctx, Cmd, argtable, true);
3797 CLIGetHexWithReturn(ctx, 1, key, &keylen);
3798 swapEndian = arg_get_lit(ctx, 2);
3799 CLIParserFree(ctx);
3801 switch (keylen) {
3802 case 0:
3803 break;
3804 case 4:
3805 case 16:
3806 hasAuthKey = true;
3807 break;
3808 default:
3809 PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n");
3810 return PM3_EINVARG;
3813 // Get tag type
3814 TagTypeUL_t tagtype = GetHF14AMfU_Type();
3815 if (tagtype == UL_ERROR) {
3816 PrintAndLogEx(WARNING, "No Ultraligth / NTAG based tag found");
3817 return PM3_ESOFT;
3820 // Is tag UL/NTAG?
3822 // Swap endianness
3823 if (swapEndian && hasAuthKey) p_key = SwapEndian64(key, keylen, (keylen == 16) ? 8 : 4);
3825 // Select and Auth
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));
3830 if (status == -1) {
3831 DropField();
3832 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
3833 return PM3_ESOFT;
3834 } else if (status == 16) {
3836 status = ndef_print_CC(data + 12);
3837 if (status == PM3_ESOFT) {
3838 DropField();
3839 PrintAndLogEx(ERR, "Error: tag didn't contain a NDEF Container");
3840 return PM3_ESOFT;
3843 // max datasize;
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));
3856 break;
3860 // allocate mem
3861 uint8_t *records = calloc(maxsize, sizeof(uint8_t));
3862 if (records == NULL) {
3863 DropField();
3864 return PM3_EMALLOC;
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);
3870 if (status == -1) {
3871 DropField();
3872 PrintAndLogEx(ERR, "Error: tag didn't answer to READ");
3873 free(records);
3874 return PM3_ESOFT;
3878 DropField();
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=");
3885 if (jooki) {
3886 jooki += 17;
3887 while (jooki) {
3888 if ((*jooki) != '=')
3889 jooki++;
3890 else {
3891 jooki++;
3892 char s[17] = {0};
3893 strncpy(s, jooki, 16);
3894 PrintAndLogEx(HINT, "Use `" _YELLOW_("hf jooki decode -d %s") "` to decode", s);
3895 break;
3899 char *mattel = strstr((char *)records, ".pid.mattel/");
3900 if (mattel) {
3901 mattel += 12;
3902 while (mattel) {
3903 if ((*mattel) != '/')
3904 mattel++;
3905 else {
3906 mattel++;
3907 char b64[33] = {0};
3908 strncpy(b64, mattel, 32);
3909 uint8_t arr[24] = {0};
3910 size_t arrlen = 0;
3911 mbedtls_base64_decode(arr, sizeof(arr), &arrlen, (const unsigned char *)b64, 32);
3913 PrintAndLogEx(INFO, "decoded... %s", sprint_hex(arr, arrlen));
3914 break;
3919 free(records);
3920 return status;
3923 static int CmdHF14AMfuEView(const char *Cmd) {
3924 CLIParserContext *ctx;
3925 CLIParserInit(&ctx, "hf mfu eview",
3926 "It displays emulator memory",
3927 "hf mfu eview"
3930 void *argtable[] = {
3931 arg_param_begin,
3932 arg_param_end
3934 CLIExecWithReturn(ctx, Cmd, argtable, true);
3935 CLIParserFree(ctx);
3937 uint16_t blocks = 0xFF;
3938 uint16_t bytes = blocks * 4;
3940 uint8_t *dump = calloc(bytes, sizeof(uint8_t));
3941 if (dump == NULL) {
3942 PrintAndLogEx(WARNING, "Fail, cannot allocate memory");
3943 return PM3_EMALLOC;
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");
3949 free(dump);
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, "");
3962 free(dump);
3963 return PM3_SUCCESS;
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",
3972 "hf mfu decrypt"
3975 void *argtable[] = {
3976 arg_param_begin,
3977 arg_param_end
3979 CLIExecWithReturn(ctx, Cmd, argtable, true);
3980 CLIParserFree(ctx);
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));
4000 free(encrypted);
4002 return PM3_SUCCESS;
4006 //------------------------------------
4007 // Menu Stuff
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);
4039 return PM3_SUCCESS;
4042 int CmdHFMFUltra(const char *Cmd) {
4043 clearCommandBuffer();
4044 return CmdsParse(CommandTable, Cmd);