diff --git a/components/bt/controller/esp32c2/bt.c b/components/bt/controller/esp32c2/bt.c index a9146050013..d0f20ba8b7c 100644 --- a/components/bt/controller/esp32c2/bt.c +++ b/components/bt/controller/esp32c2/bt.c @@ -1447,6 +1447,7 @@ uint8_t esp_ble_get_chip_rev_version(void) #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS #if CONFIG_BT_LE_SM_SC #include "psa/crypto.h" +static const char *TAG_SM_ALG = "ble_sm_alg"; #endif // CONFIG_BT_LE_SM_SC #else #include "tinycrypt/aes.h" @@ -1495,12 +1496,14 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ uint8_t priv[32]; int rc = BLE_SM_KEY_ERR; - pk[0] = 0x04; // Uncompressed format for public key - swap_buf(&pk[1], peer_pub_key_x, 32); - swap_buf(&pk[33], peer_pub_key_y, 32); swap_buf(priv, our_priv_key, 32); #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA expects 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + pk[0] = 0x04; // Uncompressed format for public key + swap_buf(&pk[1], peer_pub_key_x, 32); + swap_buf(&pk[33], peer_pub_key_y, 32); + psa_key_id_t key_id = 0; psa_status_t status; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -1508,18 +1511,22 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ psa_set_key_bits(&key_attributes, 256); psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH); psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); + status = psa_import_key(&key_attributes, priv, 32, &key_id); if (status != PSA_SUCCESS) { + ESP_LOGE(TAG_SM_ALG, "Failed to import key: %d", status); goto exit; } psa_reset_key_attributes(&key_attributes); size_t output_len = 0; status = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, pk, BLE_PUB_KEY_LEN, dh, sizeof(dh), &output_len); if (status != PSA_SUCCESS) { + ESP_LOGE(TAG_SM_ALG, "Failed to perform raw key agreement: %d", status); goto exit; } if (output_len != 32) { + ESP_LOGE(TAG_SM_ALG, "Unexpected output length: %zu", output_len); goto exit; } rc = 0; @@ -1530,7 +1537,11 @@ exit: } #else - if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { + // tinycrypt expects 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pk, peer_pub_key_x, 32); + swap_buf(&pk[32], peer_pub_key_y, 32); + + if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { return BLE_SM_KEY_ERR; } @@ -1613,8 +1624,16 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) /* Make sure generated key isn't debug key. */ } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0); +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA returns 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + // Skip the 0x04 prefix when copying to pub swap_buf(pub, &pk[1], 32); swap_buf(&pub[32], &pk[33], 32); +#else + // tinycrypt returns 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pub, pk, 32); + swap_buf(&pub[32], &pk[32], 32); +#endif swap_in_place(priv, 32); #endif // CONFIG_BT_LE_SM_SC_DEBUG_KEYS return 0; diff --git a/components/bt/controller/esp32c5/bt.c b/components/bt/controller/esp32c5/bt.c index f31eabb2a17..760170c4a66 100644 --- a/components/bt/controller/esp32c5/bt.c +++ b/components/bt/controller/esp32c5/bt.c @@ -1589,6 +1589,7 @@ void esp_ble_controller_log_dump_all(bool output) #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS #if CONFIG_BT_LE_SM_SC #include "psa/crypto.h" +static const char *TAG_SM_ALG = "ble_sm_alg"; #endif // CONFIG_BT_LE_SM_SC #else #include "tinycrypt/aes.h" @@ -1636,12 +1637,14 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ uint8_t priv[32]; int rc = BLE_SM_KEY_ERR; - pk[0] = 0x04; // Uncompressed format for public key - swap_buf(&pk[1], peer_pub_key_x, 32); - swap_buf(&pk[33], peer_pub_key_y, 32); swap_buf(priv, our_priv_key, 32); #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA/mbedTLS expects 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + pk[0] = 0x04; // Uncompressed format for public key + swap_buf(&pk[1], peer_pub_key_x, 32); + swap_buf(&pk[33], peer_pub_key_y, 32); + psa_key_id_t key_id = 0; psa_status_t status; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -1651,27 +1654,37 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); status = psa_import_key(&key_attributes, priv, 32, &key_id); if (status != PSA_SUCCESS) { + ESP_LOGE(TAG_SM_ALG, "Failed to import key: %d", status); goto exit; } psa_reset_key_attributes(&key_attributes); size_t output_len = 0; status = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, pk, BLE_PUB_KEY_LEN, dh, sizeof(dh), &output_len); if (status != PSA_SUCCESS) { + ESP_LOGE(TAG_SM_ALG, "Failed to perform raw key agreement: %d", status); goto exit; } if (output_len != 32) { + ESP_LOGE(TAG_SM_ALG, "Unexpected output length: %zu", output_len); goto exit; } rc = 0; exit: + if (key_id != 0) { + psa_destroy_key(key_id); + } if (rc != 0) { return BLE_SM_KEY_ERR; } #else - if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { + // TinyCrypt/uECC expects 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pk, peer_pub_key_x, 32); + swap_buf(&pk[32], peer_pub_key_y, 32); + + if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { return BLE_SM_KEY_ERR; } @@ -1754,8 +1767,16 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) /* Make sure generated key isn't debug key. */ } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0); +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA returns 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + // Skip the 0x04 prefix when copying to pub swap_buf(pub, &pk[1], 32); swap_buf(&pub[32], &pk[33], 32); +#else + // tinycrypt returns 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pub, pk, 32); + swap_buf(&pub[32], &pk[32], 32); +#endif swap_in_place(priv, 32); #endif // CONFIG_BT_LE_SM_SC_DEBUG_KEYS return 0; diff --git a/components/bt/controller/esp32c6/bt.c b/components/bt/controller/esp32c6/bt.c index e3548412274..5eb26edc600 100644 --- a/components/bt/controller/esp32c6/bt.c +++ b/components/bt/controller/esp32c6/bt.c @@ -1659,6 +1659,7 @@ void esp_ble_controller_log_dump_all(bool output) #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS #if CONFIG_BT_LE_SM_SC #include "psa/crypto.h" +static const char *TAG_SM_ALG = "ble_sm_alg"; #endif // CONFIG_BT_LE_SM_SC #else #include "tinycrypt/aes.h" @@ -1704,12 +1705,14 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ uint8_t priv[32]; int rc = BLE_SM_KEY_ERR; - pk[0] = 0x04; // Uncompressed format for public key - swap_buf(&pk[1], peer_pub_key_x, 32); - swap_buf(&pk[33], peer_pub_key_y, 32); swap_buf(priv, our_priv_key, 32); #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA/mbedTLS expects 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + pk[0] = 0x04; // Uncompressed format for public key + swap_buf(&pk[1], peer_pub_key_x, 32); + swap_buf(&pk[33], peer_pub_key_y, 32); + psa_key_id_t key_id = 0; psa_status_t status; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -1719,27 +1722,37 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE); status = psa_import_key(&key_attributes, priv, 32, &key_id); if (status != PSA_SUCCESS) { + ESP_LOGE(TAG_SM_ALG, "Failed to import key: %d", status); goto exit; } psa_reset_key_attributes(&key_attributes); size_t output_len = 0; status = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, pk, BLE_PUB_KEY_LEN, dh, sizeof(dh), &output_len); if (status != PSA_SUCCESS) { + ESP_LOGE(TAG_SM_ALG, "Failed to perform raw key agreement: %d", status); goto exit; } if (output_len != 32) { + ESP_LOGE(TAG_SM_ALG, "Unexpected output length: %zu", output_len); goto exit; } rc = 0; exit: + if (key_id != 0) { + psa_destroy_key(key_id); + } if (rc != 0) { return BLE_SM_KEY_ERR; } #else - if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { + // TinyCrypt/uECC expects 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pk, peer_pub_key_x, 32); + swap_buf(&pk[32], peer_pub_key_y, 32); + + if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { return BLE_SM_KEY_ERR; } @@ -1822,8 +1835,16 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) /* Make sure generated key isn't debug key. */ } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0); +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA returns 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + // Skip the 0x04 prefix when copying to pub swap_buf(pub, &pk[1], 32); swap_buf(&pub[32], &pk[33], 32); +#else + // tinycrypt returns 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pub, pk, 32); + swap_buf(&pub[32], &pk[32], 32); +#endif swap_in_place(priv, 32); #endif // CONFIG_BT_LE_SM_SC_DEBUG_KEYS return 0; diff --git a/components/bt/controller/esp32h2/bt.c b/components/bt/controller/esp32h2/bt.c index 55ed62e31bb..ec66328ab1c 100644 --- a/components/bt/controller/esp32h2/bt.c +++ b/components/bt/controller/esp32h2/bt.c @@ -1656,12 +1656,14 @@ int ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_ uint8_t priv[32]; int rc = BLE_SM_KEY_ERR; - pk[0] = 0x04; // Uncompressed format for public key - swap_buf(&pk[1], peer_pub_key_x, 32); - swap_buf(&pk[33], peer_pub_key_y, 32); swap_buf(priv, our_priv_key, 32); #if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA/mbedTLS expects 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + pk[0] = 0x04; // Uncompressed format for public key + swap_buf(&pk[1], peer_pub_key_x, 32); + swap_buf(&pk[33], peer_pub_key_y, 32); + psa_key_id_t key_id = 0; psa_status_t status; psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -1691,7 +1693,11 @@ exit: } #else - if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { + // TinyCrypt/uECC expects 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pk, peer_pub_key_x, 32); + swap_buf(&pk[32], peer_pub_key_y, 32); + + if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { return BLE_SM_KEY_ERR; } @@ -1775,8 +1781,16 @@ int ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) /* Make sure generated key isn't debug key. */ } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0); +#if CONFIG_BT_LE_CRYPTO_STACK_MBEDTLS + // PSA returns 65 bytes: 0x04 prefix + X (32 bytes) + Y (32 bytes) + // Skip the 0x04 prefix when copying to pub swap_buf(pub, &pk[1], 32); swap_buf(&pub[32], &pk[33], 32); +#else + // tinycrypt returns 64 bytes: X (32 bytes) + Y (32 bytes), no prefix + swap_buf(pub, pk, 32); + swap_buf(&pub[32], &pk[32], 32); +#endif swap_in_place(priv, 32); #endif // CONFIG_BT_LE_SM_SC_DEBUG_KEYS return 0; diff --git a/components/esp-tls/test_apps/main/CMakeLists.txt b/components/esp-tls/test_apps/main/CMakeLists.txt index d57cfd52498..dd9e94d16b7 100644 --- a/components/esp-tls/test_apps/main/CMakeLists.txt +++ b/components/esp-tls/test_apps/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register(SRC_DIRS "." - PRIV_REQUIRES test_utils esp-tls unity + PRIV_REQUIRES test_utils esp-tls unity nvs_flash WHOLE_ARCHIVE) diff --git a/components/esp-tls/test_apps/main/app_main.c b/components/esp-tls/test_apps/main/app_main.c index 03369386dd6..e560e37e528 100644 --- a/components/esp-tls/test_apps/main/app_main.c +++ b/components/esp-tls/test_apps/main/app_main.c @@ -60,7 +60,7 @@ void setUp(void) psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, buf, CALL_SZ, buf, CALL_SZ, &output_length); heap_caps_free(buf); psa_destroy_key(key_id); -#endif // SOC_AES_SUPPORTED +// #endif // SOC_AES_SUPPORTED test_utils_record_free_mem(); TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 6229fc0d91b..fa0ad5e7fa0 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -183,6 +183,7 @@ endif() set(mbedtls_targets mbedtls mbedx509 tfpsacrypto builtin) target_include_directories(tfpsacrypto PUBLIC "port/include") +target_include_directories(tfpsacrypto PRIVATE "port/psa_crypto_storage/include") if(CONFIG_MBEDTLS_HARDWARE_SHA OR CONFIG_MBEDTLS_HARDWARE_AES) list(APPEND include_dirs "${COMPONENT_DIR}/port/psa_driver/include") @@ -212,6 +213,29 @@ set(mbedtls_target_sources "${COMPONENT_DIR}/port/mbedtls_debug.c" if(CONFIG_MBEDTLS_VER_4_X_SUPPORT) list(APPEND mbedtls_target_sources "${COMPONENT_DIR}/port/esp_psa_crypto_init.c") + # Add ESP-IDF NVS-based PSA ITS implementation + # Only compile esp_psa_its.c if nvs_flash component is available + if(NOT ${IDF_TARGET} STREQUAL "linux") + if(IDF_BUILD_V2) + # For v2: conditionally compile source and link only if nvs_flash target exists + target_sources( + tfpsacrypto PRIVATE + "$<$:${COMPONENT_DIR}/port/psa_crypto_storage/esp_psa_its.c>" + ) + target_link_libraries(tfpsacrypto PRIVATE "$<$:idf::nvs_flash>") + # Define compile definition to indicate ESP-IDF PSA ITS implementation is available + target_compile_definitions(tfpsacrypto PRIVATE "$<$:ESP_PSA_ITS_AVAILABLE>") + else() + # For v1: check if component is in build before adding source and linking + idf_build_get_property(build_components BUILD_COMPONENTS) + if(nvs_flash IN_LIST build_components) + target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_crypto_storage/esp_psa_its.c") + idf_component_get_property(nvs_flash_lib nvs_flash COMPONENT_LIB) + target_link_libraries(tfpsacrypto PRIVATE ${nvs_flash_lib}) + target_compile_definitions(tfpsacrypto PRIVATE ESP_PSA_ITS_AVAILABLE) + endif() + endif() + endif() endif() if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) @@ -251,7 +275,6 @@ target_sources(mbedtls PRIVATE ${mbedtls_target_sources}) if(NOT ${IDF_TARGET} STREQUAL "linux") target_link_libraries(tfpsacrypto PRIVATE idf::esp_security) target_link_libraries(builtin PRIVATE idf::esp_security) - # target_link_libraries(builtin PRIVATE idf::esp_security) endif() # Choose peripheral type diff --git a/components/mbedtls/port/esp_psa_crypto_init.c b/components/mbedtls/port/esp_psa_crypto_init.c index 728c98966f6..a929c82356c 100644 --- a/components/mbedtls/port/esp_psa_crypto_init.c +++ b/components/mbedtls/port/esp_psa_crypto_init.c @@ -16,7 +16,7 @@ void mbedtls_psa_crypto_init_include_impl(void); * @brief Initialize PSA Crypto library at system startup * * This function is called during the SECONDARY initialization stage with priority 104, - * which ensures it runs after esp_security_init (priority 104). This ordering guarantees + * which ensures it runs after esp_security_init (priority 103). This ordering guarantees * that hardware crypto support is fully initialized before PSA crypto initialization. */ ESP_SYSTEM_INIT_FN(mbedtls_psa_crypto_init_fn, SECONDARY, BIT(0), 104) diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index 7368d8b6a57..8eb5aa5649c 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -1052,6 +1052,26 @@ under the driver abstraction layer */ #endif #ifndef CONFIG_IDF_TARGET_LINUX + +/** + * \def MBEDTLS_PSA_ITS_FILE_C + * + * ESP-IDF: PSA Internal Trusted Storage (ITS) implementation. + * + * ESP-IDF does NOT use the file-based implementation (MBEDTLS_PSA_ITS_FILE_C) + * when the ESP-IDF NVS-based implementation is available. + * Instead, ESP-IDF provides its own NVS (Non-Volatile Storage) based implementation + * in port/psa_crypto_storage/esp_psa_its.c + * + * If ESP_PSA_ITS_AVAILABLE is defined, it means the ESP-IDF NVS-based implementation + * is available and we should undefine MBEDTLS_PSA_ITS_FILE_C to use it. + * Otherwise, keep MBEDTLS_PSA_ITS_FILE_C defined to use the file-based implementation. + * + */ +#ifdef ESP_PSA_ITS_AVAILABLE +#undef MBEDTLS_PSA_ITS_FILE_C +#endif + /** * \def MBEDTLS_NO_PLATFORM_ENTROPY * @@ -3070,9 +3090,11 @@ under the driver abstraction layer */ #ifdef CONFIG_MBEDTLS_SHA256_C // #define MBEDTLS_SHA256_C #define PSA_WANT_ALG_SHA_256 1 +#define PSA_WANT_ALG_SHA_224 1 #else // #undef MBEDTLS_SHA256_C #undef PSA_WANT_ALG_SHA_256 +#undef PSA_WANT_ALG_SHA_224 #endif /* MBEDTLS_SHAxx_ALT to enable hardware SHA support @@ -3107,6 +3129,30 @@ under the driver abstraction layer */ #undef MBEDTLS_SHA512_ALT #endif +/* MBEDTLS_MD_CAN_SHA* macros indicate whether a hash algorithm is available + * either via legacy implementation (MBEDTLS_SHA*_C) or via PSA (PSA_WANT_ALG_SHA_*). + * These are used for TLS 1.3 signature algorithm configuration. + */ +#if defined(MBEDTLS_SHA1_C) || defined(PSA_WANT_ALG_SHA_1) +#define MBEDTLS_MD_CAN_SHA1 +#endif + +#if defined(MBEDTLS_SHA224_C) || defined(PSA_WANT_ALG_SHA_224) +#define MBEDTLS_MD_CAN_SHA224 +#endif + +#if defined(MBEDTLS_SHA256_C) || defined(PSA_WANT_ALG_SHA_256) +#define MBEDTLS_MD_CAN_SHA256 +#endif + +#if defined(MBEDTLS_SHA384_C) || defined(PSA_WANT_ALG_SHA_384) +#define MBEDTLS_MD_CAN_SHA384 +#endif + +#if defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512) +#define MBEDTLS_MD_CAN_SHA512 +#endif + /** * \def MBEDTLS_SHA3_C * diff --git a/components/mbedtls/port/psa_crypto_storage/esp_psa_its.c b/components/mbedtls/port/psa_crypto_storage/esp_psa_its.c new file mode 100644 index 00000000000..89a5f693f88 --- /dev/null +++ b/components/mbedtls/port/psa_crypto_storage/esp_psa_its.c @@ -0,0 +1,453 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + * + * PSA ITS (Internal Trusted Storage) implementation using ESP-IDF NVS. + * + * This file provides the PSA Internal Trusted Storage API using ESP-IDF's + * NVS (Non-Volatile Storage) flash storage instead of a filesystem. + * This is suitable for embedded systems without filesystem support. + */ + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "psa_crypto_its.h" + +#include +#include +#include + +/* ESP-IDF specific includes */ +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_log.h" + +static const char *TAG = "esp_psa_its"; + +/* NVS namespace for PSA ITS */ +#define PSA_ITS_NVS_NAMESPACE "psa_its" + +/* The maximum value of psa_storage_info_t.size */ +#define PSA_ITS_MAX_SIZE 0xffffffff + +/* Magic number for entry validation: 'PSAI' */ +#define PSA_ITS_MAGIC 0x50534149 + +/* NVS key length limit is 15 characters + null terminator */ +#define PSA_ITS_NVS_KEY_LEN 14 /* 13 chars + null */ + +/** + * Storage entry format stored in NVS blob: + * - magic: 4 bytes (0x50534149 'PSAI') + * - flags: 4 bytes (PSA storage flags) + * - size: 4 bytes (data size) + * - data: variable length + */ +typedef struct { + uint32_t magic; + uint32_t flags; + uint32_t size; + uint8_t data[]; +} __attribute__((packed)) psa_its_entry_t; + +/** + * Convert 64-bit UID to 13-character base32 NVS key. + * Uses RFC 4648 base32 alphabet: A-Z, 2-7 (32 characters). + * 64 bits / 5 bits per char = 12.8, needs 13 chars + null terminator. + */ +static void uid_to_nvs_key(psa_storage_uid_t uid, char *key) +{ + static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + + /* Encode 64-bit UID as 13 base32 characters */ + for (int i = 0; i < 13; i++) { + key[12 - i] = base32_alphabet[uid & 0x1F]; + uid >>= 5; + } + key[13] = '\0'; +} + +/** + * Map ESP error codes to PSA status codes. + */ +static psa_status_t esp_err_to_psa_status(esp_err_t err) +{ + switch (err) { + case ESP_OK: + return PSA_SUCCESS; + case ESP_ERR_NVS_NOT_FOUND: + return PSA_ERROR_DOES_NOT_EXIST; + case ESP_ERR_NVS_NOT_ENOUGH_SPACE: + case ESP_ERR_NVS_NO_FREE_PAGES: + return PSA_ERROR_INSUFFICIENT_STORAGE; + case ESP_ERR_NVS_INVALID_LENGTH: + case ESP_ERR_NVS_INVALID_NAME: + return PSA_ERROR_INVALID_ARGUMENT; + default: + return PSA_ERROR_STORAGE_FAILURE; + } +} + +/** + * Get storage information for a UID. + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + nvs_handle_t handle; + esp_err_t err; + char nvs_key[PSA_ITS_NVS_KEY_LEN]; + size_t required_size = 0; + psa_its_entry_t *entry = NULL; + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + + if (p_info == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Convert UID to NVS key */ + uid_to_nvs_key(uid, nvs_key); + + /* Open NVS handle */ + err = nvs_open(PSA_ITS_NVS_NAMESPACE, NVS_READONLY, &handle); + if (err == ESP_ERR_NVS_NOT_FOUND) { + /* Namespace doesn't exist yet, which means key doesn't exist */ + return PSA_ERROR_DOES_NOT_EXIST; + } + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS namespace: %s", esp_err_to_name(err)); + return esp_err_to_psa_status(err); + } + + /* Get the blob size first */ + err = nvs_get_blob(handle, nvs_key, NULL, &required_size); + if (err != ESP_OK) { + status = esp_err_to_psa_status(err); + goto exit; + } + + /* Check minimum size for header */ + if (required_size < sizeof(psa_its_entry_t)) { + ESP_LOGE(TAG, "Corrupted entry: size too small"); + status = PSA_ERROR_DATA_CORRUPT; + goto exit; + } + + /* Allocate and read entry header */ + entry = mbedtls_calloc(1, required_size); + if (entry == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + err = nvs_get_blob(handle, nvs_key, entry, &required_size); + if (err != ESP_OK) { + status = esp_err_to_psa_status(err); + goto exit; + } + + /* Validate magic number */ + if (entry->magic != PSA_ITS_MAGIC) { + ESP_LOGE(TAG, "Invalid magic number: 0x%08lx", (unsigned long)entry->magic); + status = PSA_ERROR_DATA_CORRUPT; + goto exit; + } + + /* Return info */ + p_info->size = entry->size; + p_info->flags = entry->flags; + status = PSA_SUCCESS; + +exit: + if (entry != NULL) { + mbedtls_platform_zeroize(entry, required_size); + mbedtls_free(entry); + } + nvs_close(handle); + return status; +} + +/** + * Retrieve data from storage. + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length) +{ + nvs_handle_t handle; + esp_err_t err; + char nvs_key[PSA_ITS_NVS_KEY_LEN]; + size_t required_size = 0; + psa_its_entry_t *entry = NULL; + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + + if (p_data == NULL && data_length != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Convert UID to NVS key */ + uid_to_nvs_key(uid, nvs_key); + + /* Open NVS handle */ + err = nvs_open(PSA_ITS_NVS_NAMESPACE, NVS_READONLY, &handle); + if (err == ESP_ERR_NVS_NOT_FOUND) { + return PSA_ERROR_DOES_NOT_EXIST; + } + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS namespace: %s", esp_err_to_name(err)); + return esp_err_to_psa_status(err); + } + + /* Get the blob size */ + err = nvs_get_blob(handle, nvs_key, NULL, &required_size); + if (err != ESP_OK) { + status = esp_err_to_psa_status(err); + goto exit; + } + + /* Check minimum size */ + if (required_size < sizeof(psa_its_entry_t)) { + ESP_LOGE(TAG, "Corrupted entry: size too small"); + status = PSA_ERROR_DATA_CORRUPT; + goto exit; + } + + /* Allocate and read full entry */ + entry = mbedtls_calloc(1, required_size); + if (entry == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + err = nvs_get_blob(handle, nvs_key, entry, &required_size); + if (err != ESP_OK) { + status = esp_err_to_psa_status(err); + goto exit; + } + + /* Validate magic number */ + if (entry->magic != PSA_ITS_MAGIC) { + ESP_LOGE(TAG, "Invalid magic number: 0x%08lx", (unsigned long)entry->magic); + status = PSA_ERROR_DATA_CORRUPT; + goto exit; + } + + /* Validate offset and length */ + if (data_offset + data_length < data_offset) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } +#if SIZE_MAX < 0xffffffff + if (data_offset + data_length > SIZE_MAX) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } +#endif + if (data_offset + data_length > entry->size) { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Copy requested data portion */ + if (data_length > 0) { + memcpy(p_data, entry->data + data_offset, data_length); + } + + if (p_data_length != NULL) { + *p_data_length = data_length; + } + + status = PSA_SUCCESS; + +exit: + if (entry != NULL) { + mbedtls_platform_zeroize(entry, required_size); + mbedtls_free(entry); + } + nvs_close(handle); + return status; +} + +/** + * Store data in NVS. + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + nvs_handle_t handle; + esp_err_t err; + char nvs_key[PSA_ITS_NVS_KEY_LEN]; + psa_its_entry_t *entry = NULL; + size_t entry_size; + size_t existing_size = 0; + psa_its_entry_t *existing_entry = NULL; + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + + /* UID 0 is invalid per PSA spec */ + if (uid == 0) { + return PSA_ERROR_INVALID_HANDLE; + } + + if (p_data == NULL && data_length != 0) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Convert UID to NVS key */ + uid_to_nvs_key(uid, nvs_key); + + /* Open NVS handle with read-write access */ + err = nvs_open(PSA_ITS_NVS_NAMESPACE, NVS_READWRITE, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS namespace: %s", esp_err_to_name(err)); + return esp_err_to_psa_status(err); + } + + /* Check if entry already exists and has WRITE_ONCE flag */ + err = nvs_get_blob(handle, nvs_key, NULL, &existing_size); + if (err == ESP_OK && existing_size >= sizeof(psa_its_entry_t)) { + /* Entry exists, check WRITE_ONCE flag */ + existing_entry = mbedtls_calloc(1, existing_size); + if (existing_entry != NULL) { + err = nvs_get_blob(handle, nvs_key, existing_entry, &existing_size); + if (err == ESP_OK && + existing_entry->magic == PSA_ITS_MAGIC && + (existing_entry->flags & PSA_STORAGE_FLAG_WRITE_ONCE)) { + ESP_LOGW(TAG, "Cannot modify WRITE_ONCE entry"); + status = PSA_ERROR_NOT_PERMITTED; + mbedtls_platform_zeroize(existing_entry, existing_size); + mbedtls_free(existing_entry); + goto exit; + } + mbedtls_platform_zeroize(existing_entry, existing_size); + mbedtls_free(existing_entry); + } + } + + /* Allocate entry with header + data */ + entry_size = sizeof(psa_its_entry_t) + data_length; + entry = mbedtls_calloc(1, entry_size); + if (entry == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + /* Fill entry */ + entry->magic = PSA_ITS_MAGIC; + entry->flags = create_flags; + entry->size = data_length; + if (data_length > 0) { + memcpy(entry->data, p_data, data_length); + } + + /* Write to NVS */ + err = nvs_set_blob(handle, nvs_key, entry, entry_size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write blob: %s", esp_err_to_name(err)); + status = esp_err_to_psa_status(err); + goto exit; + } + + /* Commit to ensure atomicity */ + err = nvs_commit(handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit: %s", esp_err_to_name(err)); + status = esp_err_to_psa_status(err); + goto exit; + } + + status = PSA_SUCCESS; + +exit: + if (entry != NULL) { + mbedtls_platform_zeroize(entry, entry_size); + mbedtls_free(entry); + } + nvs_close(handle); + return status; +} + +/** + * Remove data from storage. + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid) +{ + nvs_handle_t handle; + esp_err_t err; + char nvs_key[PSA_ITS_NVS_KEY_LEN]; + size_t existing_size = 0; + psa_its_entry_t *existing_entry = NULL; + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + + /* Convert UID to NVS key */ + uid_to_nvs_key(uid, nvs_key); + + /* Open NVS handle */ + err = nvs_open(PSA_ITS_NVS_NAMESPACE, NVS_READWRITE, &handle); + if (err == ESP_ERR_NVS_NOT_FOUND) { + return PSA_ERROR_DOES_NOT_EXIST; + } + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to open NVS namespace: %s", esp_err_to_name(err)); + return esp_err_to_psa_status(err); + } + + /* Check if entry exists and has WRITE_ONCE flag */ + err = nvs_get_blob(handle, nvs_key, NULL, &existing_size); + if (err == ESP_ERR_NVS_NOT_FOUND) { + status = PSA_ERROR_DOES_NOT_EXIST; + goto exit; + } + if (err != ESP_OK) { + status = esp_err_to_psa_status(err); + goto exit; + } + + if (existing_size >= sizeof(psa_its_entry_t)) { + /* Read entry to check WRITE_ONCE flag */ + existing_entry = mbedtls_calloc(1, existing_size); + if (existing_entry == NULL) { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto exit; + } + + err = nvs_get_blob(handle, nvs_key, existing_entry, &existing_size); + if (err == ESP_OK && + existing_entry->magic == PSA_ITS_MAGIC && + (existing_entry->flags & PSA_STORAGE_FLAG_WRITE_ONCE)) { + ESP_LOGW(TAG, "Cannot remove WRITE_ONCE entry"); + status = PSA_ERROR_NOT_PERMITTED; + goto exit; + } + } + + /* Erase the key */ + err = nvs_erase_key(handle, nvs_key); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to erase key: %s", esp_err_to_name(err)); + status = esp_err_to_psa_status(err); + goto exit; + } + + /* Commit to ensure atomicity */ + err = nvs_commit(handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to commit: %s", esp_err_to_name(err)); + status = esp_err_to_psa_status(err); + goto exit; + } + + status = PSA_SUCCESS; + +exit: + if (existing_entry != NULL) { + mbedtls_platform_zeroize(existing_entry, existing_size); + mbedtls_free(existing_entry); + } + nvs_close(handle); + return status; +} diff --git a/components/mbedtls/port/psa_crypto_storage/include/psa/error.h b/components/mbedtls/port/psa_crypto_storage/include/psa/error.h new file mode 100644 index 00000000000..1dc6456feca --- /dev/null +++ b/components/mbedtls/port/psa_crypto_storage/include/psa/error.h @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "psa/crypto_values.h" diff --git a/components/mbedtls/port/psa_crypto_storage/include/psa/internal_trusted_storage.h b/components/mbedtls/port/psa_crypto_storage/include/psa/internal_trusted_storage.h new file mode 100644 index 00000000000..dd46b4d77da --- /dev/null +++ b/components/mbedtls/port/psa_crypto_storage/include/psa/internal_trusted_storage.h @@ -0,0 +1,6 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "psa_crypto_its.h" diff --git a/components/protocomm/src/security/security1.c b/components/protocomm/src/security/security1.c index bbc429c01ee..da7b89e0296 100644 --- a/components/protocomm/src/security/security1.c +++ b/components/protocomm/src/security/security1.c @@ -113,6 +113,7 @@ static esp_err_t handle_session_command1(session_t *cur_session, psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT); psa_set_key_algorithm(&key_attributes, alg); psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES); + psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE); psa_set_key_bits(&key_attributes, sizeof(cur_session->sym_key) * 8); status = psa_import_key(&key_attributes, cur_session->sym_key, sizeof(cur_session->sym_key), &key_id); if (status != PSA_SUCCESS) { @@ -447,21 +448,25 @@ static esp_err_t sec1_close_session(protocomm_security_handle_t handle, uint32_t // if (cur_session->state == SESSION_STATE_DONE) { /* Free AES context data */ + if (cur_session->key_id != 0) { psa_status_t status = psa_destroy_key(cur_session->key_id); if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "psa_destroy_key failed with status=%d", status); // return ESP_FAIL; } - status = psa_destroy_key(cur_session->key_id_sym); + } + if (cur_session->key_id_sym != 0) { + psa_status_t status = psa_destroy_key(cur_session->key_id_sym); if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "psa_destroy_key failed with status=%d", status); // return ESP_FAIL; } - status = psa_cipher_abort(&cur_session->ctx_aes); - if (status != PSA_SUCCESS) { - ESP_LOGE(TAG, "psa_cipher_abort failed with status=%d", status); - // return ESP_FAIL; - } + } + psa_status_t status = psa_cipher_abort(&cur_session->ctx_aes); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "psa_cipher_abort failed with status=%d", status); + // return ESP_FAIL; + } // } memset(cur_session, 0, sizeof(session_t)); diff --git a/components/protocomm/test_apps/main/app_main.c b/components/protocomm/test_apps/main/app_main.c index d89c74aeabb..15f78695136 100644 --- a/components/protocomm/test_apps/main/app_main.c +++ b/components/protocomm/test_apps/main/app_main.c @@ -21,7 +21,7 @@ /* setUp runs before every test */ void setUp(void) { -#if SOC_SHA_SUPPORTED +#if CONFIG_MBEDTLS_HARDWARE_SHA // Execute esp_sha operation to allocate internal SHA semaphore (in case of ESP32) // and initial DMA setup memory which is considered as leaked otherwise const uint8_t input_buffer[64] = {0}; @@ -35,7 +35,7 @@ void setUp(void) #if SOC_SHA_SUPPORT_SHA512 esp_sha(SHA2_512, input_buffer, sizeof(input_buffer), output_buffer); #endif // SOC_SHA_SUPPORT_SHA512 -#endif // SOC_SHA_SUPPORTED +#endif // CONFIG_MBEDTLS_HARDWARE_SHA #if defined(CONFIG_MBEDTLS_HARDWARE_MPI) esp_mpi_enable_hardware_hw_op(); @@ -55,6 +55,7 @@ void setUp(void) psa_set_key_algorithm(&attributes, PSA_ALG_CBC_NO_PADDING); psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); psa_set_key_bits(&attributes, 128); + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE); status = psa_import_key(&attributes, key, sizeof(key), &key_id); TEST_ASSERT_EQUAL(PSA_SUCCESS, status); size_t output_len = 0; @@ -67,7 +68,11 @@ void setUp(void) status = psa_cipher_encrypt(key_id, PSA_ALG_CBC_NO_PADDING, plaintext_long, sizeof(plaintext_long), ciphertext_long, sizeof(ciphertext_long), &output_len); TEST_ASSERT_EQUAL(PSA_SUCCESS, status); psa_destroy_key(key_id); -#endif // SOC_AES_SUPPORTED + // Destroying the key again to get rid of nvs flash memory leak + // If the key doesn't exist, PSA looks for it in nvs and that + // allocates some memory which is considered as leak otherwise + psa_destroy_key(key_id); +// #endif // SOC_AES_SUPPORTED test_utils_record_free_mem(); TEST_ESP_OK(test_utils_set_leak_level(50, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); 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 21e95a228e3..e3d12310c28 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 @@ -25,6 +25,7 @@ #include "mbedtls/oid.h" #include #include "psa/crypto.h" +#include "psa/crypto_sizes.h" #include "esp_heap_caps.h" #define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) @@ -482,8 +483,8 @@ int crypto_ec_key_compare(struct crypto_ec_key *key1, struct crypto_ec_key *key2 psa_key_id_t *key1_id = (psa_key_id_t *)key1; psa_key_id_t *key2_id = (psa_key_id_t *)key2; - unsigned char pub1[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; - unsigned char pub2[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE]; + unsigned char pub1[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)]; + unsigned char pub2[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(256)]; size_t key1_len, key2_len; @@ -1674,6 +1675,10 @@ struct crypto_ecdh * crypto_ecdh_init(int group) size_t key_size = 0; psa_ecc_family_t ecc_family = group_id_to_psa(crypto_mbedtls_get_grp_id(group), &key_size); + if (ecc_family == 0) { + wpa_printf(MSG_ERROR, "group_id_to_psa failed, group: %d", group); + return NULL; + } psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family)); psa_set_key_bits(&key_attributes, key_size); diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c index 6559716fd08..8b3997deace 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls.c @@ -336,7 +336,9 @@ static int hmac_vector(psa_algorithm_t alg, } size_t mac_len; - status = psa_mac_sign_finish(&operation, mac, PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 8 * key_len, PSA_ALG_HMAC(alg)), &mac_len); + /* For HMAC, the MAC length equals the hash output length */ + size_t expected_mac_len = PSA_HASH_LENGTH(alg); + status = psa_mac_sign_finish(&operation, mac, expected_mac_len, &mac_len); if (status != PSA_SUCCESS) { ret = -1; goto err; @@ -460,26 +462,22 @@ static int aes_crypt(void *ctx, int mode, const u8 *in, u8 *out) status = psa_cipher_decrypt_setup(&operation, *key_id, PSA_ALG_ECB_NO_PADDING); } else { wpa_printf(MSG_ERROR, "%s: invalid mode", __func__); - printf("%s: invalid mode\n", __func__); return -1; } if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_cipher_encrypt_setup failed", __func__); - printf("%s: psa_cipher_encrypt_setup failed, status: %d\n", __func__, status); return -1; } status = psa_cipher_update(&operation, in, 16, out, 16, &output_len); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_cipher_update failed", __func__); - printf("%s: psa_cipher_update failed\n", __func__); return -1; } status = psa_cipher_finish(&operation, out + output_len, 16 - output_len, &output_len); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_cipher_finish failed", __func__); - printf("%s: psa_cipher_finish failed\n", __func__); return -1; } @@ -493,10 +491,9 @@ static void aes_crypt_deinit(void *ctx) psa_key_id_t *key_id = (psa_key_id_t *) ctx; psa_status_t status = psa_destroy_key(*key_id); if (status != PSA_SUCCESS) { - printf("%s: psa_destroy_key failed\n", __func__); + wpa_printf(MSG_ERROR, "%s: psa_destroy_key failed", __func__); } os_free(ctx); - ctx = NULL; } void *aes_encrypt_init(const u8 *key, size_t len) @@ -612,7 +609,6 @@ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) status = psa_cipher_decrypt_setup(&operation, key_id, PSA_ALG_CBC_NO_PADDING); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_cipher_decrypt_setup failed", __func__); - psa_cipher_abort(&operation); psa_destroy_key(key_id); return -1; } @@ -1121,18 +1117,23 @@ int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce, status = psa_aead_encrypt_setup(&operation, key_id, PSA_ALG_CCM); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_encrypt_setup failed", __func__); + psa_destroy_key(key_id); return -1; } status = psa_aead_set_nonce(&operation, nonce, 13); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_set_nonce failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } status = psa_aead_set_lengths(&operation, aad_len, plain_len); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_set_lengths failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } @@ -1142,18 +1143,25 @@ int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce, status = psa_aead_update_ad(&operation, aad, aad_len); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_update_ad failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } status = psa_aead_update(&operation, plain, plain_len, crypt, plain_len, &output_length); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_update failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } - status = psa_aead_finish(&operation, crypt + output_length, 16 - output_length, &output_length, auth, M, &tag_len); + size_t finish_output = 0; + status = psa_aead_finish(&operation, crypt + output_length, plain_len - output_length, &finish_output, auth, M, &tag_len); if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_finish failed, status: %d\n", __func__, status); + wpa_printf(MSG_ERROR, "%s: psa_aead_finish failed, status: %d", __func__, status); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } @@ -1191,18 +1199,23 @@ int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce, status = psa_aead_decrypt_setup(&operation, key_id, PSA_ALG_CCM); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_decrypt_setup failed", __func__); + psa_destroy_key(key_id); return -1; } status = psa_aead_set_nonce(&operation, nonce, 13); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_set_nonce failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } status = psa_aead_set_lengths(&operation, aad_len, crypt_len); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_set_lengths failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } @@ -1212,18 +1225,25 @@ int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce, status = psa_aead_update_ad(&operation, aad, aad_len); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_update_ad failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } status = psa_aead_update(&operation, crypt, crypt_len, plain, crypt_len, &output_length); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_update failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } - status = psa_aead_verify(&operation, plain + output_length, 16 - output_length, &output_length, auth, M); + size_t verify_output = 0; + status = psa_aead_verify(&operation, plain + output_length, crypt_len - output_length, &verify_output, auth, M); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "%s: psa_aead_verify failed", __func__); + psa_aead_abort(&operation); + psa_destroy_key(key_id); return -1; } diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c index 07399125930..0fb36e4e5c4 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/tls_mbedtls.c @@ -240,32 +240,32 @@ static uint16_t tls_sig_algs_for_suiteb[] = { #endif \ /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) && defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, -#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ +#endif /* (MBEDTLS_RSA_C || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) && MBEDTLS_MD_CAN_SHA512 */ -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) && defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, -#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ +#endif /* (MBEDTLS_RSA_C || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) && MBEDTLS_MD_CAN_SHA384 */ #endif /* CONFIG_TLSV13 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) #if defined(MBEDTLS_ECDSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512), MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), #endif -#if defined(MBEDTLS_RSA_C) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512), MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), #endif -#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_SHA512_C || PSA_WANT_ALG_SHA_512 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_TLS_SIG_NONE }; const mbedtls_x509_crt_profile suiteb_mbedtls_x509_crt_profile = { -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | #endif @@ -325,61 +325,61 @@ static uint16_t tls_sig_algs_for_eap[] = { #endif \ /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_MD_CAN_SHA256 */ -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) && defined(MBEDTLS_MD_CAN_SHA512) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512, -#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */ +#endif /* (MBEDTLS_RSA_C || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) && MBEDTLS_MD_CAN_SHA512 */ -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) && defined(MBEDTLS_MD_CAN_SHA384) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384, -#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */ +#endif /* (MBEDTLS_RSA_C || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) && MBEDTLS_MD_CAN_SHA384 */ -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) && defined(MBEDTLS_MD_CAN_SHA256) MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, -#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */ +#endif /* (MBEDTLS_RSA_C || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) && MBEDTLS_MD_CAN_SHA256 */ #endif /* CONFIG_TLSV13 */ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) #if defined(MBEDTLS_ECDSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512), MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384), #endif -#if defined(MBEDTLS_RSA_C) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512), MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384), #endif -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SHA256_C) +#endif /* MBEDTLS_SHA512_C || PSA_WANT_ALG_SHA_512 */ +#if (defined(MBEDTLS_SHA256_C) || defined(PSA_WANT_ALG_SHA_256)) #if defined(MBEDTLS_ECDSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256), MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA224), #endif -#if defined(MBEDTLS_RSA_C) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256), MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA224), #endif -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA1_C) +#endif /* MBEDTLS_SHA256_C || PSA_WANT_ALG_SHA_256 */ +#if (defined(MBEDTLS_SHA1_C) || defined(PSA_WANT_ALG_SHA_1)) #if defined(MBEDTLS_ECDSA_C) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA1), #endif -#if defined(MBEDTLS_RSA_C) +#if (defined(MBEDTLS_RSA_C) || defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)) MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA1), #endif -#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SHA1_C || PSA_WANT_ALG_SHA_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ MBEDTLS_TLS_SIG_NONE }; const mbedtls_x509_crt_profile eap_mbedtls_x509_crt_profile = { -#if defined(MBEDTLS_SHA1_C) +#if (defined(MBEDTLS_SHA1_C) || defined(PSA_WANT_ALG_SHA_1)) MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | #endif -#if defined(MBEDTLS_SHA256_C) +#if (defined(MBEDTLS_SHA256_C) || defined(PSA_WANT_ALG_SHA_256)) MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | #endif -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | #endif @@ -410,7 +410,7 @@ static const int suiteb_rsa_ciphersuite_preference[] = { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, // MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, #endif @@ -423,7 +423,7 @@ static const int suiteb_ecc_ciphersuite_preference[] = { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, #endif #endif @@ -434,7 +434,7 @@ static const int suiteb_ciphersuite_preference[] = { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, #endif /* CONFIG_ESP_WIFI_EAP_TLS1_3 */ #if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA512_C) +#if (defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)) MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, // MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, diff --git a/components/wpa_supplicant/src/common/dpp_crypto.c b/components/wpa_supplicant/src/common/dpp_crypto.c index 4b811d01e6b..583a3d60511 100644 --- a/components/wpa_supplicant/src/common/dpp_crypto.c +++ b/components/wpa_supplicant/src/common/dpp_crypto.c @@ -158,7 +158,7 @@ int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, const u8 *buf, size_t len) { - const struct crypto_ec_group *group; + struct crypto_ec_group *group; struct crypto_ec_key *pkey = NULL; group = crypto_ec_get_group_from_key(group_key); @@ -167,6 +167,7 @@ struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, else wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); + os_free(group); return pkey; } @@ -962,7 +963,7 @@ int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len) int dpp_auth_derive_l_responder(struct dpp_authentication *auth) { - struct crypto_ec_group *group; + struct crypto_ec_group *group = NULL; struct crypto_ec_point *L = NULL; struct crypto_ec_point *BI; struct crypto_bignum *lx, *sum, *q; @@ -1006,6 +1007,7 @@ fail: crypto_bignum_deinit(lx, 0); crypto_bignum_deinit(sum, 0); crypto_bignum_deinit(q, 0); + os_free(group); return ret; } @@ -1062,7 +1064,7 @@ fail: } if (group) { - crypto_ec_deinit((struct crypto_ec *)group); + os_free(group); } if (bI_bn) { diff --git a/components/wpa_supplicant/src/crypto/aes-ccm.c b/components/wpa_supplicant/src/crypto/aes-ccm.c index fe0b03d8f68..44a4b1ff546 100644 --- a/components/wpa_supplicant/src/crypto/aes-ccm.c +++ b/components/wpa_supplicant/src/crypto/aes-ccm.c @@ -159,73 +159,57 @@ int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce, return 0; } +static void aes_ccm_decr_auth(void *aes, size_t M, u8 *a, const u8 *auth, u8 *t) +{ + size_t i; + u8 tmp[AES_BLOCK_SIZE]; + + wpa_hexdump_key(MSG_DEBUG, "CCM U", auth, M); + /* U = T XOR S_0; S_0 = E(K, A_0) */ + WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0); + aes_encrypt(aes, a, tmp); + for (i = 0; i < M; i++) + t[i] = auth[i] ^ tmp[i]; + wpa_hexdump_key(MSG_DEBUG, "CCM T", t, M); +} /* AES-CCM with fixed L=2 and aad_len <= 30 assumption */ int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce, size_t M, const u8 *crypt, size_t crypt_len, const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain) { - psa_status_t status; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_key_id_t key_id; + /* PSA doesn't support M=0 (zero-length tags) which ESP-NOW uses + * Fall back to old AES implementation for M=0 case + */ + const size_t L = 2; + void *aes; + u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE]; + u8 t[AES_BLOCK_SIZE]; - psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); - psa_set_key_algorithm(&attributes, PSA_ALG_CCM); - psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); - psa_set_key_bits(&attributes, key_len * 8); + if (aad_len > 30 || M > AES_BLOCK_SIZE) + return -1; - status = psa_import_key(&attributes, key, key_len, &key_id); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_import_key failed", __func__); - return -1; - } + aes = aes_encrypt_init(key, key_len); + if (aes == NULL) + return -1; - psa_reset_key_attributes(&attributes); + /* Decryption */ + aes_ccm_encr_start(L, nonce, a); + aes_ccm_decr_auth(aes, M, a, auth, t); - psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + /* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */ + aes_ccm_encr(aes, L, crypt, crypt_len, plain, a); - status = psa_aead_decrypt_setup(&operation, key_id, PSA_ALG_CCM); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_decrypt_setup failed", __func__); - return -1; - } + aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, crypt_len, x); + aes_ccm_auth(aes, plain, crypt_len, x); - status = psa_aead_set_nonce(&operation, nonce, 13); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_set_nonce failed", __func__); - return -1; - } + aes_encrypt_deinit(aes); - status = psa_aead_set_lengths(&operation, aad_len, crypt_len); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_set_lengths failed", __func__); - return -1; - } + if (os_memcmp_const(x, t, M) != 0) { + wpa_printf(MSG_DEBUG, "CCM: Auth mismatch"); + return -1; + } - size_t output_length = 0; - - status = psa_aead_update_ad(&operation, aad, aad_len); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_update_ad failed", __func__); - return -1; - } - - status = psa_aead_update(&operation, crypt, crypt_len, plain, crypt_len, &output_length); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_update failed", __func__); - return -1; - } - - status = psa_aead_verify(&operation, plain + output_length, 16 - output_length, &output_length, auth, M); - if (status != PSA_SUCCESS) { - wpa_printf(MSG_ERROR, "%s: psa_aead_verify failed", __func__); - return -1; - } - - psa_aead_abort(&operation); - - psa_destroy_key(key_id); - - return 0; + return 0; } #endif /* CONFIG_IEEE80211W */ diff --git a/components/wpa_supplicant/test_apps/main/test_crypto.c b/components/wpa_supplicant/test_apps/main/test_crypto.c index a53ef933f21..e00f73163b7 100644 --- a/components/wpa_supplicant/test_apps/main/test_crypto.c +++ b/components/wpa_supplicant/test_apps/main/test_crypto.c @@ -706,6 +706,101 @@ TEST_CASE("Test crypto lib aes apis", "[wpa_crypto]") TEST_ASSERT(!memcmp(tag, expected_tag, 16)); TEST_ASSERT(!memcmp(decrypted, data, 16)); } + + { + /* Test PSA migration compatibility: aes_ccm_ae (old AES) vs aes_ccm_ad (PSA) + * This test verifies that encryption and decryption are compatible despite + * using different implementations. This is critical for PMF frame encryption/decryption. + */ + const uint8_t key_size = 16; + const uint8_t key[16] = {[0 ... key_size - 1] = 0x3A}; + const uint8_t nonce[13] = {[0 ... 12] = 0x5A}; + const uint8_t aad[16] = {[0 ... 15] = 0xA5}; + + /* Test with 32-byte plaintext (not 16 bytes) */ + const uint8_t data_32[32] = {[0 ... 31] = 0xA5}; + uint8_t crypt_32[32]; + uint8_t tag_32[16]; + uint8_t decrypted_32[32] = {0}; + + int ret = aes_ccm_ae(key, key_size, nonce, 16, data_32, 32, aad, 16, crypt_32, tag_32); + TEST_ASSERT(ret == 0); + + /* Critical test: Can PSA-based decryption decrypt old AES-based encryption? */ + ret = aes_ccm_ad(key, key_size, nonce, 16, crypt_32, 32, aad, 16, tag_32, decrypted_32); + TEST_ASSERT(ret == 0); + TEST_ASSERT(!memcmp(decrypted_32, data_32, 32)); + + /* Test with 8-byte plaintext (smaller than 16 bytes) - common for PMF frames */ + const uint8_t data_8[8] = {[0 ... 7] = 0xA5}; + uint8_t crypt_8[8]; + uint8_t tag_8[16]; + uint8_t decrypted_8[8] = {0}; + + ret = aes_ccm_ae(key, key_size, nonce, 16, data_8, 8, aad, 16, crypt_8, tag_8); + TEST_ASSERT(ret == 0); + + /* This should also work correctly with the fix */ + ret = aes_ccm_ad(key, key_size, nonce, 16, crypt_8, 8, aad, 16, tag_8, decrypted_8); + TEST_ASSERT(ret == 0); + TEST_ASSERT(!memcmp(decrypted_8, data_8, 8)); + } + + { + /* Test round-trip encryption/decryption with various PMF-like frame sizes + * PMF frames typically use 8-byte tags and various payload sizes + */ + const uint8_t key_size = 16; + const uint8_t key[16] = {[0 ... key_size - 1] = 0x3A}; + const uint8_t nonce[13] = {[0 ... 12] = 0x5A}; + const uint8_t aad[24] = {[0 ... 23] = 0xA5}; /* Typical PMF AAD size */ + + /* Test multiple round-trips to catch any state issues */ + for (int i = 0; i < 10; i++) { + uint8_t data[20] = {[0 ... 19] = (uint8_t)(0xA5 + i)}; + uint8_t crypt[20]; + uint8_t tag[8]; /* PMF uses 8-byte tags */ + uint8_t decrypted[20] = {0}; + + int ret = aes_ccm_ae(key, key_size, nonce, 8, data, 20, aad, 24, crypt, tag); + TEST_ASSERT(ret == 0); + + ret = aes_ccm_ad(key, key_size, nonce, 8, crypt, 20, aad, 24, tag, decrypted); + TEST_ASSERT(ret == 0); + TEST_ASSERT(!memcmp(decrypted, data, 20)); + } + } + + { + /* Test ESP-NOW specific case: M=0 (tag_len=0) with modified nonce + * ESP-NOW uses tag_len=0 and sets nonce[0]=0 when espnow_pkt=true + * This test verifies if PSA implementation handles M=0 correctly + */ + const uint8_t key_size = 16; + const uint8_t key[16] = {[0 ... key_size - 1] = 0x3A}; + uint8_t nonce[13] = {[0 ... 12] = 0x5A}; + nonce[0] = 0; /* ESP-NOW sets nonce[0] = 0 when espnow_pkt=true */ + const uint8_t aad[24] = {[0 ... 23] = 0xA5}; + const uint8_t data[20] = {[0 ... 19] = 0xA5}; + + uint8_t crypt[20]; + uint8_t tag[8] = {0}; /* M=0 means tag_len=0, tag is not verified */ + uint8_t decrypted[20] = {0}; + + /* Test: Encrypt with M=0 (ESP-NOW encryption case) */ + int ret = aes_ccm_ae(key, key_size, nonce, 0, data, 20, aad, 24, crypt, tag); + if (ret != 0) { + TEST_FAIL_MESSAGE("aes_ccm_ae with M=0 failed - PSA may not support zero-length tags for ESP-NOW"); + } + + /* Test: Decrypt with M=0 (ESP-NOW decryption case) */ + ret = aes_ccm_ad(key, key_size, nonce, 0, crypt, 20, aad, 24, tag, decrypted); + if (ret != 0) { + TEST_FAIL_MESSAGE("aes_ccm_ad with M=0 failed - PSA may not support zero-length tags for ESP-NOW"); + } + + TEST_ASSERT(!memcmp(decrypted, data, 20)); + } } // NOTE: This is disable as PSA does not support DES diff --git a/examples/system/console/advanced/partitions_example.csv b/examples/system/console/advanced/partitions_example.csv index 1c79321a107..27472b2454b 100644 --- a/examples/system/console/advanced/partitions_example.csv +++ b/examples/system/console/advanced/partitions_example.csv @@ -2,5 +2,5 @@ # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 1M, +factory, app, factory, 0x10000, 0x110000, storage, data, fat, , 1M, diff --git a/examples/system/ota/advanced_https_ota/partitions_example_with_ble.csv b/examples/system/ota/advanced_https_ota/partitions_example_with_ble.csv index dd7501cb4ff..e629d8da8b9 100644 --- a/examples/system/ota/advanced_https_ota/partitions_example_with_ble.csv +++ b/examples/system/ota/advanced_https_ota/partitions_example_with_ble.csv @@ -4,5 +4,5 @@ nvs, data, nvs, , 0x4000, otadata, data, ota, , 0x2000, phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, , 1500K, -ota_1, app, ota_1, , 1500K, +ota_0, app, ota_0, , 1600K, +ota_1, app, ota_1, , 1600K,