diff --git a/client/dictionaries/mfdes_default_keys.dic b/client/dictionaries/mfdes_default_keys.dic index b71a8a8af..4c863c3f5 100644 --- a/client/dictionaries/mfdes_default_keys.dic +++ b/client/dictionaries/mfdes_default_keys.dic @@ -43,3 +43,4 @@ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 404142434445464748494a4b4c4d4e4f 303132333435363738393a3b3c3d3e3f 9CABF398358405AE2F0E2B3D31C99A8A # Default key +605F5E5D5C5B5A59605F5E5D5C5B5A59 # access control \ No newline at end of file diff --git a/client/dictionaries/mfp_default_keys.dic b/client/dictionaries/mfp_default_keys.dic index e492e2686..a063e34ad 100644 --- a/client/dictionaries/mfp_default_keys.dic +++ b/client/dictionaries/mfp_default_keys.dic @@ -27,4 +27,4 @@ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 100f0e0d0c0b0a090807060504030201 404142434445464748494a4b4c4d4e4f 303132333435363738393a3b3c3d3e3f - +605F5E5D5C5B5A59605F5E5D5C5B5A59 diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 421e7488f..76500668d 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -380,7 +380,7 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, - {"MICRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"}, + {"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"}, {"Spark1 Public key", "04d64bb732c0d214e7ec580736acf847284b502c25c0f7f2fa86aace1dada4387a"}, }; /* @@ -423,6 +423,16 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { }; */ uint8_t i; + uint8_t revuid[8]; + for (i = 0; i < sizeof(revuid); i++) { + revuid[i] = uid[7 - i]; + } + uint8_t revsign[32]; + for (i = 0; i < sizeof(revsign); i++) { + revsign[i] = signature[31 - i]; + } + + int reason = 0; bool is_valid = false; for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) { @@ -432,22 +442,65 @@ static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 8, signature, 32, false); is_valid = (res == 0); - if (is_valid) + if (is_valid) { + reason = 1; break; + } + + // try with sha256 + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 8, signature, 32, true); + is_valid = (res == 0); + if (is_valid) { + reason = 2; + break; + } + + // try with reversed uid / signature + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, revuid, sizeof(revuid), revsign, sizeof(revsign), false); + is_valid = (res == 0); + if (is_valid) { + reason = 3; + break; + } + + + // try with sha256 + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, revuid, sizeof(revuid), revsign, sizeof(revsign), true); + is_valid = (res == 0); + if (is_valid) { + reason = 4; + break; + } } PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); if (is_valid == false || i == ARRAYLEN(nxp_15693_public_keys)) { - PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32)); + PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); return PM3_ESOFT; } - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); PrintAndLogEx(INFO, " IC signature public key name: %s", nxp_15693_public_keys[i].desc); PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_15693_public_keys[i].value); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); - PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex(signature, 32)); - PrintAndLogEx(SUCCESS, " Signature verified: " _GREEN_("successful")); + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32)); + PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); + switch(reason) { + case 1: + PrintAndLogEx(INFO, " Params used: UID and signature, plain"); + break; + case 2: + PrintAndLogEx(INFO, " Params used: UID and signature, SHA256"); + break; + case 3: + PrintAndLogEx(INFO, " Params used: reversed UID and signature, plain"); + break; + case 4: + PrintAndLogEx(INFO, " Params used: reversed UID and signature, SHA256"); + break; + } return PM3_SUCCESS; } diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index e48e54958..5517ad15f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1176,6 +1176,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signat {"Mifare Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"} }; + uint32_t i; bool is_valid = false; @@ -1190,24 +1191,29 @@ static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signat if (is_valid) break; } +// PrintAndLogEx(NORMAL, ""); +// PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); if (is_valid == false || i == ARRAYLEN(nxp_desfire_public_keys)) { - PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1"); + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48)); + PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); return PM3_ESOFT; } -// PrintAndLogEx(NORMAL, ""); -// PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_desfire_public_keys[i].desc); PrintAndLogEx(INFO, "IC signature public key value: %.32s", nxp_desfire_public_keys[i].value); - PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 16); PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 32); - PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 48); + PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 64); + PrintAndLogEx(INFO, " : %.32s", nxp_desfire_public_keys[i].value + 96); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48)); - PrintAndLogEx(SUCCESS, " Signature verified: " _GREEN_("successful")); + PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); return PM3_SUCCESS; } diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 4ee04e781..f7d7d2142 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -58,9 +58,9 @@ static char *getCardSizeStr(uint8_t fsize) { // is LSB set? if (fsize & 1) - snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); + snprintf(retStr, sizeof(buf), "0x%02X (" _GREEN_("%d - %d bytes") ")", fsize, usize, lsize); else - snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("%d bytes") ")", fsize, lsize); + snprintf(retStr, sizeof(buf), "0x%02X (" _GREEN_("%d bytes") ")", fsize, lsize); return buf; } @@ -88,18 +88,17 @@ static char *getVersionStr(uint8_t major, uint8_t minor) { char *retStr = buf; if (major == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire MF3ICD40") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire MF3ICD40") ")", major, minor); else if (major == 0x01 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV1") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV1") ")", major, minor); else if (major == 0x12 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV2") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV2") ")", major, minor); else if (major == 0x33 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire EV3") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV3") ")", major, minor); else if (major == 0x30 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("DESFire Light") ")", major, minor); - + snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire Light") ")", major, minor); else if (major == 0x11 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Plus EV1") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("Plus EV1") ")", major, minor); else snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor); return buf; @@ -186,21 +185,26 @@ static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); if (is_valid == false || i == ARRAYLEN(nxp_plus_public_keys)) { - PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1"); + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48)); + PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); return PM3_ESOFT; } PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_plus_public_keys[i].desc); PrintAndLogEx(INFO, "IC signature public key value: %.32s", nxp_plus_public_keys[i].value); - PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 16); PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 32); - PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 48); + PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 64); + PrintAndLogEx(INFO, " : %.32s", nxp_plus_public_keys[i].value + 96); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp224r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48)); - PrintAndLogEx(SUCCESS, " Signature verified: " _GREEN_("successful")); + PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); return PM3_SUCCESS; } @@ -356,10 +360,8 @@ static int CmdHFMFPInfo(const char *Cmd) { } if (card.sak == 0x20) { - PrintAndLogEx(INFO, " SAK: " _GREEN_("MIFARE Plus SL0/SL3") " or " _GREEN_("MIFARE DESFire")); - if (card.ats_len > 0) { - + PrintAndLogEx(INFO, " SAK: " _GREEN_("MIFARE Plus SL0/SL3") " or " _GREEN_("MIFARE DESFire")); SLmode = 3; // check SL0 uint8_t data[250] = {0}; @@ -368,15 +370,22 @@ static int CmdHFMFPInfo(const char *Cmd) { uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; int res = ExchangeRAW14a(cmd, sizeof(cmd), true, false, data, sizeof(data), &datalen, false); - // DESFire answers 0x1C + // DESFire answers 0x1C or 67 00 // Plus answers 0x0B, 0x09 - PrintAndLogEx(INFO, "ICEE: %s", sprint_hex(data, datalen)); - - if (memcmp(data, "\x67\x00", 2) == 0) { - PrintAndLogEx(INFO, "\tMost likely a MIFARE DESFire tag"); + if ( data[0] != 0x0b && data[0] != 0x09 && data[0] != 0x1C && data[0] != 0x67) { + PrintAndLogEx(INFO, _RED_("Send copy to iceman of this command output!")); + PrintAndLogEx(INFO, "data: %s", sprint_hex(data, datalen)); + } + + if ((memcmp(data, "\x67\x00", 2) == 0) || + (memcmp(data, "\x1C\x83\x0C", 3) == 0) + ) { + PrintAndLogEx(INFO, " result: " _RED_("MIFARE DESFire")); PrintAndLogEx(HINT, "Hint: Try " _YELLOW_("`hf mfdes info`")); DropField(); return PM3_SUCCESS; + } else { + PrintAndLogEx(INFO, " result: " _GREEN_("MIFARE Plus SL0/SL3")); } if (!res && datalen > 1 && data[0] == 0x09) { diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 2a642d4c8..0fcbe1796 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -272,14 +272,14 @@ uint32_t UL_TYPES_ARRAY[] = { UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203, NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC, MY_D_MOVE_LEAN, FUDAN_UL, - UL_EV1, NTAG_213_F, NTAG_216_F, UL_NANO_40, NTAG_I2C_1K + UL_EV1, NTAG_213_F, NTAG_216_F, UL_NANO_40, NTAG_I2C_1K, NTAG_213_TT }; uint8_t UL_MEMORY_ARRAY[ARRAYLEN(UL_TYPES_ARRAY)] = { MAX_UL_BLOCKS, MAX_UL_BLOCKS, MAX_ULC_BLOCKS, MAX_ULEV1a_BLOCKS, MAX_ULEV1b_BLOCKS, MAX_NTAG_203, MAX_NTAG_203, MAX_NTAG_210, MAX_NTAG_212, MAX_NTAG_213, MAX_NTAG_215, MAX_NTAG_216, MAX_UL_BLOCKS, MAX_MY_D_NFC, MAX_MY_D_MOVE, MAX_MY_D_MOVE, MAX_MY_D_MOVE_LEAN, MAX_UL_BLOCKS, - MAX_ULEV1a_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_UL_NANO_40, MAX_NTAG_I2C_1K + MAX_ULEV1a_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_UL_NANO_40, MAX_NTAG_I2C_1K, MAX_NTAG_213 }; //------------------------------------ @@ -493,7 +493,7 @@ static int ul_fudan_check(void) { return (!resp.data.asBytes[0]) ? FUDAN_UL : UL; //if response == 0x00 then Fudan, else Genuine NXP } -static int ul_print_default(uint8_t *data) { +static int ul_print_default(uint8_t *data, uint8_t *real_uid) { uint8_t uid[7]; uid[0] = data[0]; @@ -503,10 +503,14 @@ static int ul_print_default(uint8_t *data) { uid[4] = data[5]; uid[5] = data[6]; uid[6] = data[7]; + bool mful_uid_layout = true; - PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(uid, 7)); - PrintAndLogEx(SUCCESS, " UID[0]: %02X, %s", uid[0], getTagInfo(uid[0])); - if (uid[0] == 0x05 && ((uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP + if (memcmp(uid, real_uid, 7) != 0) { + mful_uid_layout = false; + } + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(real_uid, 7)); + PrintAndLogEx(SUCCESS, " UID[0]: %02X, %s", real_uid[0], getTagInfo(real_uid[0])); + if (real_uid[0] == 0x05 && ((real_uid[1] & 0xf0) >> 4) == 2) { // is infineon and 66RxxP uint8_t chip = (data[8] & 0xC7); // 11000111 mask, bit 3,4,5 RFU switch (chip) { case 0xC2: @@ -520,20 +524,23 @@ static int ul_print_default(uint8_t *data) { break; //512 pages /2 sectors } } - // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 - int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; - if (data[3] == crc0) - PrintAndLogEx(SUCCESS, " BCC0: %02X (" _GREEN_("ok") ")", data[3]); - else - PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0); + if (mful_uid_layout) { + // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 + int crc0 = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; + if (data[3] == crc0) + PrintAndLogEx(SUCCESS, " BCC0: %02X (" _GREEN_("ok") ")", data[3]); + else + PrintAndLogEx(NORMAL, " BCC0: %02X, crc should be %02X", data[3], crc0); - int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; - if (data[8] == crc1) - PrintAndLogEx(SUCCESS, " BCC1: %02X (" _GREEN_("ok") ")", data[8]); - else - PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1); - - PrintAndLogEx(SUCCESS, " Internal: %02X (%s)", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default")); + int crc1 = uid[3] ^ uid[4] ^ uid[5] ^ uid[6]; + if (data[8] == crc1) + PrintAndLogEx(SUCCESS, " BCC1: %02X (" _GREEN_("ok") ")", data[8]); + else + PrintAndLogEx(NORMAL, " BCC1: %02X, crc should be %02X", data[8], crc1); + PrintAndLogEx(SUCCESS, " Internal: %02X (%s)", data[9], (data[9] == 0x48) ? _GREEN_("default") : _RED_("not default")); + } else { + PrintAndLogEx(SUCCESS, "Blocks 0-2: %s", sprint_hex(data + 0, 12)); + } PrintAndLogEx(SUCCESS, " Lock: %s - %s", sprint_hex(data + 10, 2), @@ -678,6 +685,8 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces) { PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213 144bytes (NT2H1311G0DU)"), spaces, ""); else if (tagtype & NTAG_213_F) PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213F 144bytes (NT2H1311F0DTL)"), spaces, ""); + else if (tagtype & NTAG_213_TT) + PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 213TT 144bytes (NT2H1311TTDU)"), spaces, ""); else if (tagtype & NTAG_215) PrintAndLogEx(SUCCESS, "%*sTYPE: " _YELLOW_("NTAG 215 504bytes (NT2H1511G0DU)"), spaces, ""); else if (tagtype & NTAG_216) @@ -758,7 +767,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st PrintAndLogEx(INFO, " cfg0 [%u/0x%02X]: %s", startPage, startPage, sprint_hex(data, 4)); - if ((tagtype & (NTAG_213_F | NTAG_216_F))) { + if ((tagtype & (NTAG_213_F | NTAG_213_TT | NTAG_216_F))) { uint8_t mirror_conf = (data[0] & 0xC0); uint8_t mirror_byte = (data[0] & 0x30); bool sleep_en = (data[0] & 0x08); @@ -801,7 +810,7 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st break; } // valid mirror start page and byte position within start page. - if (tagtype & NTAG_213_F) { + if ((tagtype & NTAG_213_F)||(tagtype & NTAG_213_TT)) { switch (mirror_conf) { case 1: { PrintAndLogEx(INFO, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, (data[2] >= 0x4 && data[2] <= 0x24) ? "OK" : "Invalid value"); break;} @@ -880,7 +889,7 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, - {"MICRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"}, + {"MIKRON Public key", "04f971eda742a4a80d32dcf6a814a707cc3dc396d35902f72929fdcd698b3468f2"}, }; /* @@ -945,17 +954,19 @@ static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *sig } PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); if (is_valid == false || i == ARRAYLEN(nxp_mfu_public_keys)) { - PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); + PrintAndLogEx(SUCCESS, " Signature verification: " _RED_("failed")); return PM3_ESOFT; } - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); PrintAndLogEx(INFO, " IC signature public key name: %s", nxp_mfu_public_keys[i].desc); PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_public_keys[i].value); PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verified: " _GREEN_("successful")); + PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); return PM3_SUCCESS; } @@ -1088,6 +1099,7 @@ uint32_t GetHF14AMfU_Type(void) { MF0UNH1001DUx 0004030203000B03 NT2L1001G0DUx 0004040102000B03 NT2H1001G0DUx 0004040202000B03 + NT2H1311TTDUx 0004040203000F03 Micron UL 0034210101000E03 */ @@ -1104,6 +1116,7 @@ uint32_t GetHF14AMfU_Type(void) { else if (memcmp(version, "\x00\x04\x04\x02\x01\x00\x13", 7) == 0) { tagtype = NTAG_216; break; } else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x0F", 7) == 0) { tagtype = NTAG_213_F; break; } else if (memcmp(version, "\x00\x04\x04\x04\x01\x00\x13", 7) == 0) { tagtype = NTAG_216_F; break; } + else if (memcmp(version, "\x00\x04\x04\x02\x03\x00\x0F", 7) == 0) { tagtype = NTAG_213_TT; break; } else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x13", 7) == 0) { tagtype = NTAG_I2C_1K; break; } else if (memcmp(version, "\x00\x04\x04\x05\x02\x01\x15", 7) == 0) { tagtype = NTAG_I2C_2K; break; } else if (memcmp(version, "\x00\x04\x04\x05\x02\x02\x13", 7) == 0) { tagtype = NTAG_I2C_1K_PLUS; break; } @@ -1208,7 +1221,6 @@ static int CmdHF14AMfUInfo(const char *Cmd) { uint8_t *key = pwd; uint8_t pack[4] = {0, 0, 0, 0}; int len; - uint8_t uid[7]; char tempStr[50]; @@ -1261,9 +1273,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { PrintAndLogEx(ERR, "Error: tag didn't answer to READ"); return PM3_ESOFT; } else if (status == 16) { - memcpy(uid, data, 3); - memcpy(uid + 3, data + 4, 4); - ul_print_default(data); + ul_print_default(data, card.uid); ndef_print_CC(data + 12); } else { locked = true; @@ -1328,7 +1338,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { } // NTAG counters? - if ((tagtype & (NTAG_213 | NTAG_213_F | NTAG_215 | NTAG_216))) { + if ((tagtype & (NTAG_213 | NTAG_213_F | NTAG_213_TT | NTAG_215 | NTAG_216))) { if (ntag_print_counter()) { // failed - re-select if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; @@ -1336,7 +1346,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { } // Read signature - if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1 | UL_NANO_40 | NTAG_213 | NTAG_213_F | NTAG_215 | NTAG_216 | NTAG_216_F | NTAG_I2C_1K | NTAG_I2C_2K | NTAG_I2C_1K_PLUS | NTAG_I2C_2K_PLUS))) { + if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1 | UL_NANO_40 | NTAG_213 | NTAG_213_F | NTAG_213_TT | NTAG_215 | NTAG_216 | NTAG_216_F | NTAG_I2C_1K | NTAG_I2C_2K | NTAG_I2C_1K_PLUS | NTAG_I2C_2K_PLUS))) { uint8_t ulev1_signature[32] = {0x00}; status = ulev1_readSignature(ulev1_signature, sizeof(ulev1_signature)); if (status == -1) { @@ -1345,7 +1355,7 @@ static int CmdHF14AMfUInfo(const char *Cmd) { return PM3_ESOFT; } if (status == 32) { - ulev1_print_signature(tagtype, uid, ulev1_signature, sizeof(ulev1_signature)); + ulev1_print_signature(tagtype, card.uid, ulev1_signature, sizeof(ulev1_signature)); } else { // re-select if (ul_auth_select(&card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack)) == PM3_ESOFT) return PM3_ESOFT; @@ -2022,7 +2032,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { uint8_t n = 0; // NTAG has 1 counter, at 0x02 - if ((tagtype & (NTAG_213 | NTAG_213_F | NTAG_215 | NTAG_216))) { + if ((tagtype & (NTAG_213 | NTAG_213_F | NTAG_213_TT | NTAG_215 | NTAG_216))) { n = 2; } diff --git a/client/src/cmdhfmfu.h b/client/src/cmdhfmfu.h index 67e405677..210783874 100644 --- a/client/src/cmdhfmfu.h +++ b/client/src/cmdhfmfu.h @@ -57,6 +57,7 @@ typedef enum TAGTYPE_UL { NTAG_216_F = 0x800000, UL_EV1 = 0x1000000, UL_NANO_40 = 0x2000000, + NTAG_213_TT = 0x4000000, UL_MAGIC = UL | MAGIC, UL_C_MAGIC = UL_C | MAGIC, UL_ERROR = 0xFFFFFF, diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 67042259c..74821b449 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -1522,7 +1522,7 @@ out: } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"-----------", CmdHelp, AlwaysAvailable, "-------------- " _CYAN_("Direct") " --------------"}, {"awid", CmdLFAWID, AlwaysAvailable, "{ AWID RFIDs... }"}, {"cotag", CmdLFCOTAG, AlwaysAvailable, "{ COTAG CHIPs... }"}, {"em", CmdLFEM4X, AlwaysAvailable, "{ EM4X CHIPs & RFIDs... }"}, @@ -1549,16 +1549,17 @@ static command_t CommandTable[] = { {"t55xx", CmdLFT55XX, AlwaysAvailable, "{ T55xx CHIPs... }"}, {"viking", CmdLFViking, AlwaysAvailable, "{ Viking RFIDs... }"}, {"visa2000", CmdLFVisa2k, AlwaysAvailable, "{ Visa2000 RFIDs... }"}, - {"", CmdHelp, AlwaysAvailable, ""}, + {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, {"config", CmdLFConfig, IfPm3Lf, "Get/Set config for LF sampling, bit/sample, decimation, frequency"}, {"cmdread", CmdLFCommandRead, IfPm3Lf, "Modulate LF reader field to send command before read (all periods in microseconds)"}, {"read", CmdLFRead, IfPm3Lf, "Read LF tag"}, {"search", CmdLFfind, AlwaysAvailable, "Read and Search for valid known tag (in offline mode it you can load first then search)"}, {"sim", CmdLFSim, IfPm3Lf, "Simulate LF tag from buffer with optional GAP (in microseconds)"}, - {"simask", CmdLFaskSim, IfPm3Lf, "Simulate LF ASK tag from demodbuffer or input"}, - {"simfsk", CmdLFfskSim, IfPm3Lf, "Simulate LF FSK tag from demodbuffer or input"}, - {"simpsk", CmdLFpskSim, IfPm3Lf, "Simulate LF PSK tag from demodbuffer or input"}, -// {"simpsk", CmdLFnrzSim, IfPm3Lf, "Simulate LF NRZ tag from demodbuffer or input"}, + {"simask", CmdLFaskSim, IfPm3Lf, "Simulate " _YELLOW_("LF ASK tag") " from demodbuffer or input"}, + {"simfsk", CmdLFfskSim, IfPm3Lf, "Simulate " _YELLOW_("LF FSK tag") " from demodbuffer or input"}, + {"simpsk", CmdLFpskSim, IfPm3Lf, "Simulate " _YELLOW_("LF PSK tag") " from demodbuffer or input"}, +// {"simpsk", CmdLFnrzSim, IfPm3Lf, "Simulate " _YELLOW_("LF NRZ tag") " from demodbuffer or input"}, {"simbidir", CmdLFSimBidir, IfPm3Lf, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, {"sniff", CmdLFSniff, IfPm3Lf, "Sniff LF traffic between reader and tag"}, {"tune", CmdLFTune, IfPm3Lf, "Continuously measure LF antenna tuning"}, diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index 837c13fed..93bba22bf 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -168,7 +168,11 @@ void CmdsHelp(const command_t Commands[]) { while (Commands[i].Name) { if (Commands[i].IsAvailable()) { g_printAndLog = PRINTANDLOG_PRINT; - PrintAndLogEx(NORMAL, _GREEN_("%-16s")" %s", Commands[i].Name, Commands[i].Help); + if (Commands[i].Name[0] == '-' || Commands[i].Name[0] == ' ') { + PrintAndLogEx(NORMAL, "%-16s %s", Commands[i].Name, Commands[i].Help); + } else { + PrintAndLogEx(NORMAL, _GREEN_("%-16s")" %s", Commands[i].Name, Commands[i].Help); + } g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; } ++i; diff --git a/tools/recover_pk.py b/tools/recover_pk.py new file mode 100755 index 000000000..b2ff2e6c7 --- /dev/null +++ b/tools/recover_pk.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +# @doegox -- 2020 + +import sslcrypto +import binascii +import sys + +debug = False + +def recover(data, signature, alghash=None): + recovered = set() + if len(signature) == 32: + curve = sslcrypto.ecc.get_curve("secp128r1") + recoverable = False + elif len(signature) == 33: + curve = sslcrypto.ecc.get_curve("secp128r1") + recoverable = True + elif len(signature) == 56: + curve = sslcrypto.ecc.get_curve("secp224r1") + recoverable = False + elif len(signature) == 57: + curve = sslcrypto.ecc.get_curve("secp224r1") + recoverable = True + else: + print("Unsupported signature size %i" % len(signature)) + exit(1) + + if (recoverable): + try: + pk = curve.recover(signature, data, hash=alghash) + recovered.add(pk) + if debug: + print("Possible Pk: ", binascii.hexlify(pk)) + except: + pass + else: + for i in range(2): + # Brute force RECID + recid = bytes([27+i]) + try: + pk = curve.recover(recid + signature, data, hash=alghash) + recovered.add(pk) + if debug: + print("Possible Pk: ", binascii.hexlify(pk)) + except: + pass + return recovered + +def recover_multiple(uids, sigs, alghash=None): + recovered = set() + assert len(uids) == len(sigs) + for i in range(len(uids)): + data = binascii.unhexlify(uids[i]) + if debug: + print("UID (%2i): " % len(data), binascii.hexlify(data)) + signature = binascii.unhexlify(sigs[i]) + if debug: + print("Signature (%2i): " % len(signature), binascii.hexlify(signature)) + recovered_tmp = recover(data, signature, alghash) + if i == 0: + if recovered_tmp == set(): + break + else: + recovered = recovered_tmp + else: + recovered &= recovered_tmp + return recovered + +if len(sys.argv) < 3 or len(sys.argv) % 2 == 0: + print("Usage: \n%s UID SIGN [UID SIGN] [...]" % sys.argv[0]) + print("Example: \n%s 04ee45daa34084 ebb6102bff74b087d18a57a54bc375159a04ea9bc61080b7f4a85afe1587d73b" % sys.argv[0]) + exit(1) + +print("Assuming no hash was used in the signature generation:") +recovered = recover_multiple(sys.argv[1:][::2], sys.argv[1:][1::2]) +print("Possible uncompressed Pk(s):") +for pk in list(recovered): + print(binascii.hexlify(pk).decode('utf8')) +print("Assuming SHA-256 was used in the signature generation:") +recovered = recover_multiple(sys.argv[1:][::2], sys.argv[1:][1::2], alghash="sha256") +print("Possible uncompressed Pk(s):") +for pk in list(recovered): + print(binascii.hexlify(pk).decode('utf8'))