From 3c4dadff0b3a8afce3f0ca9016cd37f1682508c9 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Sat, 27 Dec 2025 00:03:46 +0530 Subject: [PATCH 1/3] fix(mbedtls): Support partial hardware AES-GCM and s/w fallback for non-AES ciphers - Support software-fallback for unsupported hardware AES lengths --- components/mbedtls/CMakeLists.txt | 12 +-- components/mbedtls/Kconfig | 27 ++---- .../config/mbedtls_preset_default.conf | 2 - .../config/mbedtls_preset_minimal.conf | 1 - components/mbedtls/mbedtls | 2 +- .../mbedtls/port/include/mbedtls/esp_config.h | 36 ++------ .../esp_aes/psa_crypto_driver_esp_aes.c | 14 +-- .../esp_aes/psa_crypto_driver_esp_aes_gcm.c | 4 +- .../include/psa_crypto_driver_esp_aes_gcm.h | 2 +- .../mbedtls/test_apps/main/test_psa_aes.c | 76 ++++++++++++++- .../mbedtls/test_apps/main/test_psa_cipher.c | 92 +++++++++++++++++++ ...t_use_with_psa.sdkconfig.ci.mbedtls_config | 2 - tools/ldgen/samples/sdkconfig | 5 - 13 files changed, 197 insertions(+), 78 deletions(-) create mode 100644 components/mbedtls/test_apps/main/test_psa_cipher.c diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 891c8dd9fb..9db36e5127 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -343,6 +343,7 @@ if(CONFIG_SOC_AES_SUPPORTED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_xts.c" "${COMPONENT_DIR}/port/aes/esp_aes_common.c" "${COMPONENT_DIR}/port/aes/esp_aes.c" + "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c" ) endif() @@ -393,17 +394,14 @@ if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES) target_compile_definitions(tfpsacrypto PRIVATE ESP_AES_DRIVER_ENABLED) target_include_directories(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/include/aes") target_sources(tfpsacrypto PRIVATE - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c" - ) + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c" + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c" + ) if(CONFIG_MBEDTLS_HARDWARE_SHA) target_sources(tfpsacrypto PRIVATE - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c" + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c" ) endif() - if(CONFIG_SOC_AES_SUPPORT_GCM) - target_sources(tfpsacrypto PRIVATE "$ENV{IDF_PATH}/components/mbedtls/port/aes/esp_aes_gcm.c" - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c") - endif() endif() if(CONFIG_MBEDTLS_HARDWARE_ECC) diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 0ea2c25569..254a112b44 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -886,22 +886,6 @@ menu "mbedTLS" 3DES is vulnerable to the Sweet32 attack and should only be enabled if absolutely necessary. - config MBEDTLS_BLOWFISH_C - bool "Blowfish block cipher (read help)" - default n - help - Enables the Blowfish block cipher (not used for TLS sessions.) - - The Blowfish cipher is not used for mbedTLS TLS sessions but can be - used for other purposes. Read up on the limitations of Blowfish (including - Sweet32) before enabling. - - config MBEDTLS_XTEA_C - bool "XTEA block cipher" - default n - help - Enables the XTEA block cipher. - config MBEDTLS_CCM_C bool "CCM (Counter with CBC-MAC) block cipher modes" default y @@ -1427,6 +1411,15 @@ menu "mbedTLS" Note that if the ESP32 CPU is running at 240MHz, hardware AES does not offer any speed boost over software AES. + config MBEDTLS_AES_SOFT_FALLBACK + bool "Enable software fallback for AES" + default n + depends on MBEDTLS_HARDWARE_AES + help + Enable software fallback for AES. + This option is used to fallback to software implementation of AES if the + hardware AES does not support the requested operation. + config MBEDTLS_HARDWARE_GCM bool "Enable partially hardware accelerated GCM" depends on SOC_AES_SUPPORT_GCM && MBEDTLS_HARDWARE_AES @@ -1447,7 +1440,7 @@ menu "mbedTLS" Enable this config to support fallback to software definitions for a non-AES cipher GCM operation as we support hardware acceleration only for AES cipher. Some of the non-AES ciphers used in a GCM operation are DES, ARIA, CAMELLIA, - CHACHA20, BLOWFISH. + CHACHA20. If this config is disabled, performing a non-AES cipher GCM operation with the config MBEDTLS_HARDWARE_AES enabled will result in calculation of an diff --git a/components/mbedtls/config/mbedtls_preset_default.conf b/components/mbedtls/config/mbedtls_preset_default.conf index affbd1556e..8e7a211649 100644 --- a/components/mbedtls/config/mbedtls_preset_default.conf +++ b/components/mbedtls/config/mbedtls_preset_default.conf @@ -94,8 +94,6 @@ CONFIG_MBEDTLS_AES_C=y CONFIG_MBEDTLS_CAMELLIA_C=n CONFIG_MBEDTLS_ARIA_C=y CONFIG_MBEDTLS_DES_C=n -CONFIG_MBEDTLS_BLOWFISH_C=n -CONFIG_MBEDTLS_XTEA_C=n CONFIG_MBEDTLS_CCM_C=y CONFIG_MBEDTLS_CIPHER_MODE_CBC=y CONFIG_MBEDTLS_CIPHER_MODE_CFB=y diff --git a/components/mbedtls/config/mbedtls_preset_minimal.conf b/components/mbedtls/config/mbedtls_preset_minimal.conf index 59a375098d..5760b5a6e9 100644 --- a/components/mbedtls/config/mbedtls_preset_minimal.conf +++ b/components/mbedtls/config/mbedtls_preset_minimal.conf @@ -46,7 +46,6 @@ CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=n # Symmetric Ciphers CONFIG_MBEDTLS_ARIA_C=n -CONFIG_MBEDTLS_BLOWFISH_C=n CONFIG_MBEDTLS_CCM_C=n CONFIG_MBEDTLS_CIPHER_MODE_OFB=n CONFIG_MBEDTLS_CIPHER_MODE_XTS=y diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls index dd4bd6bf4e..504bb1dddc 160000 --- a/components/mbedtls/mbedtls +++ b/components/mbedtls/mbedtls @@ -1 +1 @@ -Subproject commit dd4bd6bf4e13d2bc9691171266af09822179629c +Subproject commit 504bb1dddc89fbb6410455368e9bc55ebe7b28e1 diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index 8e5b5b2ec3..7ea49d62b2 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -1812,19 +1812,6 @@ #undef MBEDTLS_BIGNUM_C #endif -/** - * \def MBEDTLS_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#ifdef CONFIG_MBEDTLS_BLOWFISH_C -#define MBEDTLS_BLOWFISH_C -#else -#undef MBEDTLS_BLOWFISH_C -#endif - /** * \def MBEDTLS_CAMELLIA_C * @@ -1879,7 +1866,7 @@ * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 */ #ifdef CONFIG_MBEDTLS_CAMELLIA_C -#define MBEDTLS_CAMELLIA_C +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 #else #undef MBEDTLS_CAMELLIA_C #undef PSA_WANT_KEY_TYPE_CAMELLIA @@ -1938,6 +1925,7 @@ #ifdef CONFIG_MBEDTLS_ARIA_C #define PSA_WANT_KEY_TYPE_ARIA 1 #else +#undef MBEDTLS_ARIA_C #undef PSA_WANT_KEY_TYPE_ARIA #endif @@ -1980,9 +1968,10 @@ * Module: library/chacha20.c */ #ifdef CONFIG_MBEDTLS_CHACHA20_C -#define MBEDTLS_CHACHA20_C +#define PSA_WANT_KEY_TYPE_CHACHA20 1 #else #undef MBEDTLS_CHACHA20_C +#undef PSA_WANT_KEY_TYPE_CHACHA20 #endif /** @@ -1995,9 +1984,10 @@ * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C */ #ifdef CONFIG_MBEDTLS_CHACHAPOLY_C -#define MBEDTLS_CHACHAPOLY_C +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 #else #undef MBEDTLS_CHACHAPOLY_C +#undef PSA_WANT_ALG_CHACHA20_POLY1305 #endif /** @@ -3035,20 +3025,6 @@ #undef MBEDTLS_X509_CSR_WRITE_C #endif -/** - * \def MBEDTLS_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -#ifdef CONFIG_MBEDTLS_XTEA_C -#define MBEDTLS_XTEA_C -#else -#undef MBEDTLS_XTEA_C -#endif - /* \} name SECTION: mbed TLS modules */ /** diff --git a/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c b/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c index ad18760de1..a44c584e9c 100644 --- a/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c +++ b/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -458,10 +458,10 @@ static psa_status_t esp_crypto_aes_setup( goto exit; } - // if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) { - // status = PSA_ERROR_INVALID_ARGUMENT; - // goto exit; - // } + if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } switch (alg) { case PSA_ALG_ECB_NO_PADDING: @@ -529,8 +529,6 @@ psa_status_t esp_aes_cipher_encrypt( memset(&esp_aes_driver_ctx, 0, sizeof(esp_aes_operation_t)); size_t update_output_length, finish_output_length; - // ESP_LOGI("esp_aes_cipher_encrypt", "Starting encryption"); - status = esp_aes_cipher_encrypt_setup(&esp_aes_driver_ctx, attributes, key_buffer, key_buffer_size, alg); @@ -642,8 +640,6 @@ exit: esp_crypto_aes_abort(&esp_aes_driver_ctx); } - // printf("AES decryption finished with status: %ld\n", status); - return status; } diff --git a/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c b/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c index 7ccf1b1dc9..bd7e4cd335 100644 --- a/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c +++ b/components/mbedtls/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c @@ -14,7 +14,7 @@ #include "../include/psa_crypto_driver_esp_aes_contexts.h" // #ifdef ESP_MBEDTLS_AES_ACCEL -#if (defined(ESP_AES_DRIVER_ENABLED) || defined(MBEDTLS_HARDWARE_GCM)) +#if defined(ESP_AES_DRIVER_ENABLED) #define ESP_AES_GCM_TAG_LENGTH 16 @@ -271,4 +271,4 @@ exit: return status; } // #endif /* ESP_MBEDTLS_AES_ACCEL */ -#endif /* ESP_AES_DRIVER_ENABLED && MBEDTLS_HARDWARE_GCM */ +#endif /* ESP_AES_DRIVER_ENABLED */ diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_aes_gcm.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_aes_gcm.h index baf4504bc3..f8c18b068e 100644 --- a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_aes_gcm.h +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_aes_gcm.h @@ -12,7 +12,7 @@ extern "C" { #endif -#if (defined(ESP_AES_DRIVER_ENABLED) || defined(MBEDTLS_HARDWARE_GCM)) +#if defined(ESP_AES_DRIVER_ENABLED) #include "psa/crypto.h" #include "psa_crypto_driver_esp_aes_contexts.h" diff --git a/components/mbedtls/test_apps/main/test_psa_aes.c b/components/mbedtls/test_apps/main/test_psa_aes.c index b58e78c76e..a85d55a5d5 100644 --- a/components/mbedtls/test_apps/main/test_psa_aes.c +++ b/components/mbedtls/test_apps/main/test_psa_aes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -867,3 +867,77 @@ TEST_CASE("PSA AES-CBC one-shot", "[psa-aes]") /* Destroy the key */ psa_destroy_key(key_id); } + +static const uint8_t key_192[24] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, +}; + +TEST_CASE("PSA AES-CBC-192", "[psa-aes]") +{ + const size_t SZ = 1008; + const size_t iv_SZ = 16; + + const uint8_t expected_cipher_end[] = { + 0x57, 0x6a, 0x75, 0xb4, 0x5d, 0xbc, 0x96, 0xf8, + 0xa4, 0xb7, 0xb6, 0x0c, 0x6b, 0xa5, 0x1e, 0x02, + }; + + const uint8_t iv_seed[] = { + 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, + 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, + }; + + uint8_t iv[iv_SZ]; + uint8_t *plaintext = malloc(SZ); + uint8_t *ciphertext = malloc(SZ); + uint8_t *decryptedtext = malloc(SZ); + + memcpy(iv, iv_seed, iv_SZ); + memset(plaintext, 0x3A, SZ); + memset(decryptedtext, 0x0, SZ); + + psa_key_id_t key_id; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_CBC_NO_PADDING); + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, 192); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_192, sizeof(key_192), &key_id)); + psa_reset_key_attributes(&attributes); + + psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT; + size_t out_len = 0, total_out = 0; + + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, PSA_ALG_CBC_NO_PADDING)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ)); + + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext, SZ, ciphertext, SZ, &out_len)); + total_out += out_len; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out, SZ - total_out, &out_len)); + total_out += out_len; + TEST_ASSERT_EQUAL_size_t(SZ, total_out); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - sizeof(expected_cipher_end), sizeof(expected_cipher_end)); + + psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT; + total_out = 0; + memcpy(iv, iv_seed, iv_SZ); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, PSA_ALG_CBC_NO_PADDING)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ)); + + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext, SZ, decryptedtext, SZ, &out_len)); + total_out += out_len; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out, SZ - total_out, &out_len)); + total_out += out_len; + TEST_ASSERT_EQUAL_size_t(SZ, total_out); + TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); + + psa_cipher_abort(&enc_op); + psa_cipher_abort(&dec_op); + psa_destroy_key(key_id); + + free(plaintext); + free(ciphertext); + free(decryptedtext); +} diff --git a/components/mbedtls/test_apps/main/test_psa_cipher.c b/components/mbedtls/test_apps/main/test_psa_cipher.c new file mode 100644 index 0000000000..5b5c8e21da --- /dev/null +++ b/components/mbedtls/test_apps/main/test_psa_cipher.c @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include "psa/crypto.h" +#include "unity.h" +#include "esp_log.h" + +/* + ARIA-256-ECB Encrypt - RFC 5794 test vector + Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f + Input: 00112233445566778899aabbccddeeff + Output:f92bd7c79fb72e2f2b8f80c1972d24fc +*/ + +static const uint8_t aria_256_key[32] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, + 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f +}; + +static const uint8_t aria_ecb_input[16] = { + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77, + 0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff +}; + +static const uint8_t aria_ecb_expected_output[16] = { + 0xf9,0x2b,0xd7,0xc7,0x9f,0xb7,0x2e,0x2f, + 0x2b,0x8f,0x80,0xc1,0x97,0x2d,0x24,0xfc +}; + +TEST_CASE("PSA ARIA-256-ECB encrypt test vector", "[psa][psa_cipher][aria]") +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + uint8_t output[16] = {0}; + size_t output_len = 0; + + status = psa_crypto_init(); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ARIA); + psa_set_key_bits(&key_attr, 256); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING); + + status = psa_import_key(&key_attr, aria_256_key, sizeof(aria_256_key), &key_id); + TEST_ASSERT_EQUAL_HEX32_MESSAGE(PSA_SUCCESS, status, "psa_import_key failed"); + + status = psa_cipher_encrypt( + key_id, + PSA_ALG_ECB_NO_PADDING, + aria_ecb_input, sizeof(aria_ecb_input), + output, sizeof(output), &output_len + ); + TEST_ASSERT_EQUAL_HEX32_MESSAGE(PSA_SUCCESS, status, "psa_cipher_encrypt failed"); + TEST_ASSERT_EQUAL_UINT_MESSAGE(sizeof(aria_ecb_expected_output), output_len, "Output length mismatch"); + TEST_ASSERT_EQUAL_UINT8_ARRAY(aria_ecb_expected_output, output, sizeof(aria_ecb_expected_output)); + psa_destroy_key(key_id); + + // Test decryption: decrypt the previously encrypted ciphertext and compare with original plaintext + uint8_t decrypted[16] = {0}; + size_t decrypted_len = 0; + + // To decrypt, we need a key with PSA_KEY_USAGE_DECRYPT usage + psa_key_attributes_t dec_key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&dec_key_attr, PSA_KEY_TYPE_ARIA); + psa_set_key_bits(&dec_key_attr, 256); + psa_set_key_usage_flags(&dec_key_attr, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&dec_key_attr, PSA_ALG_ECB_NO_PADDING); + + psa_key_id_t dec_key_id = 0; + status = psa_import_key(&dec_key_attr, aria_256_key, sizeof(aria_256_key), &dec_key_id); + TEST_ASSERT_EQUAL_HEX32_MESSAGE(PSA_SUCCESS, status, "psa_import_key (decrypt key) failed"); + + status = psa_cipher_decrypt( + dec_key_id, + PSA_ALG_ECB_NO_PADDING, + output, sizeof(output), + decrypted, sizeof(decrypted), &decrypted_len + ); + TEST_ASSERT_EQUAL_HEX32_MESSAGE(PSA_SUCCESS, status, "psa_cipher_decrypt failed"); + TEST_ASSERT_EQUAL_UINT_MESSAGE(sizeof(aria_ecb_input), decrypted_len, "Decrypted length mismatch"); + TEST_ASSERT_EQUAL_UINT8_ARRAY(aria_ecb_input, decrypted, sizeof(aria_ecb_input)); + + psa_destroy_key(dec_key_id); +} diff --git a/examples/protocols/https_request/dont_use_with_psa.sdkconfig.ci.mbedtls_config b/examples/protocols/https_request/dont_use_with_psa.sdkconfig.ci.mbedtls_config index 6db2b14061..f1d6d04766 100644 --- a/examples/protocols/https_request/dont_use_with_psa.sdkconfig.ci.mbedtls_config +++ b/examples/protocols/https_request/dont_use_with_psa.sdkconfig.ci.mbedtls_config @@ -49,8 +49,6 @@ CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=n # CONFIG_MBEDTLS_CAMELLIA_C=n CONFIG_MBEDTLS_DES_C=n -CONFIG_MBEDTLS_BLOWFISH_C=n -CONFIG_MBEDTLS_XTEA_C=n CONFIG_MBEDTLS_CCM_C=n CONFIG_MBEDTLS_GCM_C=n CONFIG_MBEDTLS_NIST_KW_C=n diff --git a/tools/ldgen/samples/sdkconfig b/tools/ldgen/samples/sdkconfig index b5bf78599b..8a24162a47 100644 --- a/tools/ldgen/samples/sdkconfig +++ b/tools/ldgen/samples/sdkconfig @@ -429,11 +429,6 @@ CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y CONFIG_MBEDTLS_AES_C=y CONFIG_MBEDTLS_CAMELLIA_C= CONFIG_MBEDTLS_DES_C= -CONFIG_MBEDTLS_RC4_DISABLED=y -CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= -CONFIG_MBEDTLS_RC4_ENABLED= -CONFIG_MBEDTLS_BLOWFISH_C= -CONFIG_MBEDTLS_XTEA_C= CONFIG_MBEDTLS_CCM_C=y CONFIG_MBEDTLS_GCM_C=y CONFIG_MBEDTLS_RIPEMD160_C= From 54a72063ef129f26c9d38fbac47101c1305bda66 Mon Sep 17 00:00:00 2001 From: Ashish Sharma Date: Tue, 6 Jan 2026 15:32:16 +0800 Subject: [PATCH 2/3] fix: fixes failing tee_basic example build --- .../mbedtls/esp_tee/esp_tee_mbedtls.cmake | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake index 91fb959acc..70596b4182 100644 --- a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake +++ b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake @@ -71,23 +71,24 @@ target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/ # AES implementation if(CONFIG_SOC_AES_SUPPORTED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes.c" - "${COMPONENT_DIR}/port/aes/dma/esp_aes_dma_core.c") - target_compile_definitions(tfpsacrypto PRIVATE ESP_AES_DRIVER_ENABLED) + "${COMPONENT_DIR}/port/aes/dma/esp_aes_dma_core.c" + "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c" + "${COMPONENT_DIR}/port/aes/esp_aes_common.c" + "${COMPONENT_DIR}/port/aes/esp_aes_xts.c") target_include_directories(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/include/aes") - if(CONFIG_MBEDTLS_HARDWARE_SHA) + if(CONFIG_MBEDTLS_HARDWARE_AES) + target_compile_definitions(tfpsacrypto PRIVATE ESP_AES_DRIVER_ENABLED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c" - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c" + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c" ) - endif() - if(CONFIG_SOC_AES_SUPPORT_GCM) - target_sources(tfpsacrypto PRIVATE "$ENV{IDF_PATH}/components/mbedtls/port/aes/esp_aes_gcm.c" - "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c") + if(CONFIG_MBEDTLS_HARDWARE_SHA) + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c" + ) + endif() endif() - target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_common.c" - "${COMPONENT_DIR}/port/aes/esp_aes_xts.c" - "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c") endif() # SHA implementation if(CONFIG_SOC_SHA_SUPPORTED) From 933dd7e02f27a3c6c4810af87dad04e017013b0a Mon Sep 17 00:00:00 2001 From: Ashish Sharma Date: Mon, 5 Jan 2026 16:35:48 +0800 Subject: [PATCH 3/3] feat: adds PSA MD5 driver support --- components/mbedtls/CMakeLists.txt | 11 +- .../mbedtls/esp_tee/esp_tee_mbedtls.cmake | 7 + components/mbedtls/mbedtls | 2 +- .../mbedtls/port/include/mbedtls/esp_config.h | 10 +- components/mbedtls/port/include/md/esp_md.h | 119 -------- components/mbedtls/port/include/md5_alt.h | 35 --- components/mbedtls/port/md/esp_md.c | 61 ---- .../esp_md/psa_crypto_driver_esp_md5.c | 101 +++++++ .../include/psa_crypto_driver_esp_md5.h | 51 ++++ components/mbedtls/test_apps/main/test_md5.c | 263 ++++++++++++++++++ 10 files changed, 434 insertions(+), 226 deletions(-) delete mode 100644 components/mbedtls/port/include/md/esp_md.h delete mode 100644 components/mbedtls/port/include/md5_alt.h delete mode 100644 components/mbedtls/port/md/esp_md.c create mode 100644 components/mbedtls/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c create mode 100644 components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_md5.h create mode 100644 components/mbedtls/test_apps/main/test_md5.c diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index 9db36e5127..1a30e84d0d 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -363,6 +363,13 @@ if(CONFIG_SOC_SHA_SUPPORTED) ) endif() +if(CONFIG_MBEDTLS_ROM_MD5) + target_compile_definitions(tfpsacrypto PRIVATE ESP_MD5_DRIVER_ENABLED) + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c" + ) +endif() + if(CONFIG_SOC_DIG_SIGN_SUPPORTED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/esp_ds/esp_rsa_sign_alt.c" @@ -448,10 +455,6 @@ CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) endif() endif() -# if(CONFIG_MBEDTLS_ROM_MD5) -# target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/md/esp_md.c") -# endif() - # if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL) # target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/mbedtls_rom/mbedtls_rom_osi.c") # target_link_libraries(${COMPONENT_LIB} PRIVATE "-u mbedtls_rom_osi_functions_init") diff --git a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake index 70596b4182..e5596d10e3 100644 --- a/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake +++ b/components/mbedtls/esp_tee/esp_tee_mbedtls.cmake @@ -102,6 +102,13 @@ if(CONFIG_SOC_SHA_SUPPORTED) "${COMPONENT_DIR}/port/sha/esp_sha.c") endif() +if(CONFIG_MBEDTLS_ROM_MD5) + target_compile_definitions(tfpsacrypto PRIVATE ESP_MD5_DRIVER_ENABLED) + target_sources(tfpsacrypto PRIVATE + "${COMPONENT_DIR}/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c" + ) +endif() + if(CONFIG_SOC_ECC_SUPPORTED) target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c" "${COMPONENT_DIR}/port/ecc/ecc_alt.c") diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls index 504bb1dddc..41dc25dd2f 160000 --- a/components/mbedtls/mbedtls +++ b/components/mbedtls/mbedtls @@ -1 +1 @@ -Subproject commit 504bb1dddc89fbb6410455368e9bc55ebe7b28e1 +Subproject commit 41dc25dd2f557cbb0ee0771e6c725b3621d65527 diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index 7ea49d62b2..c862bcd7ed 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -212,12 +212,10 @@ /* MBEDTLS_MDx_ALT to enable ROM MD support with software fallback. */ -/* TODO: IDF-15029 */ -// #ifdef CONFIG_MBEDTLS_ROM_MD5 -// #define MBEDTLS_MD5_ALT -// #else -// #undef MBEDTLS_MD5_ALT -// #endif +#ifdef CONFIG_MBEDTLS_ROM_MD5 +#define MBEDTLS_PSA_ACCEL_ALG_MD5 +#undef MBEDTLS_PSA_BUILTIN_ALG_MD5 +#endif /* The following MPI (bignum) functions have hardware support. * Uncommenting these macros will use the hardware-accelerated diff --git a/components/mbedtls/port/include/md/esp_md.h b/components/mbedtls/port/include/md/esp_md.h deleted file mode 100644 index 3d93dafa78..0000000000 --- a/components/mbedtls/port/include/md/esp_md.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "esp_rom_md5.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if CONFIG_IDF_TARGET_ESP32C2 -typedef struct mbedtls_md5_context mbedtls_md5_context; -#else -typedef struct MD5Context mbedtls_md5_context; -#endif - -/** - * \brief Initialize MD5 context - * - * \param ctx MD5 context to be initialized - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void esp_md5_init( mbedtls_md5_context *ctx ); - -/** - * \brief Clear MD5 context - * - * \param ctx MD5 context to be cleared - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void esp_md5_free( mbedtls_md5_context *ctx ); - -/** - * \brief Clone (the state of) an MD5 context - * - * \param dst The destination context - * \param src The context to be cloned - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -void esp_md5_clone( mbedtls_md5_context *dst, const mbedtls_md5_context *src ); - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - * - * \return 0 if successful - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int mbedtls_md5_starts( mbedtls_md5_context *ctx ); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \return 0 if successful - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int esp_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - * - * \return 0 if successful - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int esp_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); - -/** - * \brief MD5 process data block (internal use only) - * - * \param ctx MD5 context - * \param data buffer holding one block of data - * - * \return 0 if successful - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -int esp_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif diff --git a/components/mbedtls/port/include/md5_alt.h b/components/mbedtls/port/include/md5_alt.h deleted file mode 100644 index 788c6554eb..0000000000 --- a/components/mbedtls/port/include/md5_alt.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * md5_alt.h: MD5 block cipher - * - * SPDX-FileCopyrightText: The Mbed TLS Contributors - * - * SPDX-License-Identifier: Apache-2.0 - * - * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD - */ -#ifndef MD5_ALT_H -#define MD5_ALT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_MD5_ALT) -#include "md/esp_md.h" - -#define mbedtls_md5_init esp_md5_init -#define mbedtls_md5_update esp_md5_update -#define mbedtls_md5_finish esp_md5_finish -#define mbedtls_md5_starts esp_md5_starts - -#define mbedtls_md5_free esp_md5_free -#define mbedtls_md5_clone esp_md5_clone -#define mbedtls_internal_md5_process esp_md5_process - -#endif /* MBEDTLS_MD5_ALT */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/components/mbedtls/port/md/esp_md.c b/components/mbedtls/port/md/esp_md.c deleted file mode 100644 index eb54b5d85c..0000000000 --- a/components/mbedtls/port/md/esp_md.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include "mbedtls/md5.h" -#include "mbedtls/platform_util.h" - -#if defined(MBEDTLS_MD5_ALT) -#include "md/esp_md.h" - -int esp_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) -{ - esp_rom_md5_final(output, ctx); - - - return 0; -} - -int esp_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) -{ - esp_rom_md5_update(ctx, input, ilen); - - - return 0; -} - -void esp_md5_init( mbedtls_md5_context *ctx ) -{ - esp_rom_md5_init(ctx); -} - -int esp_md5_starts( mbedtls_md5_context *ctx ) -{ - esp_md5_init(ctx); - return 0; -} - -void esp_md5_free( mbedtls_md5_context *ctx ) -{ - if (ctx == NULL) { - return; - } - - mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); -} - -int esp_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) -{ - esp_md5_update(ctx, data, 64); - - return 0; -} - -void esp_md5_clone( mbedtls_md5_context *dst, const mbedtls_md5_context *src ) -{ - *dst = *src; -} -#endif diff --git a/components/mbedtls/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c b/components/mbedtls/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c new file mode 100644 index 0000000000..b903212465 --- /dev/null +++ b/components/mbedtls/port/psa_driver/esp_md/psa_crypto_driver_esp_md5.c @@ -0,0 +1,101 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "psa_crypto_driver_esp_md5.h" + +psa_status_t esp_md5_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + if (hash == NULL || hash_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (input_length > 0 && input == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (hash_size < PSA_HASH_LENGTH(PSA_ALG_MD5)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + if (alg != PSA_ALG_MD5) { + return PSA_ERROR_NOT_SUPPORTED; + } + md5_context_t operation = {0}; + esp_rom_md5_init(&operation); + esp_rom_md5_update(&operation, input, input_length); + esp_rom_md5_final(hash, &operation); + *hash_length = PSA_HASH_LENGTH(PSA_ALG_MD5); + return PSA_SUCCESS; +} + +psa_status_t esp_md5_hash_setup(md5_context_t *operation, + psa_algorithm_t alg) +{ + if (operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (alg != PSA_ALG_MD5) { + return PSA_ERROR_NOT_SUPPORTED; + } + esp_rom_md5_init(operation); + return PSA_SUCCESS; +} + +psa_status_t esp_md5_hash_update( + md5_context_t *operation, + const uint8_t *input, + size_t input_length ) +{ + if (operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (input_length > 0 && input == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + esp_rom_md5_update(operation, input, input_length); + return PSA_SUCCESS; +} + +psa_status_t esp_md5_hash_finish( + md5_context_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + if (operation == NULL || hash == NULL || hash_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + if (hash_size < PSA_HASH_LENGTH(PSA_ALG_MD5)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + esp_rom_md5_final(hash, operation); + *hash_length = PSA_HASH_LENGTH(PSA_ALG_MD5); + return PSA_SUCCESS; +} + +psa_status_t esp_md5_hash_abort(md5_context_t *operation) +{ + if (operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + memset(operation, 0, sizeof(*operation)); + return PSA_SUCCESS; +} + +psa_status_t esp_md5_hash_clone( + const md5_context_t *source_operation, + md5_context_t *target_operation) +{ + if (source_operation == NULL || target_operation == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memcpy(target_operation, source_operation, sizeof(md5_context_t)); + return PSA_SUCCESS; +} diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_md5.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_md5.h new file mode 100644 index 0000000000..943f4edd1d --- /dev/null +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_md5.h @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "psa/crypto.h" +#include "esp_rom_md5.h" + +#ifdef CONFIG_MBEDTLS_ROM_MD5 +#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#endif +#endif // CONFIG_MBEDTLS_ROM_MD5 + +psa_status_t esp_md5_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +psa_status_t esp_md5_hash_setup(md5_context_t *operation, + psa_algorithm_t alg); + +psa_status_t esp_md5_hash_update( + md5_context_t *operation, + const uint8_t *input, + size_t input_length ); + +psa_status_t esp_md5_hash_finish( + md5_context_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +psa_status_t esp_md5_hash_abort(md5_context_t *operation); + +psa_status_t esp_md5_hash_clone( + const md5_context_t *source_operation, + md5_context_t *target_operation); + +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/test_apps/main/test_md5.c b/components/mbedtls/test_apps/main/test_md5.c new file mode 100644 index 0000000000..979db320f2 --- /dev/null +++ b/components/mbedtls/test_apps/main/test_md5.c @@ -0,0 +1,263 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "psa/crypto.h" +#include "esp_types.h" +#include "esp_log.h" +#include "ccomp_timer.h" +#include "unity.h" +#include "test_utils.h" +#include "esp_heap_caps.h" +#include "test_mbedtls_utils.h" + +#define TAG "md5_test" +#define MD5_HASH_LEN 16 + +TEST_CASE("Test PSA MD5 with known test vectors", "[hw_crypto][psa]") +{ + ESP_LOGI(TAG, "Testing MD5 implementation with known test vectors"); + + uint8_t input[128] = {0}; + for (int i = 0; i < 128; i++) { + input[i] = i; + } + + uint8_t hash_output[MD5_HASH_LEN] = {0}; + + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + size_t hash_len = 0; + + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS); + status = psa_hash_update(&operation, input, sizeof(input)); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS); + status = psa_hash_finish(&operation, hash_output, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(status, PSA_SUCCESS); + + uint8_t expected_hash[MD5_HASH_LEN] = { + 0x37, 0xEF, 0xF0, 0x18, 0x66, 0xBA, 0x3F, 0x53, 0x84, 0x21, 0xB3, 0x0B, 0x7C, 0xBE, 0xFC, 0xAC + }; + + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_hash, hash_output, MD5_HASH_LEN); +} + +TEST_CASE("Test PSA MD5 error cases", "[hw_crypto][psa]") +{ + ESP_LOGI(TAG, "Testing MD5 error handling"); + + uint8_t input[64] = {0}; + uint8_t hash_output[MD5_HASH_LEN] = {0}; + size_t hash_len = 0; + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status; + + // Test 1: NULL hash buffer in hash_compute + status = psa_hash_compute(PSA_ALG_MD5, input, sizeof(input), NULL, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status); + + // Test 2: NULL input with non-zero length in hash_compute + status = psa_hash_compute(PSA_ALG_MD5, NULL, 10, hash_output, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status); + + // Test 3: Buffer too small in hash_compute + status = psa_hash_compute(PSA_ALG_MD5, input, sizeof(input), hash_output, MD5_HASH_LEN - 1, &hash_len); + TEST_ASSERT_EQUAL(PSA_ERROR_BUFFER_TOO_SMALL, status); + + // Test 4: NULL input with non-zero length in hash_update + operation = psa_hash_operation_init(); + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_update(&operation, NULL, 10); + TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status); + psa_hash_abort(&operation); + + // Test 5: NULL hash buffer in hash_finish + operation = psa_hash_operation_init(); + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_finish(&operation, NULL, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_ARGUMENT, status); + psa_hash_abort(&operation); + + // Test 6: Buffer too small in hash_finish + operation = psa_hash_operation_init(); + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_update(&operation, input, sizeof(input)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_finish(&operation, hash_output, 8, &hash_len); + TEST_ASSERT_EQUAL(PSA_ERROR_BUFFER_TOO_SMALL, status); + psa_hash_abort(&operation); + + // Test 7: Multiple aborts should be safe + operation = psa_hash_operation_init(); + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_abort(&operation); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_abort(&operation); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + ESP_LOGI(TAG, "All MD5 error cases passed"); +} + +TEST_CASE("Test PSA MD5 clone operation", "[hw_crypto][psa]") +{ + ESP_LOGI(TAG, "Testing MD5 clone operation"); + + uint8_t input_part1[32]; + uint8_t input_part2[32]; + for (int i = 0; i < 32; i++) { + input_part1[i] = i; + input_part2[i] = i + 32; + } + + uint8_t hash_output1[MD5_HASH_LEN] = {0}; + uint8_t hash_output2[MD5_HASH_LEN] = {0}; + size_t hash_len1 = 0, hash_len2 = 0; + psa_hash_operation_t operation1 = PSA_HASH_OPERATION_INIT; + psa_hash_operation_t operation2 = PSA_HASH_OPERATION_INIT; + psa_status_t status; + + // Setup and update first operation + status = psa_hash_setup(&operation1, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_update(&operation1, input_part1, sizeof(input_part1)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // Clone the operation + status = psa_hash_clone(&operation1, &operation2); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // Continue both operations with the same data + status = psa_hash_update(&operation1, input_part2, sizeof(input_part2)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_update(&operation2, input_part2, sizeof(input_part2)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // Finish both operations + status = psa_hash_finish(&operation1, hash_output1, MD5_HASH_LEN, &hash_len1); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_finish(&operation2, hash_output2, MD5_HASH_LEN, &hash_len2); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // Both should produce the same hash + TEST_ASSERT_EQUAL_HEX8_ARRAY(hash_output1, hash_output2, MD5_HASH_LEN); + + ESP_LOGI(TAG, "MD5 clone operation test passed"); +} + +TEST_CASE("Test PSA MD5 with zero-length input", "[hw_crypto][psa]") +{ + ESP_LOGI(TAG, "Testing MD5 with zero-length input"); + + uint8_t hash_output[MD5_HASH_LEN] = {0}; + size_t hash_len = 0; + psa_status_t status; + + // Empty string MD5 hash: d41d8cd98f00b204e9800998ecf8427e + uint8_t expected_hash[MD5_HASH_LEN] = { + 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E + }; + + // Test with hash_compute + status = psa_hash_compute(PSA_ALG_MD5, NULL, 0, hash_output, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(MD5_HASH_LEN, hash_len); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_hash, hash_output, MD5_HASH_LEN); + + // Test with hash_setup/update/finish + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + memset(hash_output, 0, MD5_HASH_LEN); + + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_update(&operation, NULL, 0); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + status = psa_hash_finish(&operation, hash_output, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(MD5_HASH_LEN, hash_len); + TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_hash, hash_output, MD5_HASH_LEN); + + ESP_LOGI(TAG, "Zero-length input test passed"); +} + +TEST_CASE("Test PSA MD5 incremental updates", "[hw_crypto][psa]") +{ + ESP_LOGI(TAG, "Testing MD5 incremental updates"); + + uint8_t input[128]; + for (int i = 0; i < 128; i++) { + input[i] = i; + } + + uint8_t hash_full[MD5_HASH_LEN] = {0}; + uint8_t hash_incremental[MD5_HASH_LEN] = {0}; + size_t hash_len = 0; + psa_status_t status; + + // Compute hash in one go + status = psa_hash_compute(PSA_ALG_MD5, input, sizeof(input), hash_full, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // Compute hash incrementally in small chunks + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + for (int i = 0; i < 128; i += 16) { + status = psa_hash_update(&operation, input + i, 16); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + } + + status = psa_hash_finish(&operation, hash_incremental, MD5_HASH_LEN, &hash_len); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // Both methods should produce the same hash + TEST_ASSERT_EQUAL_HEX8_ARRAY(hash_full, hash_incremental, MD5_HASH_LEN); + + ESP_LOGI(TAG, "Incremental updates test passed"); +} + +TEST_CASE("psa MD5 performance", "[mbedtls]") +{ + const unsigned CALLS = 256; + const unsigned CALL_SZ = 16 * 1024; + float elapsed_usec; + uint8_t hash_output[MD5_HASH_LEN] = {0}; + + psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + psa_status_t status = psa_hash_setup(&operation, PSA_ALG_MD5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + // allocate internal memory + uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buf); + memset(buf, 0x55, CALL_SZ); + + ccomp_timer_start(); + for (int c = 0; c < CALLS; c++) { + status = psa_hash_update(&operation, buf, CALL_SZ); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + } + size_t hash_length; + status = psa_hash_finish(&operation, hash_output, MD5_HASH_LEN, &hash_length); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + elapsed_usec = ccomp_timer_stop(); + free(buf); + + const char *expected_hash = "9a9819e47b2014589ae2057458664df7"; + char hash_str[MD5_HASH_LEN * 2 + 1]; + utils_bin2hex(hash_str, sizeof(hash_str), hash_output, MD5_HASH_LEN); + + TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str); + + float mb_sec = (CALL_SZ * CALLS) / elapsed_usec; + printf("MD5 rate %.3fMB/sec\n", mb_sec); +}