diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index f2bc5f4405f..8a6943251c5 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -1905,8 +1905,65 @@ int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, if (!wrapper) { return -1; } - psa_status_t status = psa_verify_hash(wrapper->key_id, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), data, len, sig, sig_len); + + /* Get key attributes to extract key_bits needed for DER-to-raw conversion */ + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = psa_get_key_attributes(wrapper->key_id, &key_attributes); if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "crypto_ec_key_verify_signature: psa_get_key_attributes failed: %d", status); + psa_reset_key_attributes(&key_attributes); + return -1; + } + + size_t key_bits = psa_get_key_bits(&key_attributes); + psa_reset_key_attributes(&key_attributes); + + /* Determine hash algorithm from data length */ + psa_algorithm_t verify_alg; + if (len == 32) { + verify_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256); + } else if (len == 48) { + verify_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384); + } else if (len == 64) { + verify_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512); + } else if (len == 20) { + verify_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_1); + } else { + wpa_printf(MSG_ERROR, "crypto_ec_key_verify_signature: Unsupported hash length %d", (int)len); + return -1; + } + + /* Convert DER-encoded signature to raw format (r||s) for PSA */ + /* PSA verify_hash expects raw format, not DER format */ + /* API specification requires DER format input */ + /* Raw signature length = 2 * PSA_BITS_TO_BYTES(key_bits), max 132 bytes for P-521 */ + unsigned char raw_sig[132]; + size_t raw_sig_len = 0; + const u8 *sig_to_verify = sig; + size_t sig_len_to_verify = sig_len; + + /* Check if signature is DER format (starts with 0x30) */ + if (sig_len > 0 && sig[0] == 0x30) { + /* Convert DER to raw format */ + int ret = mbedtls_ecdsa_der_to_raw(key_bits, sig, sig_len, + raw_sig, sizeof(raw_sig), &raw_sig_len); + if (ret != 0) { + wpa_printf(MSG_ERROR, "crypto_ec_key_verify_signature: Failed to convert DER to raw format: %d", ret); + return -1; + } + sig_to_verify = raw_sig; + sig_len_to_verify = raw_sig_len; + } else { + /* Signature must be in DER format as per API specification */ + wpa_printf(MSG_ERROR, "crypto_ec_key_verify_signature: Invalid signature format (expected DER, got 0x%02x)", sig_len > 0 ? sig[0] : 0); + return -1; + } + + /* Perform signature verification */ + status = psa_verify_hash(wrapper->key_id, verify_alg, + data, len, sig_to_verify, sig_len_to_verify); + if (status != PSA_SUCCESS) { + wpa_printf(MSG_ERROR, "crypto_ec_key_verify_signature: psa_verify_hash failed: %d", status); return -1; } diff --git a/components/wpa_supplicant/test_apps/main/test_crypto.c b/components/wpa_supplicant/test_apps/main/test_crypto.c index ea6a279be4d..3141c1e423f 100644 --- a/components/wpa_supplicant/test_apps/main/test_crypto.c +++ b/components/wpa_supplicant/test_apps/main/test_crypto.c @@ -27,6 +27,11 @@ typedef struct crypto_bignum crypto_bignum; +/* Minimal structure to access key_id from crypto_ec_key wrapper (for test purposes) */ +typedef struct { + psa_key_id_t key_id; +} crypto_ec_key_wrapper_test_t; + TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") { set_leak_threshold(300); @@ -831,12 +836,28 @@ TEST_CASE("Test crypto lib ecdsa apis", "[wpa_crypto]") ret = crypto_bignum_to_bin(s, s_buf, sizeof(s_buf), 32); TEST_ASSERT(ret == 32); - /* Construct signature as r||s */ + /* Construct signature as r||s (raw format) */ memcpy(signature, r_buf, 32); memcpy(signature + 32, s_buf, 32); + /* Convert raw signature to DER format as required by crypto_ec_key_verify_signature API */ + /* Get key bits from the key object */ + crypto_ec_key_wrapper_test_t *key_wrapper = (crypto_ec_key_wrapper_test_t *)eckey; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = psa_get_key_attributes(key_wrapper->key_id, &key_attributes); + TEST_ASSERT(status == PSA_SUCCESS); + size_t key_bits = psa_get_key_bits(&key_attributes); + psa_reset_key_attributes(&key_attributes); + TEST_ASSERT(key_bits > 0); + + uint8_t der_sig[MBEDTLS_ECDSA_DER_MAX_SIG_LEN(key_bits)]; + size_t der_sig_len = 0; + ret = mbedtls_ecdsa_raw_to_der(key_bits, signature, 64, der_sig, sizeof(der_sig), &der_sig_len); + TEST_ASSERT(ret == 0); + TEST_ASSERT(der_sig_len > 0); + uint8_t expected_data[64] = {[0 ... 63] = 0xA5}; - ret = crypto_ec_key_verify_signature(eckey, expected_data, 64, signature, 64); + ret = crypto_ec_key_verify_signature(eckey, expected_data, 64, der_sig, der_sig_len); TEST_ASSERT(ret == 1); /* Returns 1 on success */ ret = crypto_ec_key_verify_signature_r_s(eckey, expected_data, 64, r_buf, 32, s_buf, 32); @@ -844,7 +865,7 @@ TEST_CASE("Test crypto lib ecdsa apis", "[wpa_crypto]") // Negative test case expected_data[0] = 0x5A; - ret = crypto_ec_key_verify_signature(eckey, expected_data, 64, signature, 64); + ret = crypto_ec_key_verify_signature(eckey, expected_data, 64, der_sig, der_sig_len); TEST_ASSERT(ret == -1); crypto_bignum_deinit(r, 1); @@ -1339,12 +1360,28 @@ TEST_CASE("Test crypto lib ecdh apis", "[wpa_crypto]") ret = crypto_bignum_to_bin(s, s_buf, sizeof(s_buf), 32); TEST_ASSERT(ret == 32); - /* Construct signature as r||s */ + /* Construct signature as r||s (raw format) */ memcpy(signature, r_buf, 32); memcpy(signature + 32, s_buf, 32); + /* Convert raw signature to DER format as required by crypto_ec_key_verify_signature API */ + /* Get key bits from the key object */ + crypto_ec_key_wrapper_test_t *key_wrapper = (crypto_ec_key_wrapper_test_t *)key; + psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status = psa_get_key_attributes(key_wrapper->key_id, &key_attributes); + TEST_ASSERT(status == PSA_SUCCESS); + size_t key_bits = psa_get_key_bits(&key_attributes); + psa_reset_key_attributes(&key_attributes); + TEST_ASSERT(key_bits > 0); + + uint8_t der_sig[MBEDTLS_ECDSA_DER_MAX_SIG_LEN(key_bits)]; + size_t der_sig_len = 0; + ret = mbedtls_ecdsa_raw_to_der(key_bits, signature, 64, der_sig, sizeof(der_sig), &der_sig_len); + TEST_ASSERT(ret == 0); + TEST_ASSERT(der_sig_len > 0); + /* Verify the signature */ - ret = crypto_ec_key_verify_signature(key, data, 64, signature, 64); + ret = crypto_ec_key_verify_signature(key, data, 64, der_sig, der_sig_len); TEST_ASSERT(ret == 1); /* Returns 1 on success */ /* Now test ECDH with the same key */