From f26727eb28ff48afd2dd747a04270cd122846222 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 14 Dec 2024 02:18:38 +0100 Subject: [PATCH] Refactor originality checks. Notes: - removed pk "NTAG424DNA, NTAG424DNATT, DESFire Light Ev2", "04B304...3B" which is a typo of "DESFire Ev2", "04B3...3A"}, - MIKRON pk currently not used because I don't know if it's for MFC, MFUL or sth else - ST25TN pk added but currently not used, need to be implemented/tested - ST25TV pk currently not used, need to be implemented/tested --- CHANGELOG.md | 1 + client/CMakeLists.txt | 1 + client/Makefile | 1 + client/experimental_lib/CMakeLists.txt | 1 + client/src/cmdhf15.c | 131 ++++--------------- client/src/cmdhfmf.c | 50 +------- client/src/cmdhfmfdes.c | 58 +-------- client/src/cmdhfmfp.c | 51 +------- client/src/cmdhfmfu.c | 131 +------------------ client/src/cmdhfst25ta.c | 46 +------ client/src/crypto/originality.c | 171 +++++++++++++++++++++++++ client/src/crypto/originality.h | 42 ++++++ 12 files changed, 261 insertions(+), 423 deletions(-) create mode 100644 client/src/crypto/originality.c create mode 100644 client/src/crypto/originality.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aed8d508..b6d3ca1da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Changed originality checks handling to refactor code and pk data (@doegox) - Changed `uniq.yaml` workflow to be case-insensitive (@iceman1001) - Fixed `mem load --mfc` not erasing all SPI flash blocks after extending to 4095 keys (@piotrva) - Extended area for Mifare keys in SPI flash to hold 4095 keys (@piotrva) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 544fe5395..2a74b1500 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -270,6 +270,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/crypto/asn1dump.c ${PM3_ROOT}/client/src/crypto/asn1utils.c ${PM3_ROOT}/client/src/crypto/libpcrypto.c + ${PM3_ROOT}/client/src/crypto/originality.c ${PM3_ROOT}/client/src/emv/test/cda_test.c ${PM3_ROOT}/client/src/emv/test/crypto_test.c ${PM3_ROOT}/client/src/emv/test/cryptotest.c diff --git a/client/Makefile b/client/Makefile index f7a59ed3f..d01e08af0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -693,6 +693,7 @@ SRCS = mifare/aiddesfire.c \ crypto/asn1dump.c \ crypto/asn1utils.c\ crypto/libpcrypto.c\ + crypto/originality.c\ emv/cmdemv.c \ emv/crypto.c\ emv/crypto_polarssl.c\ diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt index e9ac8bb33..87e653c11 100644 --- a/client/experimental_lib/CMakeLists.txt +++ b/client/experimental_lib/CMakeLists.txt @@ -271,6 +271,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/crypto/asn1dump.c ${PM3_ROOT}/client/src/crypto/asn1utils.c ${PM3_ROOT}/client/src/crypto/libpcrypto.c + ${PM3_ROOT}/client/src/crypto/originality.c ${PM3_ROOT}/client/src/emv/test/cda_test.c ${PM3_ROOT}/client/src/emv/test/crypto_test.c ${PM3_ROOT}/client/src/emv/test/cryptotest.c diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index b5d886382..86a326341 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -43,6 +43,7 @@ #include "cliparser.h" #include "util_posix.h" // msleep #include "iso15.h" // typedef structs / enum +#include "crypto/originality.h" #define FrameSOF Iso15693FrameSOF #define Logic0 Iso15693Logic0 @@ -281,121 +282,35 @@ static const productName_t uidmapping[] = { static int CmdHF15Help(const char *Cmd); static int nxp_15693_print_signature(uint8_t *uid, uint8_t *signature) { - -#define PUBLIC_ECDA_KEYLEN 33 - const ecdsa_publickey_t nxp_15693_public_keys[] = { - {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"}, - {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"}, - {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"}, - {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, - {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, - {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, - {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"}, - {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"}, - {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"}, - {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"}, - }; - /* - uint8_t nxp_15693_public_keys[][PUBLIC_ECDA_KEYLEN] = { - // ICODE SLIX2 / DNA - { - 0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3, - 0x36, 0xB4, 0xF2, 0x61, 0xA0, 0x82, 0xBD, 0x71, - 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 - } - }; - */ - - uint8_t revuid[HF15_UID_LENGTH] = {0}; - reverse_array_copy(uid, sizeof(revuid), revuid); - - uint8_t revsign[32] = {0}; - reverse_array_copy(signature, sizeof(revsign), revsign); - - uint8_t i; int reason = 0; - bool is_valid = false; - for (i = 0; i < ARRAYLEN(nxp_15693_public_keys); i++) { - - int dl = 0; - uint8_t key[PUBLIC_ECDA_KEYLEN]; - param_gethex_to_eol(nxp_15693_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 8, signature, 32, false); - is_valid = (res == 0); - if (is_valid) { - reason = 1; - break; - } - + int index = -1; + index = originality_check_verify(uid, 8, signature, 32, PK_MFC); + if (index >= 0) { + reason = 1; + } else { // 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) { + index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, false, true); + if (index >= 0) { 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; + } else { + // try with reversed uid / signature + index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, true, false); + if (index >= 0) { + reason = 3; + } else { + // try with sha256 and reversed uid / signature + index = originality_check_verify_ex(uid, 8, signature, 32, PK_MFC, true, true); + if (index >= 0) { + reason = 3; + } + } } } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - if (is_valid == false || i == ARRAYLEN(nxp_15693_public_keys)) { - 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; + int ret = originality_check_print(signature, 32, index); + if (ret != PM3_SUCCESS) { + return ret; } - - PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%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_inrow(signature, 32)); - PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); switch (reason) { case 1: PrintAndLogEx(INFO, " Params used: UID and signature, plain"); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index e61a6a7e9..1dedaafca 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -46,6 +46,7 @@ #include "generator.h" // keygens. #include "fpga.h" #include "mifare/mifarehost.h" +#include "crypto/originality.h" static int CmdHelp(const char *Cmd); @@ -68,52 +69,9 @@ static int usage_hf14_keybrute(void) { */ int mfc_ev1_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) { - - // ref: MIFARE Classic EV1 Originality Signature Validation -#define PUBLIC_MFCEV1_ECDA_KEYLEN 33 - const ecdsa_publickey_t nxp_mfc_public_keys[] = { - {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"}, - {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"}, - {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"}, - {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, - {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, - {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, - {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"}, - {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"}, - {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"}, - {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"}, - }; - - uint8_t i; - bool is_valid = false; - - for (i = 0; i < ARRAYLEN(nxp_mfc_public_keys); i++) { - - int dl = 0; - uint8_t key[PUBLIC_MFCEV1_ECDA_KEYLEN]; - param_gethex_to_eol(nxp_mfc_public_keys[i].value, 0, key, PUBLIC_MFCEV1_ECDA_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, uidlen, signature, signature_len, false); - is_valid = (res == 0); - if (is_valid) - break; - } - - PrintAndLogEx(INFO, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - if (is_valid == false || i == ARRAYLEN(nxp_mfc_public_keys)) { - 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, " IC signature public key name: " _GREEN_("%s"), nxp_mfc_public_keys[i].desc); - PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfc_public_keys[i].value); - PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp128r1"); - PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 32)); - PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); - return PM3_SUCCESS; + int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFC); + PrintAndLogEx(NORMAL, ""); + return originality_check_print(signature, signature_len, index); } static int mf_read_uid(uint8_t *uid, int *uidlen, int *nxptype) { diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 245fae293..ee8b537c9 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -45,6 +45,7 @@ #include "generator.h" #include "mifare/aiddesfire.h" #include "util.h" +#include "crypto/originality.h" #define MAX_KEY_LEN 24 #define MAX_KEYS_LIST_LEN 1024 @@ -442,61 +443,10 @@ int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, si PrintAndLogEx(DEBUG, "SIGNATURE=NULL"); return PM3_EINVARG; } - // ref: MIFARE Desfire Originality Signature Validation - // See tools/recover_pk.py to recover Pk from UIDs and signatures -#define PUBLIC_DESFIRE_ECDA_KEYLEN 57 - const ecdsa_publickey_t nxp_desfire_public_keys[] = { - {"NTAG424DNA, DESFire Ev2", "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"}, - {"NTAG413DNA, DESFire Ev1", "04BB5D514F7050025C7D0F397310360EEC91EAF792E96FC7E0F496CB4E669D414F877B7B27901FE67C2E3B33CD39D1C797715189AC951C2ADD"}, - {"DESFire Ev2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"}, - {"DESFire Ev3", "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"}, - {"NTAG424DNA, NTAG424DNATT, DESFire Light Ev2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3B"}, - {"DESFire Light", "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"}, - {"MIFARE Plus Ev1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}, - {"MIFARE Plus Ev2", "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"}, - {"DESFire Ev2 XL", "04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"}, - {"MIFARE Plus Troika", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}, - }; - - uint32_t i; - bool is_valid = false; - - for (i = 0; i < ARRAYLEN(nxp_desfire_public_keys); i++) { - - int dl = 0; - uint8_t key[PUBLIC_DESFIRE_ECDA_KEYLEN]; - param_gethex_to_eol(nxp_desfire_public_keys[i].value, 0, key, PUBLIC_DESFIRE_ECDA_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, uidlen, signature, signature_len, false); - is_valid = (res == 0); - if (is_valid) - break; - } -// PrintAndLogEx(NORMAL, ""); -// PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - if (is_valid == false || i == ARRAYLEN(nxp_desfire_public_keys)) { - 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_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 + 32); - 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 verification: " _GREEN_("successful")); - return PM3_SUCCESS; + int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFDES); + PrintAndLogEx(NORMAL, ""); + return originality_check_print(signature, signature_len, index); } static void swap24(uint8_t *data) { diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index d0d230e1f..218b87504 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -35,6 +35,7 @@ #include "crypto/libpcrypto.h" #include "cmdhfmf.h" // printblock, header #include "cmdtrace.h" +#include "crypto/originality.h" static const uint8_t mfp_default_key[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static uint16_t mfp_card_adresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0x9006, 0x9007, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; @@ -190,55 +191,9 @@ static nxp_cardtype_t getCardType(uint8_t type, uint8_t major, uint8_t minor) { // --- GET SIGNATURE static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) { - - // ref: MIFARE Plus EV1 Originality Signature Validation -#define PUBLIC_PLUS_ECDA_KEYLEN 57 - const ecdsa_publickey_t nxp_plus_public_keys[] = { - {"MIFARE Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}, - {"MIFARE Plus Ev2", "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"}, - {"MIFARE Plus Troika", "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"} - }; - - uint8_t i; - bool is_valid = false; - - for (i = 0; i < ARRAYLEN(nxp_plus_public_keys); i++) { - - int dl = 0; - uint8_t key[PUBLIC_PLUS_ECDA_KEYLEN]; - param_gethex_to_eol(nxp_plus_public_keys[i].value, 0, key, PUBLIC_PLUS_ECDA_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP224R1, key, uid, uidlen, signature, signature_len, false); - is_valid = (res == 0); - if (is_valid) - break; - } - + int index = originality_check_verify(uid, uidlen, signature, signature_len, PK_MFP); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - - if (is_valid == false || i == ARRAYLEN(nxp_plus_public_keys)) { - 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 + 32); - 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 verification: " _GREEN_("successful")); - return PM3_SUCCESS; + return originality_check_print(signature, signature_len, index); } static int get_plus_signature(uint8_t *signature, int *signature_len) { diff --git a/client/src/cmdhfmfu.c b/client/src/cmdhfmfu.c index 0b3554a62..fafcf2b78 100644 --- a/client/src/cmdhfmfu.c +++ b/client/src/cmdhfmfu.c @@ -35,6 +35,7 @@ #include "fileutils.h" // saveFile #include "cmdtrace.h" // trace list #include "preferences.h" // setDeviceDebugLevel +#include "crypto/originality.h" #define MAX_UL_BLOCKS 0x0F #define MAX_ULC_BLOCKS 0x2F @@ -1397,134 +1398,14 @@ static int ulev1_print_counters(void) { } static int ulev1_print_signature(uint64_t tagtype, uint8_t *uid, uint8_t *signature, size_t signature_len) { - -#define PUBLIC_ECDA_KEYLEN 33 -#define PUBLIC_ECDA_192_KEYLEN 49 - // 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 - const ecdsa_publickey_t nxp_mfu_public_keys[] = { - {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"}, - {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"}, - {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"}, - {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, - {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, - {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, - {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"}, - {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"}, - {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"}, - {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"}, - }; - - const ecdsa_publickey_t nxp_mfu_192_public_keys[] = { - // https://www.nxp.com/docs/en/application-note/AN13452.pdf - {"NXP Ultralight AES", "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"}, - // TagInfo - {"NXP Ultralight AES (alt key)", "04DC34DAA903F2726A6225B11C692AF6AB4396575CA12810CBBCE3F781A097B3833B50AB364A70D9C2B641A728A599AE74"}, - }; - - /* - 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; - bool is_valid = false; + int index = -1; if (signature_len == 32) { - for (i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) { - - int dl = 0; - uint8_t key[PUBLIC_ECDA_KEYLEN] = {0}; - param_gethex_to_eol(nxp_mfu_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, signature_len, false); - - is_valid = (res == 0); - if (is_valid) - break; - } + index = originality_check_verify(uid, 7, signature, signature_len, PK_MFUL); + } else if (signature_len == 48) { + index = originality_check_verify(uid, 7, signature, signature_len, PK_MFULAES); } - - bool is_192_valid = false; - if (signature_len == 48) { - for (i = 0; i < ARRAYLEN(nxp_mfu_192_public_keys); i++) { - int dl = 0; - uint8_t key[PUBLIC_ECDA_192_KEYLEN] = {0}; - param_gethex_to_eol(nxp_mfu_192_public_keys[i].value, 0, key, PUBLIC_ECDA_192_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP192R1, key, uid, 7, signature, signature_len, false); - - is_192_valid = (res == 0); - if (is_192_valid) - break; - } - } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - if (is_192_valid) { - PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%s"), nxp_mfu_192_public_keys[i].desc); - PrintAndLogEx(INFO, "IC signature public key value: %s", nxp_mfu_192_public_keys[i].value); - PrintAndLogEx(INFO, " Elliptic curve parameters: NID_secp192r1"); - PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )"); - return PM3_SUCCESS; - } - - if (is_valid) { - PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%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 verification ( " _GREEN_("successful") " )"); - return PM3_SUCCESS; - } - - PrintAndLogEx(INFO, " Elliptic curve parameters: %s", (signature_len == 48) ? "NID_secp192r1" : "NID_secp128r1"); - PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, signature_len)); - PrintAndLogEx(SUCCESS, " Signature verification ( " _RED_("fail") " )"); - return PM3_ESOFT; + return originality_check_print(signature, signature_len, index); } static int ulev1_print_version(uint8_t *data) { diff --git a/client/src/cmdhfst25ta.c b/client/src/cmdhfst25ta.c index 668d3d00d..fcf5791d0 100644 --- a/client/src/cmdhfst25ta.c +++ b/client/src/cmdhfst25ta.c @@ -33,6 +33,7 @@ #include "commonutil.h" // get_sw #include "protocols.h" // ISO7816 APDU return codes #include "crypto/libpcrypto.h" // ecdsa +#include "crypto/originality.h" #define TIMEOUT 2000 @@ -148,48 +149,9 @@ static void print_st25ta_system_info(uint8_t *d, uint8_t n) { } static int print_st25ta_signature(uint8_t *uid, uint8_t *signature) { - -#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 - const ecdsa_publickey_t nxp_mfu_public_keys[] = { - {"NXP MIFARE Classic MFC1C14_x", "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"}, - {"MIFARE Classic / QL88", "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"}, - {"NXP ICODE DNA, ICODE SLIX2", "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"}, - {"NXP Public key", "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, - {"NXP Ultralight Ev1", "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, - {"NXP NTAG21x (2013)", "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, - {"MIKRON Public key", "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"}, - {"VivoKey Spark1 Public key", "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"}, - {"TruST25 (ST) key 01?", "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"}, - {"TruST25 (ST) key 04?", "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"}, - }; - - for (uint8_t i = 0; i < ARRAYLEN(nxp_mfu_public_keys); i++) { - - int dl = 0; - uint8_t key[PUBLIC_ECDA_KEYLEN] = {0}; - param_gethex_to_eol(nxp_mfu_public_keys[i].value, 0, key, PUBLIC_ECDA_KEYLEN, &dl); - - int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, key, uid, 7, signature, 32, true); - - if (res == 0) { - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - - - PrintAndLogEx(INFO, " IC signature public key name: " _GREEN_("%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, 32)); - PrintAndLogEx(SUCCESS, " Signature verification ( " _GREEN_("successful") " )"); - return PM3_SUCCESS; - } - } - - return PM3_ESOFT; + int index = originality_check_verify_ex(uid, 7, signature, 32, PK_ST25, false, true); + PrintAndLogEx(NORMAL, ""); + return originality_check_print(signature, 32, index); } static int st25ta_get_signature(uint8_t *signature) { diff --git a/client/src/crypto/originality.c b/client/src/crypto/originality.c new file mode 100644 index 000000000..e3afa1f47 --- /dev/null +++ b/client/src/crypto/originality.c @@ -0,0 +1,171 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// originality checks with known pk +//----------------------------------------------------------------------------- + +#include "originality.h" +#include // memcpy +#include "ui.h" + +// See tools/recover_pk.py to recover Pk from UIDs and signatures +const ecdsa_publickey_ng_t manufacturer_public_keys[] = { + {PK_MFC, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP MIFARE Classic MFC1C14_x", + "044F6D3F294DEA5737F0F46FFEE88A356EED95695DD7E0C27A591E6F6F65962BAF"}, + {PK_MFC, MBEDTLS_ECP_DP_SECP128R1, 33, "MIFARE Classic / QL88", + "046F70AC557F5461CE5052C8E4A7838C11C7A236797E8A0730A101837C004039C2"}, + + // ref: TagInfo + // NTAG 210/212 ? not present in recover_pk + {PK_MFUL, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP Public key", + "04A748B6A632FBEE2C0897702B33BEA1C074998E17B84ACA04FF267E5D2C91F6DC"}, + // ref: AN11341 MIFARE Ultralight EV1 Originality Signature Validation + {PK_MFUL, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP Ultralight EV1", + "0490933BDCD6E99B4E255E3DA55389A827564E11718E017292FAF23226A96614B8"}, + // ref: AN11350 NTAG 21x Originality Signature Validation + {PK_MFUL, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP NTAG21x (2013)", + "04494E1A386D3D3CFE3DC10E5DE68A499B1C202DB5B132393E89ED19FE5BE8BC61"}, + + // ref: AN13452 MIFARE Ultralight AES features and hints + {PK_MFULAES, MBEDTLS_ECP_DP_SECP192R1, 49, "NXP Ultralight AES", + "0453BF8C49B7BD9FE3207A91513B9C1D238ECAB07186B772104AB535F7D3AE63CF7C7F3DD0D169DA3E99E43C6399621A86"}, + // ref: TagInfo + {PK_MFULAES, MBEDTLS_ECP_DP_SECP192R1, 49, "NXP Ultralight AES (alt key)", + "04DC34DAA903F2726A6225B11C692AF6AB4396575CA12810CBBCE3F781A097B3833B50AB364A70D9C2B641A728A599AE74"}, + + {PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus EV1", + "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"}, + // not present in recover_pk + {PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus EV2", + "04BB49AE4447E6B1B6D21C098C1538B594A11A4A1DBF3D5E673DEACDEB3CC512D1C08AFA1A2768CE20A200BACD2DC7804CD7523A0131ABF607"}, + {PK_MFP, MBEDTLS_ECP_DP_SECP224R1, 57, "MIFARE Plus Troika", + "040F732E0EA7DF2B38F791BF89425BF7DCDF3EE4D976669E3831F324FF15751BD52AFF1782F72FF2731EEAD5F63ABE7D126E03C856FFB942AF"}, + + // ref: AN12343 MIFARE DESFire Light Features and Hints + // not present in recover_pk + {PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "DESFire Light", + "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"}, + {PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "NTAG413DNA, DESFire EV1", + "04BB5D514F7050025C7D0F397310360EEC91EAF792E96FC7E0F496CB4E669D414F877B7B27901FE67C2E3B33CD39D1C797715189AC951C2ADD"}, + {PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "NTAG424DNA, NTAG424DNATT, DESFire EV2, DESFire Light EV2", + "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3A"}, + // ref: AN12196 NTAG 424 DNA and NTAG 424 DNA TagTamper features and hints + {PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "NTAG424DNA, DESFire EV2", + "048A9B380AF2EE1B98DC417FECC263F8449C7625CECE82D9B916C992DA209D68422B81EC20B65A66B5102A61596AF3379200599316A00A1410"}, + {PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "DESFire EV2 XL", + "04CD5D45E50B1502F0BA4656FF37669597E7E183251150F9574CC8DA56BF01C7ABE019E29FEA48F9CE22C3EA4029A765E1BC95A89543BAD1BC"}, + {PK_MFDES, MBEDTLS_ECP_DP_SECP224R1, 57, "DESFire EV3", + "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"}, + + {PK_ST25, MBEDTLS_ECP_DP_SECP128R1, 33, "ST25TA TruST25 (ST) key 01?", + "041D92163650161A2548D33881C235D0FB2315C2C31A442F23C87ACF14497C0CBA"}, +// FIXME: need to implement support for ST25TN signature check. hash=sha256 - from block 52, followed by ascii UID + {PK_ST25, MBEDTLS_ECP_DP_SECP128R1, 33, "ST25TN TruST25 (ST) key 05?", + "0440004F974F7C76BC8718E523D85FA7B354A9A992BFA966CB8219242F9D274FD6"}, +// FIXME: need to implement support for ST25TV signature check. hash=sha256 - from block 63, starting with KeyID ? + {PK_ST25, MBEDTLS_ECP_DP_SECP128R1, 33, "ST25TV TruST25 (ST) key 04?", + "04101E188A8B4CDDBC62D5BC3E0E6850F0C2730E744B79765A0E079907FBDB01BC"}, + + {PK_15, MBEDTLS_ECP_DP_SECP128R1, 33, "NXP ICODE DNA, ICODE SLIX2", + "048878A2A2D3EEC336B4F261A082BD71F9BE11C4E2E896648B32EFA59CEA6E59F0"}, + {PK_15, MBEDTLS_ECP_DP_SECP128R1, 33, "VivoKey Spark1 Public key", + "04D64BB732C0D214E7EC580736ACF847284B502C25C0F7F2FA86AACE1DADA4387A"}, + +// FIXME: what type(s) of card exactly? MFC? MFUL? not present in recover_pk + {PK_MIK, MBEDTLS_ECP_DP_SECP128R1, 33, "MIKRON Public key", + "04F971EDA742A4A80D32DCF6A814A707CC3DC396D35902F72929FDCD698B3468F2"}, +}; + + +// return pk if match index else -1 +int originality_check_verify(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type) { + return originality_check_verify_ex(data, data_len, signature, signature_len, type, false, false); +} + +int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type, bool reverse, bool hash) { + // test if signature is null + bool is_zero = true; + for (uint8_t i = 0; i < signature_len; i++) { + if (signature[i] != 0) { + is_zero = false; + } + } + if (is_zero) { + return -1; + } + + uint8_t tmp_data[data_len]; + uint8_t tmp_signature[signature_len]; + if (reverse) { + reverse_array_copy(data, data_len, tmp_data); + reverse_array_copy(signature, signature_len, tmp_signature); + } else { + memcpy(tmp_data, data, data_len); + memcpy(tmp_signature, signature, signature_len); + } + + for (uint8_t i = 0; i < ARRAYLEN(manufacturer_public_keys); i++) { + if ((type != PK_ALL) && (type != manufacturer_public_keys[i].type)) + continue; + int dl = 0; + uint8_t key[manufacturer_public_keys[i].keylen]; + param_gethex_to_eol(manufacturer_public_keys[i].value, 0, key, manufacturer_public_keys[i].keylen, &dl); + if (ecdsa_signature_r_s_verify(manufacturer_public_keys[i].grp_id, key, tmp_data, data_len, tmp_signature, signature_len, hash) == 0) + return i; + } + return -1; +} + +int originality_check_print(uint8_t *signature, int signature_len, int index) { + if ((index < 0) || (index >= ARRAYLEN(manufacturer_public_keys))) { + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16)); + if (signature_len > 16) { + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16)); + } + if (signature_len > 32) { + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16)); + } + if (signature_len > 48) { + 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"), manufacturer_public_keys[index].desc); + PrintAndLogEx(INFO, "IC signature public key value: %.32s", manufacturer_public_keys[index].value); + if (manufacturer_public_keys[index].keylen > 16) { + PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 32); + } + if (manufacturer_public_keys[index].keylen > 32) { + PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 64); + } + if (manufacturer_public_keys[index].keylen > 48) { + PrintAndLogEx(INFO, " : %.32s", manufacturer_public_keys[index].value + 96); + } + PrintAndLogEx(INFO, " Elliptic curve parameters: %s", mbedtls_ecp_curve_info_from_grp_id(manufacturer_public_keys[index].grp_id)->name); + PrintAndLogEx(INFO, " TAG IC Signature: %s", sprint_hex_inrow(signature, 16)); + if (signature_len > 16) { + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 16, 16)); + } + if (signature_len > 32) { + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 32, 16)); + } + if (signature_len > 48) { + PrintAndLogEx(INFO, " : %s", sprint_hex_inrow(signature + 48, signature_len - 48)); + } + PrintAndLogEx(SUCCESS, " Signature verification: " _GREEN_("successful")); + return PM3_SUCCESS; +} diff --git a/client/src/crypto/originality.h b/client/src/crypto/originality.h new file mode 100644 index 000000000..e6e8e5b4b --- /dev/null +++ b/client/src/crypto/originality.h @@ -0,0 +1,42 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// originality checks with known pk +//----------------------------------------------------------------------------- + +#ifndef ORIGINALITY_H +#define ORIGINALITY_H + +#include "common.h" +#include "commonutil.h" +#include "libpcrypto.h" +#include +#include + +typedef enum {PK_MFC, PK_MFUL, PK_MFULAES, PK_MFP, PK_MFDES, PK_ST25, PK_15, PK_MIK, PK_ALL} pk_type_t; + +typedef struct { + const pk_type_t type; + const mbedtls_ecp_group_id grp_id; + const uint8_t keylen; + const char *desc; + const char *value; +} PACKED ecdsa_publickey_ng_t; + +int originality_check_verify(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type); +int originality_check_verify_ex(uint8_t *data, uint8_t data_len, uint8_t *signature, uint8_t signature_len, pk_type_t type, bool reverse, bool hash); +int originality_check_print(uint8_t *signature, int signature_len, int index); + +#endif /* originality.h */