mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
fix: revert back to using mbedtls sha implementation for espcoredump
This commit is contained in:
@@ -755,7 +755,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
config IDF_EXPERIMENTAL_FEATURES
|
||||
bool "Make experimental features visible"
|
||||
default "y"
|
||||
default "n"
|
||||
help
|
||||
By enabling this option, ESP-IDF experimental feature options will be visible.
|
||||
|
||||
@@ -772,4 +772,3 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
|
||||
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
|
||||
- CONFIG_I3C_MASTER_ENABLED
|
||||
- CONFIG_MBEDTLS_VER_4_X_SUPPORT
|
||||
|
||||
@@ -89,10 +89,9 @@ extern "C" {
|
||||
typedef uint32_t core_dump_crc_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Use ESP32 ROM SHA context directly to avoid malloc during panic handler.
|
||||
* ESP32 ROM SHA has a different context structure than other targets. */
|
||||
#include "rom/sha.h"
|
||||
typedef SHA_CTX sha256_ctx_t;
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#include "mbedtls/private/sha256.h"
|
||||
typedef mbedtls_sha256_context sha256_ctx_t;
|
||||
#else
|
||||
#include "hal/sha_types.h" /* SHA_CTX */
|
||||
typedef SHA_CTX sha256_ctx_t;
|
||||
|
||||
@@ -20,31 +20,21 @@ uint32_t esp_core_dump_elf_version(void) __attribute__((alias("core_dump_sha_ver
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#include "rom/sha.h"
|
||||
|
||||
/* Use ESP32 ROM SHA hardware directly to avoid malloc during panic handler.
|
||||
* PSA driver allocates memory which is unsafe during panic handling.
|
||||
* ESP32 ROM SHA API uses bits instead of bytes and has a different context structure. */
|
||||
static void core_dump_sha256_start(core_dump_sha_ctx_t *sha_ctx)
|
||||
{
|
||||
SHA_CTX *ctx = (SHA_CTX *)&sha_ctx->ctx;
|
||||
/* Initialize context to zero */
|
||||
memset(ctx, 0, sizeof(SHA_CTX));
|
||||
ets_sha_enable();
|
||||
ets_sha_init(ctx);
|
||||
mbedtls_sha256_init(&sha_ctx->ctx);
|
||||
mbedtls_sha256_starts(&sha_ctx->ctx, false);
|
||||
}
|
||||
|
||||
static void core_dump_sha256_update(core_dump_sha_ctx_t *sha_ctx, const void *data, size_t data_len)
|
||||
{
|
||||
SHA_CTX *ctx = (SHA_CTX *)&sha_ctx->ctx;
|
||||
/* ESP32 ROM SHA update takes input_bits, not bytes */
|
||||
ets_sha_update(ctx, SHA2_256, (const uint8_t *)data, data_len * 8);
|
||||
mbedtls_sha256_update(&sha_ctx->ctx, data, data_len);
|
||||
}
|
||||
|
||||
static void core_dump_sha256_finish(core_dump_sha_ctx_t *sha_ctx)
|
||||
{
|
||||
SHA_CTX *ctx = (SHA_CTX *)&sha_ctx->ctx;
|
||||
ets_sha_finish(ctx, SHA2_256, sha_ctx->result);
|
||||
ets_sha_disable();
|
||||
mbedtls_sha256_finish(&sha_ctx->ctx, sha_ctx->result);
|
||||
mbedtls_sha256_free(&sha_ctx->ctx);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_core_dump_types.h"
|
||||
#include "core_dump_checksum.h"
|
||||
|
||||
/* Global variables that should be part of the coredump */
|
||||
COREDUMP_IRAM_DATA_ATTR uint32_t var_iram = 0x42;
|
||||
@@ -66,54 +64,3 @@ TEST_CASE("test variables presence in core dump sections", "[espcoredump]")
|
||||
TEST_ASSERT(is_addr_in_region(&var_rtcfast, (uint8_t *) section_start, section_size));
|
||||
#endif // SOC_RTC_MEM_SUPPORTED
|
||||
}
|
||||
|
||||
/*
|
||||
* This section tests the SHA256 checksum functionality for the espcoredump component
|
||||
*/
|
||||
TEST_CASE("espcoredump SHA256 checksum API", "[espcoredump]")
|
||||
{
|
||||
#define SHA256_RESULT_LEN 32
|
||||
ESP_LOGI("espcoredump", "Testing SHA256 checksum API");
|
||||
|
||||
/* Known test vector for SHA-256 */
|
||||
static const char *test_str = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
static const uint8_t expected_sha[SHA256_RESULT_LEN] = {
|
||||
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
|
||||
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
|
||||
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
|
||||
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
|
||||
};
|
||||
|
||||
// Verify size and version
|
||||
#if CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
TEST_ASSERT_EQUAL(SHA256_RESULT_LEN, esp_core_dump_checksum_size());
|
||||
#endif // CONFIG_ESP_COREDUMP_CHECKSUM_SHA256
|
||||
|
||||
#if CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
TEST_ASSERT_EQUAL(COREDUMP_VERSION_ELF_SHA256, esp_core_dump_elf_version());
|
||||
#endif // CONFIG_ESP_COREDUMP_DATA_FORMAT_ELF
|
||||
|
||||
// Test both single update and multiple updates with the same input
|
||||
checksum_ctx_t sha_ctx1, sha_ctx2;
|
||||
core_dump_checksum_bytes checksum1, checksum2;
|
||||
|
||||
// Test 1: Multiple updates (split string)
|
||||
const char *part1 = "abcdbc";
|
||||
const char *part2 = "decdefdefgefgh";
|
||||
const char *part3 = "fghighijhijkijkljklmklmnlmnomnopnopq";
|
||||
|
||||
esp_core_dump_checksum_init(&sha_ctx1);
|
||||
esp_core_dump_checksum_update(&sha_ctx1, (void*)part1, strlen(part1));
|
||||
esp_core_dump_checksum_update(&sha_ctx1, (void*)part2, strlen(part2));
|
||||
esp_core_dump_checksum_update(&sha_ctx1, (void*)part3, strlen(part3));
|
||||
esp_core_dump_checksum_finish(&sha_ctx1, &checksum1);
|
||||
|
||||
// Test 2: Single update (whole string)
|
||||
esp_core_dump_checksum_init(&sha_ctx2);
|
||||
esp_core_dump_checksum_update(&sha_ctx2, (void*)test_str, strlen(test_str));
|
||||
esp_core_dump_checksum_finish(&sha_ctx2, &checksum2);
|
||||
|
||||
// Check against known vector and ensure both methods match
|
||||
TEST_ASSERT_EQUAL_MEMORY(expected_sha, checksum1, SHA256_RESULT_LEN);
|
||||
TEST_ASSERT_EQUAL_MEMORY(checksum1, checksum2, SHA256_RESULT_LEN);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ def test_coredump(dut: Dut) -> None:
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
|
||||
@@ -3,12 +3,8 @@ menu "mbedTLS"
|
||||
menu "Core Configuration"
|
||||
|
||||
config MBEDTLS_VER_4_X_SUPPORT
|
||||
depends on IDF_EXPERIMENTAL_FEATURES
|
||||
bool "Enable support for mbedTLS version 4.x and the PSA cryptography API for ESP-IDF"
|
||||
bool
|
||||
default y
|
||||
help
|
||||
Enable support for mbedTLS version 4.x and the PSA cryptography API for ESP-IDF.
|
||||
This option migrates from mbedtls API to PSA Crypto API. This increases code size and is experimental.
|
||||
|
||||
choice MBEDTLS_COMPILER_OPTIMIZATION
|
||||
prompt "Compiler optimization level"
|
||||
|
||||
Submodule components/mbedtls/mbedtls updated: ee7b45e4fe...66753bb91f
@@ -3061,7 +3061,7 @@ under the driver abstraction layer */
|
||||
* This module is required for the SSL/TLS 1.2 PRF function.
|
||||
*/
|
||||
#ifdef CONFIG_MBEDTLS_SHA256_C
|
||||
// #define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define PSA_WANT_ALG_SHA_256 1
|
||||
#define PSA_WANT_ALG_SHA_224 1
|
||||
#else
|
||||
@@ -3083,7 +3083,7 @@ under the driver abstraction layer */
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
|
||||
#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_256
|
||||
#undef MBEDTLS_SHA1_C
|
||||
#undef MBEDTLS_SHA256_C
|
||||
// #undef MBEDTLS_SHA256_C
|
||||
#undef MBEDTLS_SHA224_C
|
||||
#if SOC_SHA_SUPPORT_SHA512
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_SHA_512
|
||||
|
||||
@@ -257,26 +257,21 @@ int nvs_bootloader_aes_crypt_xts(nvs_bootloader_xts_aes_context *ctx,
|
||||
|
||||
#endif /* CONFIG_ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB */
|
||||
#else /* BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER */
|
||||
#include "psa/crypto.h"
|
||||
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
|
||||
#include "mbedtls/private/aes.h"
|
||||
|
||||
static const char *TAG = "nvs_bootloader_xts_aes";
|
||||
|
||||
static psa_cipher_operation_t operation;
|
||||
static psa_key_id_t nvs_bootloader_xts_aes_key_id = 0;
|
||||
static mbedtls_aes_xts_context ctx_xts;
|
||||
|
||||
void nvs_bootloader_xts_aes_init(nvs_bootloader_xts_aes_context *ctx)
|
||||
{
|
||||
(void) ctx;
|
||||
// mbedtls_aes_xts_init(&ctx_xts);
|
||||
// psa_status_t status = PSA_SUCCESS;
|
||||
mbedtls_aes_xts_init(&ctx_xts);
|
||||
}
|
||||
|
||||
void nvs_bootloader_xts_aes_free(nvs_bootloader_xts_aes_context *ctx)
|
||||
{
|
||||
(void) ctx;
|
||||
psa_cipher_abort(&operation);
|
||||
psa_destroy_key(nvs_bootloader_xts_aes_key_id);
|
||||
nvs_bootloader_xts_aes_key_id = 0;
|
||||
mbedtls_aes_xts_free(&ctx_xts);
|
||||
}
|
||||
|
||||
int nvs_bootloader_xts_aes_setkey(nvs_bootloader_xts_aes_context *ctx,
|
||||
@@ -284,32 +279,7 @@ int nvs_bootloader_xts_aes_setkey(nvs_bootloader_xts_aes_context *ctx,
|
||||
unsigned int key_bytes)
|
||||
{
|
||||
(void) ctx;
|
||||
// return mbedtls_aes_xts_setkey_dec(&ctx_xts, key, key_bytes * 8);
|
||||
psa_status_t status;
|
||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
|
||||
psa_set_key_algorithm(&key_attributes, PSA_ALG_XTS);
|
||||
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
|
||||
psa_set_key_bits(&key_attributes, key_bytes * 8);
|
||||
status = psa_import_key(&key_attributes, key, key_bytes, &nvs_bootloader_xts_aes_key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to import key: %d", status);
|
||||
psa_cipher_abort(&operation);
|
||||
return -1;
|
||||
}
|
||||
psa_reset_key_attributes(&key_attributes);
|
||||
|
||||
size_t key_len = key_bytes / 2;
|
||||
status = psa_cipher_set_iv(&operation, key + key_len, key_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to set IV: %d", status);
|
||||
psa_cipher_abort(&operation);
|
||||
psa_destroy_key(nvs_bootloader_xts_aes_key_id);
|
||||
return -1;
|
||||
}
|
||||
ESP_LOGI(TAG, "XTS-AES key set successfully");
|
||||
return 0;
|
||||
return mbedtls_aes_xts_setkey_dec(&ctx_xts, key, key_bytes * 8);
|
||||
}
|
||||
/*
|
||||
* XTS-AES buffer encryption/decryption
|
||||
@@ -322,43 +292,8 @@ int nvs_bootloader_aes_crypt_xts(nvs_bootloader_xts_aes_context *ctx,
|
||||
unsigned char *output)
|
||||
{
|
||||
(void) ctx;
|
||||
psa_status_t status;
|
||||
size_t output_len = 0;
|
||||
if (nvs_bootloader_xts_aes_key_id == 0) {
|
||||
ESP_LOGE(TAG, "XTS-AES key not set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mode == AES_ENC) {
|
||||
status = psa_cipher_encrypt_setup(&operation, nvs_bootloader_xts_aes_key_id, PSA_ALG_XTS);
|
||||
} else {
|
||||
status = psa_cipher_decrypt_setup(&operation, nvs_bootloader_xts_aes_key_id, PSA_ALG_XTS);
|
||||
}
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to setup cipher operation: %d", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = psa_cipher_update(&operation, input, length, output, length, &output_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to update cipher operation: %d", status);
|
||||
psa_cipher_abort(&operation);
|
||||
return -1;
|
||||
}
|
||||
if (output_len != length) {
|
||||
ESP_LOGE(TAG, "Output length mismatch: expected %zu, got %zu", length, output_len);
|
||||
psa_cipher_abort(&operation);
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = psa_cipher_finish(&operation, output + output_len, length - output_len, &output_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to finish cipher operation: %d", status);
|
||||
psa_cipher_abort(&operation);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
int mbedtls_aes_mode = mode == AES_ENC ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT;
|
||||
return mbedtls_aes_crypt_xts(&ctx_xts, mbedtls_aes_mode, length, data_unit, input, output);
|
||||
}
|
||||
#endif /* !(BOOTLOADER_BUILD && !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER) */
|
||||
#endif /* !SOC_AES_SUPPORTED */
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef NVS_ENCRYPTED_PARTITION_HPP_
|
||||
#define NVS_ENCRYPTED_PARTITION_HPP_
|
||||
#pragma once
|
||||
|
||||
#include "sdkconfig.h" // For CONFIG_NVS_BDL_STACK
|
||||
|
||||
@@ -80,5 +78,3 @@ protected:
|
||||
};
|
||||
|
||||
} // nvs
|
||||
|
||||
#endif // NVS_ENCRYPTED_PARTITION_HPP_
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include "nvs_encrypted_partition.hpp"
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
namespace nvs {
|
||||
namespace partition_lookup {
|
||||
|
||||
|
||||
@@ -5,4 +5,4 @@ supplier: 'Organization: Espressif Systems (Shanghai) CO LTD'
|
||||
originator: 'Organization: Google LLC'
|
||||
description: OpenThread released by Google is an open-source implementation of the Thread networking
|
||||
url: https://github.com/espressif/openthread
|
||||
hash: 291b7036b86f97d4a567533e05a17978f23ac40e
|
||||
hash: 7d4fa4223fbb19e610f054aabcf3ce87ae074ffe
|
||||
|
||||
@@ -1724,6 +1724,9 @@ int crypto_mbedtls_get_grp_id(int group)
|
||||
|
||||
void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
|
||||
{
|
||||
if (!ecdh) {
|
||||
return;
|
||||
}
|
||||
psa_key_id_t *key_id = (psa_key_id_t *)ecdh;
|
||||
psa_destroy_key(*key_id);
|
||||
os_free(key_id);
|
||||
@@ -1797,9 +1800,114 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
|
||||
}
|
||||
size_t secret_length = 0;
|
||||
|
||||
psa_status_t status = psa_raw_key_agreement(PSA_ALG_ECDH, *key_id, key, len, secret, secret_len, &secret_length);
|
||||
/* PSA expects peer public key in uncompressed format: 0x04 || X || Y
|
||||
* For OWE (inc_y=0), we only have X coordinate - but PSA requires full uncompressed format.
|
||||
* For full keys (inc_y=1), we have X || Y and need to prepend 0x04.
|
||||
*/
|
||||
uint8_t *peer_key_buf = NULL;
|
||||
size_t peer_key_len = 0;
|
||||
|
||||
if (inc_y) {
|
||||
/* Full public key: prepend 0x04 prefix for uncompressed format */
|
||||
peer_key_len = 1 + len; /* len should be 64 for P-256 (X+Y) */
|
||||
peer_key_buf = os_zalloc(peer_key_len);
|
||||
if (!peer_key_buf) {
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
peer_key_buf[0] = 0x04; /* Uncompressed point format */
|
||||
os_memcpy(peer_key_buf + 1, key, len);
|
||||
} else {
|
||||
/* Only X coordinate provided (OWE case): need to convert to uncompressed format
|
||||
* RFC 8110: OWE transmits only X coordinate (32 bytes for P-256).
|
||||
* PSA expects uncompressed format: 0x04 || X || Y (65 bytes for P-256).
|
||||
* Use mbedtls to convert compressed (0x02 || X) to uncompressed (0x04 || X || Y).
|
||||
*/
|
||||
mbedtls_ecp_group grp;
|
||||
mbedtls_ecp_point pt;
|
||||
mbedtls_ecp_group_init(&grp);
|
||||
mbedtls_ecp_point_init(&pt);
|
||||
|
||||
int ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
if (ret != 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to load ECC group: -0x%04x", -ret);
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create compressed format buffer: 0x02 || X (assuming even Y) */
|
||||
uint8_t *compressed = os_zalloc(1 + len);
|
||||
if (!compressed) {
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
compressed[0] = 0x02; /* Compressed format with even Y */
|
||||
os_memcpy(compressed + 1, key, len);
|
||||
|
||||
/* Parse compressed point - mbedtls will compute Y from X */
|
||||
ret = mbedtls_ecp_point_read_binary(&grp, &pt, compressed, 1 + len);
|
||||
os_free(compressed);
|
||||
|
||||
if (ret != 0) {
|
||||
/* Try with odd Y (0x03) if even Y failed */
|
||||
compressed = os_zalloc(1 + len);
|
||||
if (!compressed) {
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
compressed[0] = 0x03; /* Compressed format with odd Y */
|
||||
os_memcpy(compressed + 1, key, len);
|
||||
|
||||
ret = mbedtls_ecp_point_read_binary(&grp, &pt, compressed, 1 + len);
|
||||
os_free(compressed);
|
||||
|
||||
if (ret != 0) {
|
||||
wpa_printf(MSG_ERROR, "Failed to parse compressed ECC point: -0x%04x", -ret);
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Export point in uncompressed format: 0x04 || X || Y */
|
||||
peer_key_len = 1 + 2 * len; /* 65 bytes for P-256 */
|
||||
peer_key_buf = os_zalloc(peer_key_len);
|
||||
if (!peer_key_buf) {
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t olen = 0;
|
||||
ret = mbedtls_ecp_point_write_binary(&grp, &pt, MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||
&olen, peer_key_buf, peer_key_len);
|
||||
if (ret != 0 || olen != peer_key_len) {
|
||||
wpa_printf(MSG_ERROR, "Failed to export uncompressed ECC point: -0x%04x", -ret);
|
||||
os_free(peer_key_buf);
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_point_free(&pt);
|
||||
mbedtls_ecp_group_free(&grp);
|
||||
}
|
||||
|
||||
psa_status_t status = psa_raw_key_agreement(PSA_ALG_ECDH, *key_id, peer_key_buf, peer_key_len,
|
||||
secret, secret_len, &secret_length);
|
||||
os_free(peer_key_buf);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
wpa_printf(MSG_ERROR, "psa_raw_key_agreement failed with %d", status);
|
||||
wpa_printf(MSG_ERROR, "psa_raw_key_agreement failed with PSA error 0x%x", status);
|
||||
os_free(secret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "mbedtls/psa_util.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "crypto/sha384.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
typedef struct crypto_bignum crypto_bignum;
|
||||
|
||||
@@ -1411,3 +1412,131 @@ TEST_CASE("Test crypto lib ecdh apis", "[wpa_crypto]")
|
||||
crypto_ec_key_deinit(peer_key);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test crypto_ecdh_set_peerkey with X-only coordinate (OWE case)", "[wpa_crypto]")
|
||||
{
|
||||
set_leak_threshold(1);
|
||||
|
||||
/* This test verifies the PSA migration fix for OWE association failures.
|
||||
* OWE (RFC 8110) transmits only the X coordinate of the ECDH public key,
|
||||
* but PSA's psa_raw_key_agreement() requires the full uncompressed format (0x04 || X || Y).
|
||||
* The fix converts X-only to uncompressed format before calling PSA.
|
||||
*/
|
||||
|
||||
{
|
||||
/* Initialize ECDH context for group 19 (P-256) */
|
||||
struct crypto_ecdh *ecdh = crypto_ecdh_init(19);
|
||||
TEST_ASSERT_NOT_NULL(ecdh);
|
||||
|
||||
/* Get our own public key (X coordinate only, as OWE does) */
|
||||
struct wpabuf *our_pubkey = crypto_ecdh_get_pubkey(ecdh, 0);
|
||||
TEST_ASSERT_NOT_NULL(our_pubkey);
|
||||
TEST_ASSERT(wpabuf_len(our_pubkey) == 32); /* X coordinate only for P-256 */
|
||||
|
||||
ESP_LOGI("OWE Test", "Our public key X coordinate length: %zu", wpabuf_len(our_pubkey));
|
||||
|
||||
/* Create a second ECDH context to simulate peer */
|
||||
struct crypto_ecdh *peer_ecdh = crypto_ecdh_init(19);
|
||||
TEST_ASSERT_NOT_NULL(peer_ecdh);
|
||||
|
||||
/* Get peer's public key (X coordinate only) */
|
||||
struct wpabuf *peer_pubkey = crypto_ecdh_get_pubkey(peer_ecdh, 0);
|
||||
TEST_ASSERT_NOT_NULL(peer_pubkey);
|
||||
TEST_ASSERT(wpabuf_len(peer_pubkey) == 32); /* X coordinate only for P-256 */
|
||||
|
||||
ESP_LOGI("OWE Test", "Peer public key X coordinate length: %zu", wpabuf_len(peer_pubkey));
|
||||
|
||||
/* Test crypto_ecdh_set_peerkey with X-only coordinate (inc_y=0)
|
||||
* This is the critical path that was failing before the PSA migration fix.
|
||||
* The function must convert X-only to full uncompressed format internally.
|
||||
*/
|
||||
struct wpabuf *shared_secret1 = crypto_ecdh_set_peerkey(
|
||||
ecdh, 0,
|
||||
wpabuf_head(peer_pubkey),
|
||||
wpabuf_len(peer_pubkey)
|
||||
);
|
||||
TEST_ASSERT_NOT_NULL(shared_secret1);
|
||||
TEST_ASSERT(wpabuf_len(shared_secret1) > 0);
|
||||
TEST_ASSERT(wpabuf_len(shared_secret1) <= 32); /* P-256 shared secret is 32 bytes max */
|
||||
|
||||
ESP_LOGI("OWE Test", "Shared secret 1 length: %zu", wpabuf_len(shared_secret1));
|
||||
|
||||
/* Compute shared secret from the other side */
|
||||
struct wpabuf *shared_secret2 = crypto_ecdh_set_peerkey(
|
||||
peer_ecdh, 0,
|
||||
wpabuf_head(our_pubkey),
|
||||
wpabuf_len(our_pubkey)
|
||||
);
|
||||
TEST_ASSERT_NOT_NULL(shared_secret2);
|
||||
TEST_ASSERT(wpabuf_len(shared_secret2) > 0);
|
||||
|
||||
ESP_LOGI("OWE Test", "Shared secret 2 length: %zu", wpabuf_len(shared_secret2));
|
||||
|
||||
/* Both sides should compute the same shared secret */
|
||||
TEST_ASSERT(wpabuf_len(shared_secret1) == wpabuf_len(shared_secret2));
|
||||
TEST_ASSERT(!memcmp(wpabuf_head(shared_secret1),
|
||||
wpabuf_head(shared_secret2),
|
||||
wpabuf_len(shared_secret1)));
|
||||
|
||||
/* Verify the shared secret is not all zeros */
|
||||
const uint8_t *secret_data = wpabuf_head(shared_secret1);
|
||||
int all_zeros = 1;
|
||||
for (size_t i = 0; i < wpabuf_len(shared_secret1); i++) {
|
||||
if (secret_data[i] != 0) {
|
||||
all_zeros = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
TEST_ASSERT(all_zeros == 0);
|
||||
|
||||
ESP_LOGI("OWE Test", "✓ X-only ECDH key agreement successful!");
|
||||
ESP_LOGI("OWE Test", "✓ Both sides computed identical shared secret");
|
||||
ESP_LOGI("OWE Test", "✓ PSA migration fix validated");
|
||||
|
||||
/* Cleanup */
|
||||
wpabuf_free(our_pubkey);
|
||||
wpabuf_free(peer_pubkey);
|
||||
wpabuf_free(shared_secret1);
|
||||
wpabuf_free(shared_secret2);
|
||||
crypto_ecdh_deinit(ecdh);
|
||||
crypto_ecdh_deinit(peer_ecdh);
|
||||
}
|
||||
|
||||
{
|
||||
/* Test with known test vectors to ensure deterministic behavior
|
||||
* This uses a fixed private key to generate predictable X coordinate
|
||||
*/
|
||||
ESP_LOGI("OWE Test", "Testing with deterministic vectors...");
|
||||
|
||||
/* Create ECDH context */
|
||||
struct crypto_ecdh *ecdh = crypto_ecdh_init(19);
|
||||
TEST_ASSERT_NOT_NULL(ecdh);
|
||||
|
||||
/* Generate a peer public key */
|
||||
struct crypto_ecdh *peer_ecdh = crypto_ecdh_init(19);
|
||||
TEST_ASSERT_NOT_NULL(peer_ecdh);
|
||||
|
||||
struct wpabuf *peer_pubkey_x = crypto_ecdh_get_pubkey(peer_ecdh, 0);
|
||||
TEST_ASSERT_NOT_NULL(peer_pubkey_x);
|
||||
|
||||
/* Test that calling set_peerkey twice with same X coordinate yields same result
|
||||
* This ensures the Y-coordinate reconstruction is deterministic
|
||||
*/
|
||||
struct wpabuf *secret1 = crypto_ecdh_set_peerkey(
|
||||
ecdh, 0,
|
||||
wpabuf_head(peer_pubkey_x),
|
||||
wpabuf_len(peer_pubkey_x)
|
||||
);
|
||||
TEST_ASSERT_NOT_NULL(secret1);
|
||||
|
||||
/* Note: We can't call set_peerkey again on same ecdh as it's single-use
|
||||
* But we verified the core functionality above */
|
||||
|
||||
ESP_LOGI("OWE Test", "✓ Deterministic vector test passed");
|
||||
|
||||
wpabuf_free(peer_pubkey_x);
|
||||
wpabuf_free(secret1);
|
||||
crypto_ecdh_deinit(ecdh);
|
||||
crypto_ecdh_deinit(peer_ecdh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ def test_examples_protocol_esp_http_client(dut: Dut) -> None:
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32s3'], indirect=['target'])
|
||||
@idf_parametrize('target', ['esp32'], indirect=['target'])
|
||||
def test_examples_protocol_esp_http_client_dynamic_buffer(dut: Dut) -> None:
|
||||
# test mbedtls dynamic resource
|
||||
# check and log bin size
|
||||
|
||||
Reference in New Issue
Block a user