diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 9b0b8dbf1..2003fd924 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -208,7 +208,8 @@ const productName uidmapping[] = { { 0, 0, "no tag-info available" } // must be the last entry }; -uint8_t nxp_public_keys[][33] = { +#define PUBLIC_ECDA_KEYLEN 33 +uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = { // ICODE SLIX2 / DNA { 0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3, @@ -216,10 +217,67 @@ uint8_t nxp_public_keys[][33] = { 0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64, 0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0 }, + // unknown. Needs identification + { + 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, + 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, + 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, + 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF + }, + // unknown. Needs identification + { + 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, + 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, + 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, + 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC + }, + // manufacturer public key + { + 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, + 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, + 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, + 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 + }, + // MIKRON public key. + { + 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, + 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, + 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, + 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 + } }; static int CmdHF15Help(const char *Cmd); +static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { + + uint8_t i; + int res; + bool is_valid = false; + for (i = 0; i< ARRAYLEN(nxp_15693_public_keys); i++) { + + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_15693_public_keys[i], uid, 8, signature, 32, false); + + is_valid = (res == 0); + if (is_valid) + break; + } + + PrintAndLogEx(NORMAL, ""); + if (is_valid == false) { + PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + return PM3_ESOFT; + } + + PrintAndLogEx(INFO, "\n--- Tag Signature"); + PrintAndLogEx(INFO, " IC signature public key name : %s", (i == 0)? "NXP ICODE SLIX2 / DNA" : "unknown, post on forum"); + PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_15693_public_keys[i], 33)); + PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1"); + PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 32)); + PrintAndLogEx(INFO, " Signature verification " _GREEN_("successful")); + return PM3_SUCCESS; +} + // fast method to just read the UID of a tag (collision detection not supported) // *buf should be large enough to fit the 64bit uid // returns 1 if succeeded @@ -796,16 +854,8 @@ static int NxpSysInfo(uint8_t *uid) { uint8_t signature[32] = {0x00}; memcpy(signature, recv + 1, 32); - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_public_keys[0], uid, 8, signature, 32, false); - bool is_valid = (res == 0); + nxp_15693_print_signature(uid, signature); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Tag Signature"); - PrintAndLogEx(NORMAL, " IC signature public key name : NXP ICODE SLIX2 / DNA"); - PrintAndLogEx(NORMAL, " IC signature public key value : %s", sprint_hex(nxp_public_keys[0], 33)); - PrintAndLogEx(NORMAL, " Elliptic curve parameters : NID_secp128r1"); - PrintAndLogEx(NORMAL, " TAG IC Signature : %s", sprint_hex(signature, 32)); - PrintAndLogEx(NORMAL, " Signature verification %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); } } @@ -901,10 +951,16 @@ static int CmdHF15Info(const char *Cmd) { } // Check if SLIX2 and attempt to get NXP System Information + PrintAndLogEx(INFO, "4 & 08 :: %02x 7 == 1 :: %u 8 == 4 :: %u", recv[4], recv[7], recv[8]); if (recv[8] == 0x04 && recv[7] == 0x01 && recv[4] & 0x80) { return NxpSysInfo(uid); } +// if (recv[8] == 0x04 && recv[7] == 0x02 && recv[4] & 0x80) { + return NxpSysInfo(uid); + //} + + PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 7209a5a71..d44f3443d 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -12,6 +12,7 @@ #include #include +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" @@ -121,18 +122,10 @@ static int get_desfire_freemem(uint32_t *free_mem) { // --- GET SIGNATURE static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t signature_len, desfire_cardtype_t card_type) { - uint8_t public_key; - if (card_type == LIGHT) - public_key = 0; - else if (card_type == EV2) - public_key = 1; - else - return PM3_EINVARG; - #define PUBLIC_DESFIRE_ECDA_KEYLEN 57 // ref: MIFARE Desfire Originality Signature Validation - uint8_t nxp_desfire_keys[2][PUBLIC_DESFIRE_ECDA_KEYLEN] = { + uint8_t nxp_desfire_keys[][PUBLIC_DESFIRE_ECDA_KEYLEN] = { // DESFire Light { 0x04, 0x0E, 0x98, 0xE1, 0x17, 0xAA, 0xA3, 0x64, @@ -143,7 +136,11 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0xD0, 0x25, 0x72, 0x42, 0x7E, 0x5A, 0xE0, 0xA2, 0xDD, 0x36, 0x59, 0x1B, 0x1F, 0xB3, 0x4F, 0xCF, 0x3D }, - // DESFire Ev2 + + // DESFire Ev2 - wanted + // DESFire Ev3 - wanted + + // Unknown - needs identification { 0x04, 0x8A, 0x9B, 0x38, 0x0A, 0xF2, 0xEE, 0x1B, 0x98, 0xDC, 0x41, 0x7F, 0xEC, 0xC2, 0x63, 0xF8, @@ -152,26 +149,59 @@ static int desfire_print_signature(uint8_t *uid, uint8_t *signature, size_t sign 0x42, 0x2B, 0x81, 0xEC, 0x20, 0xB6, 0x5A, 0x66, 0xB5, 0x10, 0x2A, 0x61, 0x59, 0x6A, 0xF3, 0x37, 0x92, 0x00, 0x59, 0x93, 0x16, 0xA0, 0x0A, 0x14, 0x10 - } + }, + // Unknown - needs identification + { + 0x04, 0x44, 0x09, 0xAD, 0xC4, 0x2F, 0x91, 0xA8, + 0x39, 0x40, 0x66, 0xBA, 0x83, 0xD8, 0x72, 0xFB, + 0x1D, 0x16, 0x80, 0x37, 0x34, 0xE9, 0x11, 0x17, + 0x04, 0x12, 0xDD, 0xF8, 0xBA, 0xD1, 0xA4, 0xDA, + 0xDF, 0xD0, 0x41, 0x62, 0x91, 0xAF, 0xE1, 0xC7, + 0x48, 0x25, 0x39, 0x25, 0xDA, 0x39, 0xA5, 0xF3, + 0x9A, 0x1C, 0x55, 0x7F, 0xFA, 0xCD, 0x34, 0xC6, 0x2E + } }; + + uint8_t i; + int res; + bool is_valid = false; + for (i = 0; i< ARRAYLEN(nxp_desfire_keys); i++) { + + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[i], uid, 7, signature, signature_len, false); + + is_valid = (res == 0); + if (is_valid) + break; + } + if (is_valid == false) { + PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + return PM3_ESOFT; + } - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, nxp_desfire_keys[public_key], uid, 7, signature, signature_len, false); - bool is_valid = (res == 0); + char *publickeyname; + switch(i) { + case 0: + publickeyname = "NXP DESFire Light"; + break; + default: + publickeyname = "Unknown DESFire, post on forum"; + break; + } PrintAndLogEx(INFO, " Tag Signature"); - PrintAndLogEx(INFO, " IC signature public key name : %s", (card_type == LIGHT) ? "NXP DESFire Light" : "NXP DESFire Ev2"); - PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[public_key], 16)); - PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 16, 16)); - PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 32, 16)); - PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[public_key] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48)); + PrintAndLogEx(INFO, " IC signature public key name : %s", publickeyname); + PrintAndLogEx(INFO, " IC signature public key value : %s", sprint_hex(nxp_desfire_keys[i], 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 16, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 32, 16)); + PrintAndLogEx(INFO, " : %s", sprint_hex(nxp_desfire_keys[i] + 48, PUBLIC_DESFIRE_ECDA_KEYLEN - 48)); PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp224r1"); PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 16, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 32, 16)); PrintAndLogEx(INFO, " : %s", sprint_hex(signature + 48, signature_len - 48)); - PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + PrintAndLogEx( (is_valid) ? SUCCESS : WARNING, " Signature verified " _GREEN_("successful")); PrintAndLogEx(INFO, "-------------------------------------------------------------"); return PM3_SUCCESS; } diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index d5a632f8f..7acf7379b 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -262,57 +262,6 @@ uint8_t default_pwd_pack[][4] = { {0xFF, 0xFF, 0xFF, 0xFF}, // PACK 0x00,0x00 -- factory default }; -#define PUBLIC_ECDA_KEYLEN 33 - -// known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier) -// ref: AN11350 NTAG 21x Originality Signature Validation -// ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation -uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = { - // UL, NTAG21x and NDEF - { - 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, - 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49, - 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39, - 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61 - }, - // UL EV1 - { - 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b, - 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8, - 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72, - 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8 - }, - // unknown. Needs identification - { - 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, - 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, - 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, - 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF - }, - // unknown. Needs identification - { - 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, - 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, - 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, - 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC - }, - // manufacturer public key - { - 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, - 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, - 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, - 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 - }, - // MIKRON public key. - { - 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, - 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, - 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, - 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 - } -}; - - 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, @@ -915,19 +864,98 @@ static int ulev1_print_counters() { } static int ulev1_print_signature(TagTypeUL_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) { - uint8_t public_key = 0; - if (tagtype == UL_EV1_48 || tagtype == UL_EV1_128) { - public_key = 1; + + #define PUBLIC_ECDA_KEYLEN 33 + + // known public keys for the originality check (source: https://github.com/alexbatalov/node-nxp-originality-verifier) + // ref: AN11350 NTAG 21x Originality Signature Validation + // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation + uint8_t nxp_mfu_public_keys[6][PUBLIC_ECDA_KEYLEN] = { + // UL, NTAG21x and NDEF + { + 0x04, 0x49, 0x4e, 0x1a, 0x38, 0x6d, 0x3d, 0x3c, + 0xfe, 0x3d, 0xc1, 0x0e, 0x5d, 0xe6, 0x8a, 0x49, + 0x9b, 0x1c, 0x20, 0x2d, 0xb5, 0xb1, 0x32, 0x39, + 0x3e, 0x89, 0xed, 0x19, 0xfe, 0x5b, 0xe8, 0xbc, 0x61 + }, + // UL EV1 + { + 0x04, 0x90, 0x93, 0x3b, 0xdc, 0xd6, 0xe9, 0x9b, + 0x4e, 0x25, 0x5e, 0x3d, 0xa5, 0x53, 0x89, 0xa8, + 0x27, 0x56, 0x4e, 0x11, 0x71, 0x8e, 0x01, 0x72, + 0x92, 0xfa, 0xf2, 0x32, 0x26, 0xa9, 0x66, 0x14, 0xb8 + }, + // unknown. Needs identification + { + 0x04, 0x4F, 0x6D, 0x3F, 0x29, 0x4D, 0xEA, 0x57, + 0x37, 0xF0, 0xF4, 0x6F, 0xFE, 0xE8, 0x8A, 0x35, + 0x6E, 0xED, 0x95, 0x69, 0x5D, 0xD7, 0xE0, 0xC2, + 0x7A, 0x59, 0x1E, 0x6F, 0x6F, 0x65, 0x96, 0x2B, 0xAF + }, + // unknown. Needs identification + { + 0x04, 0xA7, 0x48, 0xB6, 0xA6, 0x32, 0xFB, 0xEE, + 0x2C, 0x08, 0x97, 0x70, 0x2B, 0x33, 0xBE, 0xA1, + 0xC0, 0x74, 0x99, 0x8E, 0x17, 0xB8, 0x4A, 0xCA, + 0x04, 0xFF, 0x26, 0x7E, 0x5D, 0x2C, 0x91, 0xF6, 0xDC + }, + // manufacturer public key + { + 0x04, 0x6F, 0x70, 0xAC, 0x55, 0x7F, 0x54, 0x61, + 0xCE, 0x50, 0x52, 0xC8, 0xE4, 0xA7, 0x83, 0x8C, + 0x11, 0xC7, 0xA2, 0x36, 0x79, 0x7E, 0x8A, 0x07, + 0x30, 0xA1, 0x01, 0x83, 0x7C, 0x00, 0x40, 0x39, 0xC2 + }, + // MIKRON public key. + { + 0x04, 0xf9, 0x71, 0xed, 0xa7, 0x42, 0xa4, 0xa8, + 0x0d, 0x32, 0xdc, 0xf6, 0xa8, 0x14, 0xa7, 0x07, + 0xcc, 0x3d, 0xc3, 0x96, 0xd3, 0x59, 0x02, 0xf7, + 0x29, 0x29, 0xfd, 0xcd, 0x69, 0x8b, 0x34, 0x68, 0xf2 + } + }; + + uint8_t i; + int res; + bool is_valid = false; + for (i = 0; i< ARRAYLEN(nxp_mfu_public_keys); i++) { + + res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_mfu_public_keys[i], uid, 7, signature, signature_len, false); + + is_valid = (res == 0); + if (is_valid) + break; + } + if (is_valid == false) { + PrintAndLogEx(SUCCESS, "Signature verification " _RED_("failed")); + return PM3_ESOFT; + } + + char *publickeyname; + switch(i) { + case 0: + publickeyname = "NXP NTAG21x (2013)"; + break; + case 1: + publickeyname = "NXP Ev1"; + break; + case 4: + publickeyname = "Manufacturer, post on forum"; + break; + case 5: + publickeyname = "MIKRON"; + break; + default: + publickeyname = "Unknown, post on forum"; + break; } - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_mfu_public_keys[public_key], uid, 7, signature, signature_len, false); - bool is_valid = (res == 0); PrintAndLogEx(INFO, "\n--- Tag Signature"); - PrintAndLogEx(INFO, "IC signature public key name : NXP NTAG21x (2013)"); - PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(nxp_mfu_public_keys[public_key], PUBLIC_ECDA_KEYLEN)); + PrintAndLogEx(INFO, "IC signature public key name : %s", publickeyname); + PrintAndLogEx(INFO, "IC signature public key value : %s", sprint_hex(nxp_mfu_public_keys[i], PUBLIC_ECDA_KEYLEN)); PrintAndLogEx(INFO, " Elliptic curve parameters : NID_secp128r1"); PrintAndLogEx(INFO, " TAG IC Signature : %s", sprint_hex(signature, signature_len)); - PrintAndLogEx(SUCCESS, "Signature verified %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + PrintAndLogEx(SUCCESS, "Signature verified " _GREEN_("successful")); return PM3_SUCCESS; }