From 0e2d7037db4048dbf1c194508c07384a818261d5 Mon Sep 17 00:00:00 2001 From: Yi Wu Date: Thu, 28 May 2026 15:10:14 +0100 Subject: [PATCH 1/3] Backport EC public key 1 byte overread Signed-off-by: Yi Wu --- ChangeLog.d/mbedtls_pk_ecc_set_pubkey.txt | 3 +++ library/pk_ecc.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 ChangeLog.d/mbedtls_pk_ecc_set_pubkey.txt diff --git a/ChangeLog.d/mbedtls_pk_ecc_set_pubkey.txt b/ChangeLog.d/mbedtls_pk_ecc_set_pubkey.txt new file mode 100644 index 0000000000..44906298da --- /dev/null +++ b/ChangeLog.d/mbedtls_pk_ecc_set_pubkey.txt @@ -0,0 +1,3 @@ +Security + * Fix a 1-byte buffer overread when parsing a malformed ECC public key + in the PK module. diff --git a/library/pk_ecc.c b/library/pk_ecc.c index 86218fffc8..20fe953d01 100644 --- a/library/pk_ecc.c +++ b/library/pk_ecc.c @@ -205,13 +205,19 @@ int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, { #if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + /* We need to read the first byte to determine the format (compressed, + * uncompressed or 0). */ + if (pub_len == 0) { + return MBEDTLS_ERR_PK_INVALID_PUBKEY; + } + /* Load the key */ if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) { /* Format directly supported by PSA: * - non-Weierstrass curves that only have one format; * - uncompressed format for Weierstrass curves. */ if (pub_len > sizeof(pk->pub_raw)) { - return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL; + return MBEDTLS_ERR_PK_INVALID_PUBKEY; } memcpy(pk->pub_raw, pub, pub_len); pk->pub_raw_len = pub_len; From 94883a3a851c9022dbf3c0de5947db9f0acf7059 Mon Sep 17 00:00:00 2001 From: Yi Wu Date: Thu, 28 May 2026 15:10:31 +0100 Subject: [PATCH 2/3] tests: add EC public key parser coverage Signed-off-by: Yi Wu --- tests/suites/test_suite_pkparse.data | 109 +++++++++++++++++++++++ tests/suites/test_suite_pkparse.function | 49 +++++++++- 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data index 47b3750ada..f149c441ec 100644 --- a/tests/suites/test_suite_pkparse.data +++ b/tests/suites/test_suite_pkparse.data @@ -2002,6 +2002,115 @@ pk_parse_public_keyfile_rsa:"../framework/data_files/rsa_pkcs1_2048_public.pem": Parse Public RSA Key #4 (PKCS#1 wrapped, DER) pk_parse_public_keyfile_rsa:"../framework/data_files/rsa_pkcs1_2048_public.der":0 +Parse Public EC Key: secp256r1, nominal, DER (RFC 5480) +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3059301306072a8648ce3d020106082a8648ce3d030107034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":0:0 + +Parse Public EC Key: secp256r1, compressed (supported) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3039301306072a8648ce3d020106082a8648ce3d030107032200037772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b57":0:0 + +Parse Public EC Key: secp256r1, compressed (not supported) +depends_on:PSA_WANT_ECC_SECP_R1_256:!MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3039301306072a8648ce3d020106082a8648ce3d030107032200037772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b57":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE + +# Odd length of (x,y) coordinate pair +Parse Public EC Key: secp256r1, truncated BIT STRING (-1, uncompressed) +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3058301306072a8648ce3d020106082a8648ce3d030107034100047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +# Even length of (x,y) coordinate pair +Parse Public EC Key: secp256r1, truncated BIT STRING (-2, uncompressed) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_RSA_C +pk_parse_public_key_ec:"3057301306072a8648ce3d020106082a8648ce3d030107034000047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de":MBEDTLS_ERR_RSA_BAD_INPUT_DATA:MBEDTLS_ERR_RSA_BAD_INPUT_DATA + +# Single coordinate too short +Parse Public EC Key: secp256r1, truncated BIT STRING (-1, compressed) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3038301306072a8648ce3d020106082a8648ce3d030107032100037772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, 1-byte BIT STRING (00, compressed supported) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3019301306072a8648ce3d020106082a8648ce3d03010703020000":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_INVALID_KEY + +Parse Public EC Key: secp256r1, 1-byte BIT STRING (01, compressed supported) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3019301306072a8648ce3d020106082a8648ce3d03010703020001":MBEDTLS_ERR_ECP_BAD_INPUT_DATA:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, 1-byte BIT STRING (02, compressed supported) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3019301306072a8648ce3d020106082a8648ce3d03010703020002":MBEDTLS_ERR_ECP_BAD_INPUT_DATA:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, 1-byte BIT STRING (03, compressed supported) +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3019301306072a8648ce3d020106082a8648ce3d03010703020003":MBEDTLS_ERR_ECP_BAD_INPUT_DATA:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, 1-byte BIT STRING (04) +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3019301306072a8648ce3d020106082a8648ce3d03010703020004":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, 1-byte BIT STRING (00, unsupported) +depends_on:PSA_WANT_ECC_SECP_R1_256:!MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3019301306072a8648ce3d020106082a8648ce3d03010703020000":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE + +Parse Public EC Key: secp256r1, empty BIT STRING +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3018301306072a8648ce3d020106082a8648ce3d030107030100":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +# Odd length of (x,y) coordinate pair +Parse Public EC Key: secp256r1, overly long BIT STRING (+1, uncompressed) +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"305a301306072a8648ce3d020106082a8648ce3d030107034300047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de4543":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +# Even length of (x,y) coordinate pair +Parse Public EC Key: secp256r1, overly long BIT STRING (+2, uncompressed) +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"305b301306072a8648ce3d020106082a8648ce3d030107034400047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de454343":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, extremely long BIT STRING (uncompressed) +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3081da301306072a8648ce3d020106082a8648ce3d0301070381c20004787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979797979":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: secp256r1, uncompressed, X out of range +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3059301306072a8648ce3d020106082a8648ce3d03010703420004ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_INVALID_KEY + +Parse Public EC Key: secp256r1, uncompressed, Y out of range +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3059301306072a8648ce3d020106082a8648ce3d030107034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b57ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_INVALID_KEY + +Parse Public EC Key: secp256r1, uncompressed, not on curve +depends_on:PSA_WANT_ECC_SECP_R1_256 +pk_parse_public_key_ec:"3059301306072a8648ce3d020106082a8648ce3d030107034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de46":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_INVALID_KEY + +Parse Public EC Key: secp256r1, compressed, X out of range +depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_PARSE_EC_COMPRESSED +pk_parse_public_key_ec:"3039301306072a8648ce3d020106082a8648ce3d03010703220003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_INVALID_KEY + +Parse Public EC Key: X25519, nominal, DER (RFC 8410) +depends_on:PSA_WANT_ECC_MONTGOMERY_255 +pk_parse_public_key_ec:"302a300506032b656e0321009bc3b0e93d8233fe6a8ba6138948cc12a91362d5c2ed81584db05ab5419c9d11":0:0 + +Parse Public EC Key: X25519, truncated BIT STRING (-1) +depends_on:PSA_WANT_ECC_MONTGOMERY_255 +pk_parse_public_key_ec:"3029300506032b656e0320009bc3b0e93d8233fe6a8ba6138948cc12a91362d5c2ed81584db05ab5419c9d":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: X25519, 1-byte BIT STRING +depends_on:PSA_WANT_ECC_MONTGOMERY_255 +pk_parse_public_key_ec:"300b300506032b656e0302009b":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: X25519, empty BIT STRING +depends_on:PSA_WANT_ECC_MONTGOMERY_255 +pk_parse_public_key_ec:"300a300506032b656e030100":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: X25519, overly long BIT STRING (+1) +depends_on:PSA_WANT_ECC_MONTGOMERY_255 +pk_parse_public_key_ec:"302b300506032b656e0322009bc3b0e93d8233fe6a8ba6138948cc12a91362d5c2ed81584db05ab5419c9d1143":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + +Parse Public EC Key: X25519, extremely long BIT STRING +depends_on:PSA_WANT_ECC_MONTGOMERY_255 +pk_parse_public_key_ec:"3081cc300506032b656e0381c20065656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565":MBEDTLS_ERR_PK_INVALID_PUBKEY:MBEDTLS_ERR_ECP_BAD_INPUT_DATA + Parse Public EC Key #1 (RFC 5480, DER) depends_on:MBEDTLS_ECP_HAVE_SECP192R1 pk_parse_public_keyfile_ec:"../framework/data_files/ec_pub.der":0 diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function index 942dae388a..0ba5114135 100644 --- a/tests/suites/test_suite_pkparse.function +++ b/tests/suites/test_suite_pkparse.function @@ -4,6 +4,7 @@ #include "mbedtls/oid.h" #include "mbedtls/ecp.h" #include "mbedtls/psa_util.h" +#include "mbedtls/rsa.h" #include "pk_internal.h" #if defined(MBEDTLS_PSA_CRYPTO_C) @@ -14,7 +15,7 @@ #define HAVE_mbedtls_pk_parse_key_pkcs8_encrypted_der #endif -#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_FS_IO) +#if defined(MBEDTLS_PSA_CRYPTO_C) static int test_psa_bridge(const mbedtls_pk_context *ctx, psa_key_usage_t usage_flag) { @@ -101,7 +102,7 @@ static int pk_can_ecdsa(const mbedtls_pk_context *ctx) #endif } #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */ -#endif /* MBEDTLS_PSA_CRYPTO_C && && MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PSA_CRYPTO_C */ /* END_HEADER */ @@ -194,6 +195,50 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ +void pk_parse_public_key_ec(data_t *key_data, + int result_psa, + int result_legacy) +{ + mbedtls_pk_context ctx; + mbedtls_pk_init(&ctx); + int res; +#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) + int result = result_psa; + (void) result_legacy; +#else + int result = result_legacy; + (void) result_psa; +#endif + unsigned char *key_copy = NULL; + + MD_OR_USE_PSA_INIT(); + TEST_CALLOC(key_copy, key_data->len); + memcpy(key_copy, key_data->x, key_data->len); + + res = mbedtls_pk_parse_public_key(&ctx, key_copy, key_data->len); + + TEST_EQUAL(res, result); + + if (res == 0) { + TEST_ASSERT(mbedtls_pk_can_do(&ctx, MBEDTLS_PK_ECKEY)); + +#if defined(MBEDTLS_PSA_CRYPTO_C) + PSA_INIT(); + if (pk_can_ecdsa(&ctx)) { + TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_HASH)); + TEST_ASSERT(test_psa_bridge(&ctx, PSA_KEY_USAGE_VERIFY_MESSAGE)); + } +#endif + } + +exit: + mbedtls_pk_free(&ctx); + PSA_DONE(); + mbedtls_free(key_copy); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_PK_HAVE_ECC_KEYS */ void pk_parse_public_keyfile_ec(char *key_file, int result) { From 3208173d3d6728b6d1eb25a1a448067c781cbb69 Mon Sep 17 00:00:00 2001 From: Yi Wu Date: Thu, 28 May 2026 15:10:45 +0100 Subject: [PATCH 3/3] tests: update compressed EC outcome filters Signed-off-by: Yi Wu --- tests/scripts/analyze_outcomes.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py index 9bf01248ae..83264b85ea 100755 --- a/tests/scripts/analyze_outcomes.py +++ b/tests/scripts/analyze_outcomes.py @@ -449,8 +449,8 @@ class DriverVSReference_no_ecp_at_all(outcome_analysis.DriverVSReference): # consequence compressed points are supported in the reference # component but not in the accelerated one, so they should be skipped # while checking driver's coverage. - re.compile(r'Parse EC Key .*compressed\)'), - re.compile(r'Parse Public EC Key .*compressed\)'), + re.compile(r'Parse EC Key .*(?