feat(mbedtls): adds AES drivers with PSA

This commit is contained in:
Ashish Sharma
2025-12-19 07:28:28 +08:00
parent e629ab299c
commit 7d17e8a024
36 changed files with 3795 additions and 213 deletions
+2 -3
View File
@@ -25,9 +25,8 @@ The following table shows ESP-IDF support of Espressif SoCs where ![alt text][pr
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) | |ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|ESP32-H2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) | |ESP32-H2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) | |ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|ESP32-C5 | | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) | |ESP32-C5 | | | | |![alt text][supported] |![alt text][supported] |since v5.5.1, [Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|ESP32-C61 | | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) | |ESP32-C61 | | | | |![alt text][supported] |![alt text][supported] |since v5.5.1, [Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|ESP32-H4 | | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-H4) |
[supported]: https://img.shields.io/badge/-supported-green "supported" [supported]: https://img.shields.io/badge/-supported-green "supported"
[preview]: https://img.shields.io/badge/-preview-orange "preview" [preview]: https://img.shields.io/badge/-preview-orange "preview"
+3 -4
View File
@@ -24,10 +24,9 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) | |ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) | |ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) | |ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) | |ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|ESP32-C5 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) | |ESP32-C5 | | | | |![alt text][supported] |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|ESP32-C61 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) | |ESP32-C61 | | | | |![alt text][supported] |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|ESP32-H4 | | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-H4) |
[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported" [supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported"
[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview" [preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview"
+2 -3
View File
@@ -666,9 +666,8 @@ esp_err_t esp_mbedtls_server_session_ticket_ctx_init(esp_tls_server_session_tick
int ret; int ret;
esp_err_t esp_ret; esp_err_t esp_ret;
if ((ret = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx, if ((ret = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx,
mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE, PSA_ALG_GCM, PSA_KEY_TYPE_AES, 256,
MBEDTLS_CIPHER_AES_256_GCM, 86400)) != 0) {
CONFIG_ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT)) != 0) {
ESP_LOGE(TAG, "mbedtls_ssl_ticket_setup returned -0x%04X", -ret); ESP_LOGE(TAG, "mbedtls_ssl_ticket_setup returned -0x%04X", -ret);
mbedtls_print_error_msg(ret); mbedtls_print_error_msg(ret);
esp_ret = ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED; esp_ret = ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED;
@@ -54,12 +54,28 @@ static void test_cbc_aes(size_t buffer_size, const uint8_t expected_cipher_end[3
// Encrypt // Encrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cbc(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, ciphertext)); #ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_cbc(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, ciphertext);
}
else
#endif
{
aes_crypt_cbc_block(ESP_AES_ENCRYPT, key_bits / 8, key_256, buffer_size, nonce, plaintext, ciphertext);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt // Decrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cbc(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, ciphertext, decryptedtext)); #ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_cbc(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, ciphertext, decryptedtext);
}
else
#endif
{
aes_crypt_cbc_block(ESP_AES_DECRYPT, key_bits / 8, key_256, buffer_size, nonce, ciphertext, decryptedtext);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx); esp_aes_free(&ctx);
@@ -92,13 +108,29 @@ static void test_ctr_aes(size_t buffer_size, const uint8_t expected_cipher_end[3
// Encrypt // Encrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, plaintext, ciphertext)); #ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, plaintext, ciphertext);
}
else
#endif
{
aes_crypt_ctr_block(key_bits / 8, key_256, buffer_size, &nc_off, nonce, stream_block, plaintext, ciphertext);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt // Decrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
nc_off = 0; nc_off = 0;
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, ciphertext, decryptedtext)); #ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, ciphertext, decryptedtext);
}
else
#endif
{
aes_crypt_ctr_block(key_bits / 8, key_256, buffer_size, &nc_off, nonce, stream_block, ciphertext, decryptedtext);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx); esp_aes_free(&ctx);
@@ -131,13 +163,13 @@ static void test_ofb_aes(size_t buffer_size, const uint8_t expected_cipher_end[3
// Encrypt // Encrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, plaintext, ciphertext)); esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, plaintext, ciphertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt // Decrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
nc_off = 0; nc_off = 0;
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, ciphertext, decryptedtext)); esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, ciphertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx); esp_aes_free(&ctx);
@@ -168,12 +200,12 @@ static void test_cfb8_aes(size_t buffer_size, const uint8_t expected_cipher_end[
// Encrypt // Encrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb8(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, ciphertext)); esp_aes_crypt_cfb8(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, ciphertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt // Decrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb8(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, ciphertext, decryptedtext)); esp_aes_crypt_cfb8(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, ciphertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx); esp_aes_free(&ctx);
@@ -205,13 +237,13 @@ static void test_cfb128_aes(size_t buffer_size, const uint8_t expected_cipher_en
// Encrypt // Encrypt
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb128(&ctx, ESP_AES_ENCRYPT, buffer_size, &nc_off, nonce, plaintext, ciphertext)); esp_aes_crypt_cfb128(&ctx, ESP_AES_ENCRYPT, buffer_size, &nc_off, nonce, plaintext, ciphertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt // Decrypt
nc_off = 0; nc_off = 0;
memcpy(nonce, iv, 16); memcpy(nonce, iv, 16);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb128(&ctx, ESP_AES_DECRYPT, buffer_size, &nc_off, nonce, ciphertext, decryptedtext)); esp_aes_crypt_cfb128(&ctx, ESP_AES_DECRYPT, buffer_size, &nc_off, nonce, ciphertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size); TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx); esp_aes_free(&ctx);
@@ -222,7 +254,7 @@ static void test_cfb128_aes(size_t buffer_size, const uint8_t expected_cipher_en
heap_caps_free(decryptedtext); heap_caps_free(decryptedtext);
} }
#if SOC_GCM_SUPPORTED #if CONFIG_SOC_AES_SUPPORT_GCM
#define CIPHER_ID_AES 2 #define CIPHER_ID_AES 2
static void test_gcm_aes(size_t length, const uint8_t expected_last_block[16], const uint8_t expected_tag[16]) static void test_gcm_aes(size_t length, const uint8_t expected_last_block[16], const uint8_t expected_tag[16])
{ {
@@ -273,6 +305,7 @@ static void test_gcm_aes(size_t length, const uint8_t expected_last_block[16], c
} }
#endif /* SOC_GCM_SUPPORTED */ #endif /* SOC_GCM_SUPPORTED */
#endif /* SOC_AES_SUPPORT_DMA */ #endif /* SOC_AES_SUPPORT_DMA */
#endif // CONFIG_SOC_AES_SUPPORT_GCM
TEST(aes, cbc_aes_256_block_test) TEST(aes, cbc_aes_256_block_test)
{ {
@@ -339,7 +372,7 @@ TEST(aes, cfb128_aes_256_long_dma_test)
#endif #endif
#if SOC_GCM_SUPPORTED #if CONFIG_SOC_AES_SUPPORT_GCM
TEST(aes, gcm_aes_dma_test) TEST(aes, gcm_aes_dma_test)
{ {
size_t length = 16; size_t length = 16;
@@ -372,6 +405,7 @@ TEST(aes, gcm_aes_long_dma_test)
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */ #endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
#endif /* SOC_GCM_SUPPORTED */ #endif /* SOC_GCM_SUPPORTED */
#endif /* SOC_AES_SUPPORT_DMA */ #endif /* SOC_AES_SUPPORT_DMA */
#endif /* CONFIG_SOC_AES_SUPPORT_GCM */
TEST_GROUP_RUNNER(aes) TEST_GROUP_RUNNER(aes)
{ {
@@ -390,8 +424,9 @@ TEST_GROUP_RUNNER(aes)
RUN_TEST_CASE(aes, cfb8_aes_256_long_dma_test); RUN_TEST_CASE(aes, cfb8_aes_256_long_dma_test);
RUN_TEST_CASE(aes, cfb128_aes_256_long_dma_test); RUN_TEST_CASE(aes, cfb128_aes_256_long_dma_test);
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */ #endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
#if SOC_GCM_SUPPORTED #if CONFIG_SOC_AES_SUPPORT_GCM
RUN_TEST_CASE(aes, gcm_aes_dma_test); RUN_TEST_CASE(aes, gcm_aes_dma_test);
#endif /* CONFIG_SOC_AES_SUPPORT_GCM */
#if CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT #if CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT
RUN_TEST_CASE(aes, gcm_aes_long_dma_test); RUN_TEST_CASE(aes, gcm_aes_long_dma_test);
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */ #endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
+25 -7
View File
@@ -177,7 +177,7 @@ endif()
# Core libraries from the mbedTLS project # Core libraries from the mbedTLS project
set(mbedtls_targets mbedtls mbedx509 tfpsacrypto builtin) set(mbedtls_targets mbedtls mbedx509 tfpsacrypto builtin)
if(CONFIG_MBEDTLS_HARDWARE_SHA) if(CONFIG_MBEDTLS_HARDWARE_SHA OR CONFIG_MBEDTLS_HARDWARE_AES)
list(APPEND include_dirs "${COMPONENT_DIR}/port/psa_driver/include") list(APPEND include_dirs "${COMPONENT_DIR}/port/psa_driver/include")
target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include") target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include")
endif() endif()
@@ -268,7 +268,7 @@ if(SHA_PERIPHERAL_TYPE STREQUAL "core")
elseif(CONFIG_SOC_SHA_CRYPTO_DMA) elseif(CONFIG_SOC_SHA_CRYPTO_DMA)
set(SHA_CORE_SRCS "${COMPONENT_DIR}/port/sha/core/esp_sha_crypto_dma_impl.c") set(SHA_CORE_SRCS "${COMPONENT_DIR}/port/sha/core/esp_sha_crypto_dma_impl.c")
endif() endif()
target_sources(tfpsacrypto PRIVATE "${SHA_CORE_SRCS}") target_sources(builtin PRIVATE "${SHA_CORE_SRCS}")
endif() endif()
if(AES_PERIPHERAL_TYPE STREQUAL "dma") if(AES_PERIPHERAL_TYPE STREQUAL "dma")
@@ -363,9 +363,18 @@ endif()
# ) # )
# endif() # endif()
# if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES) if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES)
# target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c") target_compile_definitions(tfpsacrypto PRIVATE ESP_AES_DRIVER_ENABLED)
# endif() 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_cmac.c"
)
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) # if(CONFIG_MBEDTLS_HARDWARE_ECC)
# target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c" # target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c"
@@ -424,10 +433,19 @@ if(CONFIG_COMPILER_STATIC_ANALYZER AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(tfpsacrypto PRIVATE "-fno-analyzer") target_compile_options(tfpsacrypto PRIVATE "-fno-analyzer")
endif() endif()
# If linkage_type is PUBLIC, use PRIVATE while setting compiler optimization flags
# as we don't want the optimization flags to modify other targets
if(linkage_type STREQUAL "PUBLIC")
set(compiler_linkage_type PRIVATE)
else()
set(compiler_linkage_type ${linkage_type})
endif()
if(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SIZE) if(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SIZE)
target_compile_options(${COMPONENT_LIB} INTERFACE "-Os") message(STATUS "Linkage type is ${linkage_type}")
target_compile_options(${COMPONENT_LIB} ${compiler_linkage_type} "-Os")
elseif(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SPEED) elseif(CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SPEED)
target_compile_options(${COMPONENT_LIB} INTERFACE "-O2") target_compile_options(${COMPONENT_LIB} ${compiler_linkage_type} "-O2")
endif() endif()
if(CONFIG_MBEDTLS_DYNAMIC_BUFFER) if(CONFIG_MBEDTLS_DYNAMIC_BUFFER)
+2 -2
View File
@@ -3,7 +3,7 @@ menu "mbedTLS"
menu "Core Configuration" menu "Core Configuration"
choice MBEDTLS_COMPILER_OPTIMIZATION choice MBEDTLS_COMPILER_OPTIMIZATION
prompt "Compiler optimization level" prompt "Compiler optimization level"
default MBEDTLS_COMPILER_OPTIMIZATION_NONE default MBEDTLS_COMPILER_OPTIMIZATION_SIZE
help help
This option allows you to select the compiler optimization level for mbedTLS. This option allows you to select the compiler optimization level for mbedTLS.
The default is set to the optimization level used by the rest of the ESP-IDF project. The default is set to the optimization level used by the rest of the ESP-IDF project.
@@ -1487,7 +1487,7 @@ menu "mbedTLS"
config MBEDTLS_HARDWARE_SHA config MBEDTLS_HARDWARE_SHA
bool "Enable hardware SHA acceleration" bool "Enable hardware SHA acceleration"
default y default n
depends on !SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_SHA_SUPPORTED depends on !SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_SHA_SUPPORTED
help help
Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS. Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS.
@@ -172,15 +172,6 @@
* \{ * \{
*/ */
/* The following units have ESP32 hardware support,
uncommenting each _ALT macro will use the
hardware-accelerated implementation. */
#ifdef CONFIG_MBEDTLS_HARDWARE_AES
#define MBEDTLS_AES_ALT
#else
#undef MBEDTLS_AES_ALT
#endif
#ifdef CONFIG_MBEDTLS_HARDWARE_AES #ifdef CONFIG_MBEDTLS_HARDWARE_AES
#define MBEDTLS_GCM_ALT #define MBEDTLS_GCM_ALT
#ifdef CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER #ifdef CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER
@@ -1968,6 +1959,31 @@
#undef MBEDTLS_AES_C #undef MBEDTLS_AES_C
#endif #endif
/* The following units have ESP32 hardware support,
uncommenting each _ALT macro will use the
hardware-accelerated implementation. */
#ifdef CONFIG_MBEDTLS_HARDWARE_AES
#define MBEDTLS_AES_ALT
#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
#undef MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING
#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
#undef MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
#define MBEDTLS_PSA_ACCEL_ALG_CCM
#undef MBEDTLS_PSA_BUILTIN_ALG_CCM
#define MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG
#undef MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG
#define MBEDTLS_PSA_ACCEL_ALG_CMAC
#undef MBEDTLS_PSA_BUILTIN_ALG_CMAC
#define MBEDTLS_PSA_ACCEL_ALG_CFB
#undef MBEDTLS_PSA_BUILTIN_ALG_CFB
#undef MBEDTLS_AES_C
// #define MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305
#define MBEDTLS_PSA_ACCEL_ALG_CTR
#undef MBEDTLS_PSA_BUILTIN_ALG_CTR
#else
#undef MBEDTLS_AES_ALT
#endif
/** /**
* \def MBEDTLS_ASN1_PARSE_C * \def MBEDTLS_ASN1_PARSE_C
* *
@@ -2950,24 +2966,23 @@
#endif #endif
/** /**
* \def MBEDTLS_SHA256_C * \def MBEDTLS_SHA512_C
* *
* Enable the SHA-224 and SHA-256 cryptographic hash algorithms. * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
* *
* Module: library/mbedtls_sha256.c * Module: library/sha512.c
* Caller: library/entropy.c * Caller: library/entropy.c
* library/mbedtls_md.c * library/md.c
* library/ssl_tls.c * library/ssl_tls.c
* library/ssl*_client.c * library/ssl_cookie.c
* library/ssl*_server.c=
* *
* This module adds support for SHA-224 and SHA-256. * This module adds support for SHA-384 and SHA-512.
* This module is required for the SSL/TLS 1.2 PRF function.
*/ */
#ifdef CONFIG_MBEDTLS_SHA256_C #ifdef CONFIG_MBEDTLS_SHA512_C
#define MBEDTLS_SHA256_C #define MBEDTLS_SHA512_C
#else #else
#undef MBEDTLS_SHA256_C #undef MBEDTLS_SHA512_C
#undef PSA_WANT_ALG_SHA_512
#endif #endif
/** /**
@@ -2992,23 +3007,56 @@
#endif #endif
/** /**
* \def MBEDTLS_SHA512_C * \def MBEDTLS_SHA256_C
* *
* Enable the SHA-384 and SHA-512 cryptographic hash algorithms. * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
* *
* Module: library/sha512.c * Module: library/mbedtls_sha256.c
* Caller: library/entropy.c * Caller: library/entropy.c
* library/md.c * library/mbedtls_md.c
* library/ssl_tls.c * library/ssl_tls.c
* library/ssl_cookie.c * library/ssl*_client.c
* library/ssl*_server.c=
* *
* This module adds support for SHA-384 and SHA-512. * This module adds support for SHA-224 and SHA-256.
* This module is required for the SSL/TLS 1.2 PRF function.
*/ */
#ifdef CONFIG_MBEDTLS_SHA512_C #ifdef CONFIG_MBEDTLS_SHA256_C
#define MBEDTLS_SHA512_C #define MBEDTLS_SHA256_C
#else #else
#undef MBEDTLS_SHA512_C #undef MBEDTLS_SHA256_C
#undef PSA_WANT_ALG_SHA_512 #endif
/* MBEDTLS_SHAxx_ALT to enable hardware SHA support
with software fallback.
*/
#ifdef CONFIG_MBEDTLS_HARDWARE_SHA
#define MBEDTLS_SHA1_ALT
#define MBEDTLS_SHA256_ALT
#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_1
#define MBEDTLS_PSA_ACCEL_ALG_SHA_224
#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_224
#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_256
#undef MBEDTLS_SHA1_C
#undef MBEDTLS_SHA256_C
#undef MBEDTLS_SHA224_C
#if SOC_SHA_SUPPORT_SHA512
#define MBEDTLS_PSA_ACCEL_ALG_SHA_512
#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_512
#define MBEDTLS_PSA_ACCEL_ALG_SHA_384
#undef MBEDTLS_PSA_BUILTIN_ALG_SHA_384
#undef MBEDTLS_SHA512_C
#undef MBEDTLS_SHA384_C
#define MBEDTLS_SHA512_ALT
#else
#undef MBEDTLS_SHA512_ALT
#endif
#else
#undef MBEDTLS_SHA1_ALT
#undef MBEDTLS_SHA256_ALT
#undef MBEDTLS_SHA512_ALT
#endif #endif
/** /**
@@ -10,52 +10,52 @@
#define MBEDTLS_PLATFORM_GET_ENTROPY_ALT #define MBEDTLS_PLATFORM_GET_ENTROPY_ALT
#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG #define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
#ifdef CONFIG_MBEDTLS_RIPEMD160_C // #ifdef CONFIG_MBEDTLS_RIPEMD160_C
#define MBEDTLS_RIPEMD160_C // #define MBEDTLS_RIPEMD160_C
#else // #else
#undef MBEDTLS_RIPEMD160_C // #undef MBEDTLS_RIPEMD160_C
#undef PSA_WANT_ALG_RIPEMD160 // #undef PSA_WANT_ALG_RIPEMD160
#endif // #endif
#if CONFIG_MBEDTLS_SHA1_C // #if CONFIG_MBEDTLS_SHA1_C
#define MBEDTLS_SHA1_C // #define MBEDTLS_SHA1_C
#else // #else
#undef MBEDTLS_SHA1_C // #undef MBEDTLS_SHA1_C
#undef PSA_WANT_ALG_SHA_1 // #undef PSA_WANT_ALG_SHA_1
#endif // #endif
#if CONFIG_MBEDTLS_SHA384_C // #if CONFIG_MBEDTLS_SHA384_C
#define MBEDTLS_SHA384_C // #define MBEDTLS_SHA384_C
#else // #else
#undef MBEDTLS_SHA384_C // #undef MBEDTLS_SHA384_C
#undef PSA_WANT_ALG_SHA_384 // #undef PSA_WANT_ALG_SHA_384
#endif // #endif
#if CONFIG_MBEDTLS_SHA512_C // #if CONFIG_MBEDTLS_SHA512_C
#define MBEDTLS_SHA512_C // #define MBEDTLS_SHA512_C
#else // #else
#undef MBEDTLS_SHA512_C // #undef MBEDTLS_SHA512_C
#undef PSA_WANT_ALG_SHA_512 // #undef PSA_WANT_ALG_SHA_512
#endif // #endif
#ifdef CONFIG_MBEDTLS_CAMELLIA_C // #ifdef CONFIG_MBEDTLS_CAMELLIA_C
#error "MBEDTLS_CAMELLIA_C defined in config" // #error "MBEDTLS_CAMELLIA_C defined in config"
#define MBEDTLS_CAMELLIA_C // #define MBEDTLS_CAMELLIA_C
#else // #else
#undef MBEDTLS_CAMELLIA_C // #undef MBEDTLS_CAMELLIA_C
#undef PSA_WANT_KEY_TYPE_CAMELLIA // #undef PSA_WANT_KEY_TYPE_CAMELLIA
#endif // #endif
#ifdef CONFIG_MBEDTLS_MD5_C // #ifdef CONFIG_MBEDTLS_MD5_C
#define MBEDTLS_MD5_C // #define MBEDTLS_MD5_C
#else // #else
#undef MBEDTLS_MD5_C // #undef MBEDTLS_MD5_C
#undef PSA_WANT_ALG_MD5 // #undef PSA_WANT_ALG_MD5
#endif // #endif
#ifdef CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED // #ifdef CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED // #define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#else // #else
#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED // #undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
#undef PSA_WANT_ECC_SECP_R1_384 // #undef PSA_WANT_ECC_SECP_R1_384
#endif // #endif
@@ -0,0 +1,674 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_aes.h"
#include "../include/psa_crypto_driver_esp_aes_contexts.h"
#include "esp_aes.h"
#include "psa_crypto_core.h"
#include "constant_time_internal.h"
static psa_status_t esp_crypto_aes_ecb_update(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
*output_length = 0;
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
if (esp_aes_driver_ctx->unprocessed_len > 0) {
/* Fill up to block size, and run the block if there's a full one. */
size_t bytes_to_copy = esp_aes_driver_ctx->block_length - esp_aes_driver_ctx->unprocessed_len;
if (input_length < bytes_to_copy) {
bytes_to_copy = input_length;
}
memcpy(&(esp_aes_driver_ctx->unprocessed_data[esp_aes_driver_ctx->unprocessed_len]), input, bytes_to_copy);
input_length -= bytes_to_copy;
input += bytes_to_copy;
esp_aes_driver_ctx->unprocessed_len += bytes_to_copy;
if (esp_aes_driver_ctx->unprocessed_len == esp_aes_driver_ctx->block_length) {
status = mbedtls_to_psa_error(esp_aes_crypt_ecb(ctx, esp_aes_driver_ctx->mode, esp_aes_driver_ctx->unprocessed_data, output));
if (status != PSA_SUCCESS) {
goto exit;
}
output += esp_aes_driver_ctx->block_length;
*output_length += esp_aes_driver_ctx->block_length;
esp_aes_driver_ctx->unprocessed_len = 0;
}
}
while (input_length >= esp_aes_driver_ctx->block_length) {
/* Run all full blocks we have, one by one */
status = mbedtls_to_psa_error(esp_aes_crypt_ecb(ctx, esp_aes_driver_ctx->mode, input, output));
if (status != PSA_SUCCESS) {
goto exit;
}
input_length -= esp_aes_driver_ctx->block_length;
input += esp_aes_driver_ctx->block_length;
output += esp_aes_driver_ctx->block_length;
*output_length += esp_aes_driver_ctx->block_length;
}
if (input_length > 0) {
/* Save unprocessed bytes for later processing */
memcpy(&(esp_aes_driver_ctx->unprocessed_data[esp_aes_driver_ctx->unprocessed_len]), input, input_length);
esp_aes_driver_ctx->unprocessed_len += input_length;
}
status = PSA_SUCCESS;
exit:
return status;
}
static psa_status_t esp_crypto_aes_cbc_update(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size,
size_t *output_length)
{
int ret = -1;
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
size_t copy_len = 0;
*output_length = 0;
/*
* If there is not enough data for a full block, cache it.
*/
if ((esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_DECRYPT &&
esp_aes_driver_ctx->aes_alg != PSA_ALG_CBC_NO_PADDING &&
input_length <= esp_aes_driver_ctx->block_length - esp_aes_driver_ctx->unprocessed_len) ||
(esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_DECRYPT &&
esp_aes_driver_ctx->aes_alg == PSA_ALG_CBC_NO_PADDING &&
input_length < esp_aes_driver_ctx->block_length - esp_aes_driver_ctx->unprocessed_len) ||
(esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_ENCRYPT &&
input_length < esp_aes_driver_ctx->block_length - esp_aes_driver_ctx->unprocessed_len)) {
memcpy(&(esp_aes_driver_ctx->unprocessed_data[esp_aes_driver_ctx->unprocessed_len]), input, input_length);
esp_aes_driver_ctx->unprocessed_len += input_length;
return PSA_SUCCESS;
}
/*
* Process cached data first
*/
if (esp_aes_driver_ctx->unprocessed_len != 0) {
copy_len = esp_aes_driver_ctx->block_length - esp_aes_driver_ctx->unprocessed_len;
memcpy(&(esp_aes_driver_ctx->unprocessed_data[esp_aes_driver_ctx->unprocessed_len]), input, copy_len);
ret = esp_aes_crypt_cbc(ctx,
esp_aes_driver_ctx->mode,
esp_aes_driver_ctx->block_length,
esp_aes_driver_ctx->iv,
esp_aes_driver_ctx->unprocessed_data,
output);
if (ret != 0) {
goto exit;
}
*output_length += esp_aes_driver_ctx->block_length;
output += esp_aes_driver_ctx->block_length;
esp_aes_driver_ctx->unprocessed_len = 0;
input += copy_len;
input_length -= copy_len;
}
/*
* Cache final, incomplete block
*/
if (input_length != 0) {
/* Encryption: only cache partial blocks
* Decryption w/ padding: always keep at least one whole block
* Decryption w/o padding: only cache partial blocks
*/
copy_len = input_length % esp_aes_driver_ctx->block_length;
if (copy_len == 0 &&
esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_DECRYPT &&
esp_aes_driver_ctx->aes_alg != PSA_ALG_CBC_NO_PADDING) {
copy_len = esp_aes_driver_ctx->block_length;
}
memcpy(esp_aes_driver_ctx->unprocessed_data, &(input[input_length - copy_len]), copy_len);
esp_aes_driver_ctx->unprocessed_len += copy_len;
input_length -= copy_len;
}
/*
* Process remaining full blocks
*/
if (input_length) {
ret = esp_aes_crypt_cbc(ctx, esp_aes_driver_ctx->mode,
input_length, esp_aes_driver_ctx->iv,
input,
output);
if (ret != 0) {
goto exit;
}
*output_length += input_length;
}
exit:
return mbedtls_to_psa_error(ret);
}
psa_status_t esp_crypto_aes_update(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size,
size_t *output_length)
{
int ret = -1;
size_t expected_output_size;
*output_length = 0;
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
if (!PSA_ALG_IS_STREAM_CIPHER(esp_aes_driver_ctx->aes_alg)) {
/* Take the unprocessed partial block left over from previous
* update calls, if any, plus the input to this call. Remove
* the last partial block, if any. You get the data that will be
* output in this call. */
expected_output_size = (esp_aes_driver_ctx->unprocessed_len + input_length) / esp_aes_driver_ctx->block_length * esp_aes_driver_ctx->block_length;
} else {
expected_output_size = input_length;
}
if (output_size < expected_output_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
if (input_length == 0) {
/* There is no input, nothing to be done */
*output_length = 0;
return PSA_SUCCESS;
}
else if (esp_aes_driver_ctx->aes_alg == PSA_ALG_ECB_NO_PADDING) {
/* esp_aes_crypt_ecb will only process a single block at a time in
* ECB mode. Abstract this away to match the PSA API behaviour. */
ret = esp_crypto_aes_ecb_update(esp_aes_driver_ctx,
input,
input_length,
output,
output_length);
} else {
if (input == output &&
(esp_aes_driver_ctx->unprocessed_len != 0 || input_length % esp_aes_driver_ctx->block_length)) {
ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
goto exit;
}
switch (esp_aes_driver_ctx->aes_alg) {
case PSA_ALG_CTR:
ret = esp_aes_crypt_ctr(ctx,
input_length,
&esp_aes_driver_ctx->unprocessed_len,
esp_aes_driver_ctx->iv,
esp_aes_driver_ctx->unprocessed_data,
input,
output);
*output_length = input_length;
break;
case PSA_ALG_CFB:
ret = esp_aes_crypt_cfb128(ctx,
esp_aes_driver_ctx->mode,
input_length,
&esp_aes_driver_ctx->unprocessed_len,
esp_aes_driver_ctx->iv,
input,
output);
*output_length = input_length;
break;
case PSA_ALG_OFB:
ret = esp_aes_crypt_ofb(ctx,
input_length,
&esp_aes_driver_ctx->unprocessed_len,
esp_aes_driver_ctx->iv,
input,
output);
*output_length = input_length;
break;
case PSA_ALG_CBC_NO_PADDING:
case PSA_ALG_CBC_PKCS7:
ret = esp_crypto_aes_cbc_update(esp_aes_driver_ctx,
input,
input_length,
output,
output_size,
output_length);
break;
default:
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
goto exit;
}
if (*output_length > output_size) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
}
exit:
return mbedtls_to_psa_error(ret);
}
/*
* PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
*/
static void add_pkcs_padding(unsigned char *output, size_t output_len,
size_t data_len)
{
size_t padding_len = output_len - data_len;
unsigned char i;
for (i = 0; i < padding_len; i++) {
output[data_len + i] = (unsigned char) padding_len;
}
}
static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
{
size_t i, pad_idx;
unsigned char padding_len;
if (NULL == input || NULL == data_len) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
padding_len = input[input_len - 1];
if (padding_len == 0 || padding_len > input_len) {
return MBEDTLS_ERR_CIPHER_INVALID_PADDING;
}
*data_len = input_len - padding_len;
mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
/* The number of bytes checked must be independent of padding_len,
* so pick input_len, which is usually 8 or 16 (one block) */
pad_idx = input_len - padding_len;
for (i = 0; i < input_len; i++) {
mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx);
mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len);
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different));
}
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
}
psa_status_t esp_crypto_aes_finish(
esp_aes_operation_t *esp_aes_driver_ctx,
uint8_t *output, size_t output_size,
size_t *output_length)
{
int ret = -1;
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
uint8_t temp_output_buffer[ESP_MBEDTLS_AES_MAX_BLOCK_LENGTH];
if (esp_aes_driver_ctx->unprocessed_len != 0) {
if (esp_aes_driver_ctx->aes_alg == PSA_ALG_ECB_NO_PADDING ||
esp_aes_driver_ctx->aes_alg == PSA_ALG_CBC_NO_PADDING) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
}
*output_length = 0;
switch (esp_aes_driver_ctx->aes_alg) {
case PSA_ALG_ECB_NO_PADDING:
case PSA_ALG_CTR:
case PSA_ALG_XTS:
case PSA_ALG_CFB:
case PSA_ALG_OFB:
status = PSA_SUCCESS;
break;
case PSA_ALG_CBC_PKCS7:
if (esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_ENCRYPT) {
if (esp_aes_driver_ctx->unprocessed_len != 0) {
add_pkcs_padding(esp_aes_driver_ctx->unprocessed_data, esp_aes_driver_ctx->block_length, esp_aes_driver_ctx->unprocessed_len);
}
} else if (esp_aes_driver_ctx->unprocessed_len != esp_aes_driver_ctx->block_length) {
/*
* For decrypt operations, expect a full block,
* or an empty block if no padding
*/
if (esp_aes_driver_ctx->unprocessed_len == 0) {
status = PSA_SUCCESS;
break;
}
return mbedtls_to_psa_error(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED);
}
ret = esp_aes_crypt_cbc(ctx, esp_aes_driver_ctx->mode,
esp_aes_driver_ctx->block_length,
esp_aes_driver_ctx->iv,
esp_aes_driver_ctx->unprocessed_data,
temp_output_buffer);
if (ret != 0) {
return mbedtls_to_psa_error(ret);
}
if (esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_DECRYPT) {
ret = get_pkcs_padding(temp_output_buffer, esp_aes_driver_ctx->block_length, output_length);
if (ret != 0) {
return mbedtls_to_psa_error(ret);
}
} else {
*output_length = esp_aes_driver_ctx->block_length;
}
status = PSA_SUCCESS;
break;
case PSA_ALG_CBC_NO_PADDING:
if (esp_aes_driver_ctx->mode == PSA_CRYPTO_DRIVER_ENCRYPT) {
if (esp_aes_driver_ctx->unprocessed_len == 0) {
status = PSA_SUCCESS;
break;
}
} else if (esp_aes_driver_ctx->unprocessed_len != esp_aes_driver_ctx->block_length) {
if (esp_aes_driver_ctx->unprocessed_len == 0) {
return PSA_SUCCESS;
}
return mbedtls_to_psa_error(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED);
}
ret = esp_aes_crypt_cbc(ctx, esp_aes_driver_ctx->mode,
esp_aes_driver_ctx->block_length,
esp_aes_driver_ctx->iv,
esp_aes_driver_ctx->unprocessed_data,
temp_output_buffer);
if (ret != 0) {
return mbedtls_to_psa_error(ret);
}
*output_length = esp_aes_driver_ctx->block_length;
status = PSA_SUCCESS;
break;
default:
status = mbedtls_to_psa_error(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE);
goto exit;
}
if (*output_length == 0) {
; /* Nothing to copy. Note that output may be NULL in this case. */
} else if (output_size >= *output_length) {
memcpy(output, temp_output_buffer, *output_length);
} else {
status = PSA_ERROR_BUFFER_TOO_SMALL;
}
exit:
mbedtls_platform_zeroize(temp_output_buffer, sizeof(temp_output_buffer));
return status;
}
psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_ctx)
{
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
if (ctx == NULL) {
return PSA_SUCCESS;
}
esp_aes_free(ctx);
free(ctx);
return PSA_SUCCESS;
}
psa_status_t esp_crypto_aes_set_iv(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *iv, size_t iv_length)
{
if (iv_length != PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, esp_aes_driver_ctx->aes_alg)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memcpy(esp_aes_driver_ctx->iv, iv, iv_length);
return PSA_SUCCESS;
}
static psa_status_t esp_crypto_aes_setup(
esp_aes_operation_t *esp_aes_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, psa_encrypt_or_decrypt_t mode)
{
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
if (!PSA_ALG_IS_CIPHER(alg)) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
// if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
// status = PSA_ERROR_INVALID_ARGUMENT;
// goto exit;
// }
switch (alg) {
case PSA_ALG_ECB_NO_PADDING:
case PSA_ALG_CBC_NO_PADDING:
case PSA_ALG_CBC_PKCS7:
case PSA_ALG_CTR:
case PSA_ALG_XTS:
case PSA_ALG_CFB:
case PSA_ALG_OFB:
break;
default:
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
esp_aes_context *ctx = (esp_aes_context *) malloc(sizeof(esp_aes_context));
if (ctx == NULL) {
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto exit;
}
esp_aes_init(ctx);
status = mbedtls_to_psa_error(esp_aes_setkey(ctx, key_buffer, key_buffer_size * 8));
if (status != PSA_SUCCESS) {
goto exit;
}
esp_aes_driver_ctx->aes_alg = alg;
esp_aes_driver_ctx->mode = mode;
esp_aes_driver_ctx->esp_aes_ctx = (void *) ctx;
esp_aes_driver_ctx->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 : PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES));
exit:
return status;
}
psa_status_t esp_aes_cipher_encrypt_setup(
esp_aes_operation_t *esp_aes_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return esp_crypto_aes_setup(esp_aes_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg, PSA_CRYPTO_DRIVER_ENCRYPT);
}
psa_status_t esp_aes_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *iv,
size_t iv_length,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_aes_operation_t esp_aes_driver_ctx;
memset(&esp_aes_driver_ctx, 0, sizeof(esp_aes_operation_t));
size_t update_output_length, finish_output_length;
status = esp_aes_cipher_encrypt_setup(&esp_aes_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (iv_length > 0) {
status = esp_crypto_aes_set_iv(&esp_aes_driver_ctx, iv, iv_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = esp_crypto_aes_update(&esp_aes_driver_ctx, input, input_length,
output, output_size,
&update_output_length);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_crypto_aes_finish(&esp_aes_driver_ctx,
mbedtls_buffer_offset(output, update_output_length),
output_size - update_output_length, &finish_output_length);
if (status != PSA_SUCCESS) {
goto exit;
}
*output_length = update_output_length + finish_output_length;
exit:
if (status == PSA_SUCCESS) {
status = esp_crypto_aes_abort(&esp_aes_driver_ctx);
} else {
esp_crypto_aes_abort(&esp_aes_driver_ctx);
}
return status;
}
psa_status_t esp_aes_cipher_decrypt_setup(
esp_aes_operation_t *esp_aes_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return esp_crypto_aes_setup(esp_aes_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg, PSA_CRYPTO_DRIVER_DECRYPT);
}
psa_status_t esp_aes_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_aes_operation_t esp_aes_driver_ctx;
memset(&esp_aes_driver_ctx, 0, sizeof(esp_aes_operation_t));
size_t olength, accumulated_length;
status = esp_aes_cipher_decrypt_setup(&esp_aes_driver_ctx, attributes,
key, key_length,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
uint8_t iv_length = PSA_CIPHER_IV_LENGTH(psa_get_key_type(attributes), alg);
if (iv_length > 0) {
status = esp_crypto_aes_set_iv(&esp_aes_driver_ctx,
input, iv_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = esp_crypto_aes_update(&esp_aes_driver_ctx,
mbedtls_buffer_offset_const(input, iv_length),
input_length - iv_length,
output, output_size, &olength);
if (status != PSA_SUCCESS) {
goto exit;
}
accumulated_length = olength;
status = esp_crypto_aes_finish(&esp_aes_driver_ctx,
mbedtls_buffer_offset(output, accumulated_length),
output_size - accumulated_length, &olength);
if (status != PSA_SUCCESS) {
goto exit;
}
*output_length = accumulated_length + olength;
exit:
if (status == PSA_SUCCESS) {
status = esp_crypto_aes_abort(&esp_aes_driver_ctx);
} else {
esp_crypto_aes_abort(&esp_aes_driver_ctx);
}
// printf("AES decryption finished with status: %ld\n", status);
return status;
}
psa_status_t esp_aes_cipher_set_iv(
esp_aes_operation_t *operation,
const uint8_t *iv,
size_t iv_length)
{
return esp_crypto_aes_set_iv(operation, iv, iv_length);
}
psa_status_t esp_aes_cipher_update(
esp_aes_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
return esp_crypto_aes_update(operation, input, input_length,
output, output_size, output_length);
}
psa_status_t esp_aes_cipher_finish(
esp_aes_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
return esp_crypto_aes_finish(operation, output, output_size, output_length);
}
psa_status_t esp_aes_cipher_abort(
esp_aes_operation_t *operation)
{
esp_aes_context *ctx = (esp_aes_context *) operation->esp_aes_ctx;
if (ctx == NULL) {
return PSA_SUCCESS;
}
esp_aes_free(ctx);
free(ctx);
return PSA_SUCCESS;
}
@@ -0,0 +1,272 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "esp_log.h"
#include "mbedtls/aes.h"
#include "psa_crypto_core.h"
// #include "mbedtls/cipher.h"
#include "aes/esp_aes_gcm.h"
#include "psa_crypto_driver_esp_aes_gcm.h"
#include "../include/psa_crypto_driver_esp_aes_contexts.h"
// #ifdef ESP_MBEDTLS_AES_ACCEL
#if (defined(ESP_AES_DRIVER_ENABLED) || defined(MBEDTLS_HARDWARE_GCM))
#define ESP_AES_GCM_TAG_LENGTH 16
static psa_status_t esp_crypto_aes_gcm_setup(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, psa_encrypt_or_decrypt_t mode)
{
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
if (alg != PSA_ALG_GCM) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
esp_gcm_context *ctx = (esp_gcm_context *) malloc(sizeof(esp_gcm_context));
if (ctx == NULL) {
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto exit;
}
esp_aes_gcm_init(ctx);
status = mbedtls_to_psa_error(esp_aes_gcm_setkey(ctx, MBEDTLS_CIPHER_ID_AES, key_buffer, key_buffer_size * 8));
if (status != PSA_SUCCESS) {
goto exit;
}
esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx = (void *) ctx;
esp_aes_gcm_driver_ctx->mode = mode;
exit:
return status;
}
psa_status_t esp_crypto_aes_gcm_encrypt_setup(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return esp_crypto_aes_gcm_setup(esp_aes_gcm_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg, PSA_CRYPTO_DRIVER_ENCRYPT);
}
psa_status_t esp_crypto_aes_gcm_decrypt_setup(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return esp_crypto_aes_gcm_setup(esp_aes_gcm_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg, PSA_CRYPTO_DRIVER_DECRYPT);
}
psa_status_t esp_crypto_aes_gcm_set_nonce(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const uint8_t *nonce,
size_t nonce_length)
{
esp_gcm_context *ctx = (esp_gcm_context *) esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx;
return mbedtls_to_psa_error(esp_aes_gcm_starts(ctx, esp_aes_gcm_driver_ctx->mode, nonce, nonce_length));
}
psa_status_t esp_crypto_aes_gcm_update_ad(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const uint8_t *aad,
size_t aad_length)
{
esp_gcm_context *ctx = (esp_gcm_context *) esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx;
return mbedtls_to_psa_error(esp_aes_gcm_update_ad(ctx, aad, aad_length));
}
psa_status_t esp_crypto_aes_gcm_update(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
size_t update_output_length = input_length;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_gcm_context *ctx = (esp_gcm_context *) esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx;
status = mbedtls_to_psa_error(esp_aes_gcm_update(ctx, input, input_length, output, output_size, &update_output_length));
if (status == PSA_SUCCESS) {
*output_length = update_output_length;
}
return status;
}
psa_status_t esp_crypto_aes_gcm_finish(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
uint8_t *output,
size_t output_size,
size_t *output_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t finish_output_size = 0;
if (tag_size < ESP_AES_GCM_TAG_LENGTH) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
esp_gcm_context *ctx = (esp_gcm_context *) esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx;
status = mbedtls_to_psa_error(esp_aes_gcm_finish(ctx, output, output_size, output_length, tag, tag_size));
if (status == PSA_SUCCESS) {
/* This will be zero for all supported algorithms currently, but left
* here for future support. */
*output_length = finish_output_size;
*tag_length = ESP_AES_GCM_TAG_LENGTH;
}
return status;
}
psa_status_t esp_crypto_aes_gcm_abort(esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx)
{
esp_gcm_context *ctx = (esp_gcm_context *) esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx;
if (ctx == NULL) {
return PSA_SUCCESS;
}
esp_aes_gcm_free(ctx);
free(ctx);
return PSA_SUCCESS;
}
psa_status_t esp_crypto_aes_gcm_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
{
uint8_t *tag = NULL;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_aes_gcm_operation_t esp_aes_gcm_driver_ctx;
memset(&esp_aes_gcm_driver_ctx, 0, sizeof(esp_aes_gcm_operation_t));
status = esp_crypto_aes_gcm_encrypt_setup(&esp_aes_gcm_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
/* For all currently supported modes, the tag is at the end of the
* ciphertext. */
if (ciphertext_size < (plaintext_length + ESP_AES_GCM_TAG_LENGTH)) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
tag = ciphertext + plaintext_length;
status = mbedtls_to_psa_error(
esp_aes_gcm_crypt_and_tag((esp_gcm_context *) esp_aes_gcm_driver_ctx.esp_aes_gcm_ctx,
PSA_CRYPTO_DRIVER_ENCRYPT,
plaintext_length,
nonce, nonce_length,
additional_data, additional_data_length,
plaintext, ciphertext,
ESP_AES_GCM_TAG_LENGTH, tag));
if (status == PSA_SUCCESS) {
*ciphertext_length = plaintext_length + ESP_AES_GCM_TAG_LENGTH;
}
exit:
esp_crypto_aes_gcm_abort(&esp_aes_gcm_driver_ctx);
return status;
}
/* Locate the tag in a ciphertext buffer containing the encrypted data
* followed by the tag. Return the length of the part preceding the tag in
* *plaintext_length. This is the size of the plaintext in modes where
* the encrypted data has the same size as the plaintext, such as
* CCM and GCM. */
static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
const uint8_t *ciphertext,
size_t ciphertext_length,
size_t plaintext_size,
const uint8_t **p_tag)
{
size_t payload_length;
if (tag_length > ciphertext_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
payload_length = ciphertext_length - tag_length;
if (payload_length > plaintext_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*p_tag = ciphertext + payload_length;
return PSA_SUCCESS;
}
psa_status_t esp_crypto_aes_gcm_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_aes_gcm_operation_t esp_aes_gcm_driver_ctx;
memset(&esp_aes_gcm_driver_ctx, 0, sizeof(esp_aes_gcm_operation_t));
const uint8_t *tag = NULL;
status = esp_crypto_aes_gcm_decrypt_setup(&esp_aes_gcm_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_aead_unpadded_locate_tag(ESP_AES_GCM_TAG_LENGTH, ciphertext, ciphertext_length, plaintext_size, &tag);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
esp_aes_gcm_auth_decrypt((esp_gcm_context *) esp_aes_gcm_driver_ctx.esp_aes_gcm_ctx,
ciphertext_length - ESP_AES_GCM_TAG_LENGTH,
nonce, nonce_length,
additional_data,
additional_data_length,
tag, ESP_AES_GCM_TAG_LENGTH,
ciphertext, plaintext));
if (status == PSA_SUCCESS) {
*plaintext_length = ciphertext_length - ESP_AES_GCM_TAG_LENGTH;
}
exit:
esp_crypto_aes_gcm_abort(&esp_aes_gcm_driver_ctx);
return status;
}
// #endif /* ESP_MBEDTLS_AES_ACCEL */
#endif /* ESP_AES_DRIVER_ENABLED && MBEDTLS_HARDWARE_GCM */
@@ -0,0 +1,615 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_cmac.h"
#include "psa_crypto_driver_esp_cmac_contexts.h"
#include "mbedtls/constant_time.h"
#define MBEDTLS_CMAC_MAX_BLOCK_SIZE 16
#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
#define MBEDTLS_IS_BIG_ENDIAN 1
#else
#define MBEDTLS_IS_BIG_ENDIAN 0
#endif
#define MBEDTLS_BSWAP32 __builtin_bswap32
static inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
{
uint32_t r;
#if defined(UINT_UNALIGNED)
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
r = *p32;
#elif defined(UINT_UNALIGNED_STRUCT)
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
r = p32->x;
#else
memcpy(&r, p, sizeof(r));
#endif
return r;
}
static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
{
#if defined(UINT_UNALIGNED)
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
*p32 = x;
#elif defined(UINT_UNALIGNED_STRUCT)
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
p32->x = x;
#else
memcpy(p, &x, sizeof(x));
#endif
}
#define MBEDTLS_GET_UINT32_BE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? mbedtls_get_unaligned_uint32((data) + (offset)) \
: MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
)
#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \
} \
else \
{ \
mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
} \
}
psa_status_t esp_cmac_mac_abort(esp_cmac_operation_t *operation)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = psa_destroy_key(operation->key_id);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_cipher_abort(&operation->cipher_ctx);
if (status != PSA_SUCCESS) {
return status;
}
mbedtls_platform_zeroize(&operation->cipher_ctx, sizeof(psa_cipher_operation_t));
return status;
}
static psa_status_t mac_init(
esp_cmac_operation_t *operation,
psa_algorithm_t alg)
{
// psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
// memset(&operation->cipher_ctx, 0, sizeof(operation->cipher_ctx));
memset(operation, 0, sizeof(*operation));
return PSA_SUCCESS;
}
static psa_status_t esp_cmac_setup_internal(esp_cmac_operation_t *cmac,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size)
{
int status = PSA_ERROR_CORRUPTION_DETECTED;
#if defined(PSA_WANT_KEY_TYPE_DES)
/* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
* to do CMAC with pure DES, so return NOT_SUPPORTED here. */
if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&
(psa_get_key_bits(attributes) == 64 ||
psa_get_key_bits(attributes) == 128)) {
return PSA_ERROR_NOT_SUPPORTED;
}
#endif
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type = psa_get_key_type(attributes);
size_t key_bits = psa_get_key_bits(attributes);
psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
/* Set up key attributes for PSA import */
psa_set_key_type(&key_attributes, key_type);
psa_set_key_bits(&key_attributes, key_bits);
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&key_attributes, alg);
/* Import key for cipher operations */
status = psa_import_key(&key_attributes, key_buffer, key_buffer_size, &cmac->key_id);
if (status != PSA_SUCCESS) {
return status;
}
status = psa_cipher_encrypt_setup(&cmac->cipher_ctx, cmac->key_id, alg);
if (status != 0) {
return status;
}
cmac->unprocessed_len = 0;
cmac->cipher_block_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
mbedtls_platform_zeroize(cmac->state, sizeof(cmac->state));
mbedtls_platform_zeroize(cmac->unprocessed_block, sizeof(cmac->unprocessed_block));
return PSA_SUCCESS;
}
static psa_status_t esp_cmac_mac_setup_cmac(esp_cmac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = mac_init(operation, alg);
if (status != PSA_SUCCESS) {
return status;
}
status = esp_cmac_setup_internal(operation, attributes, key_buffer, key_buffer_size);
if (status != PSA_SUCCESS) {
esp_cmac_mac_abort(operation);
}
return status;
}
psa_status_t esp_cmac_mac_setup(esp_cmac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
// #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
status = esp_cmac_mac_setup_cmac(operation, attributes, key_buffer, key_buffer_size, alg);
operation->alg = alg;
} else
// #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
// #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
if (PSA_ALG_IS_HMAC(alg)) {
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(alg);
uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
size_t i;
size_t hash_size = PSA_HASH_LENGTH(hash_alg);
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
// psa_status_t status;
// hmac->alg = hash_alg;
/* Sanity checks on block_size, to guarantee that there won't be a buffer
* overflow below. This should never trigger if the hash algorithm
* is implemented correctly. */
/* The size checks against the ipad and opad buffers cannot be written
* `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
* because that triggers -Wlogical-op on GCC 7.3. */
if (block_size > sizeof(ipad)) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (block_size > sizeof(operation->opad)) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (block_size < hash_size) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (key_buffer_size > block_size) {
status = esp_sha_hash_compute(hash_alg, key_buffer, key_buffer_size,
ipad, sizeof(ipad), &key_buffer_size);
if (status != PSA_SUCCESS) {
}
}
/* A 0-length key is not commonly used in HMAC when used as a MAC,
* but it is permitted. It is common when HMAC is used in HKDF, for
* example. Don't call `memcpy` in the 0-length because `key` could be
* an invalid pointer which would make the behavior undefined. */
else if (key_buffer_size != 0) {
memcpy(ipad, key_buffer, key_buffer_size);
}
/* ipad contains the key followed by garbage. Xor and fill with 0x36
* to create the ipad value. */
for (i = 0; i < key_buffer_size; i++) {
ipad[i] ^= 0x36;
}
memset(ipad + key_buffer_size, 0x36, block_size - key_buffer_size);
/* Copy the key material from ipad to opad, flipping the requisite bits,
* and filling the rest of opad with the requisite constant. */
for (i = 0; i < key_buffer_size; i++) {
operation->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
}
memset(operation->opad + key_buffer_size, 0x5C, block_size - key_buffer_size);
status = esp_sha_hash_setup(&operation->hmac_operation, hash_alg);
if (status != PSA_SUCCESS) {
return status;
}
status = esp_sha_hash_update(&operation->hmac_operation, ipad, block_size);
if (status != PSA_SUCCESS) {
return status;
}
operation->alg = alg;
} else
// #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
{
(void) attributes;
(void) key_buffer;
(void) key_buffer_size;
status = PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
static void xor_no_simd(unsigned char *output, const unsigned char *input1, const unsigned char *input2, size_t length)
{
for (size_t i = 0; i < length; i++) {
output[i] = input1[i] ^ input2[i];
}
}
static psa_status_t esp_cmac_mac_update_internal(esp_cmac_operation_t *cmac, const uint8_t *data, size_t data_length)
{
unsigned char *state = cmac->state;
int ret = 0;
size_t n, j, olen, block_size;
if (cmac == NULL || data == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
block_size = cmac->cipher_block_length;
/* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
* error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
// MBEDTLS_ASSUME(block_size <= PSA_CMAC_MAX_BLOCK_SIZE);
/* Is there data still to process from the last call, that's greater in
* size than a block? */
if (cmac->unprocessed_len > 0 && data_length > block_size - cmac->unprocessed_len) {
memcpy(&cmac->unprocessed_block[cmac->unprocessed_len], data, block_size - cmac->unprocessed_len);
xor_no_simd(state, cmac->unprocessed_block, state, block_size);
if ((ret = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
goto exit;
}
data += block_size - cmac->unprocessed_len;
data_length -= block_size - cmac->unprocessed_len;
cmac->unprocessed_len = 0;
}
/* n is the number of blocks including any final partial block */
n = (data_length + block_size - 1) / block_size;
/* Iterate across the input data in block sized chunks, excluding any
* final partial or complete block */
for (j = 1; j < n; j++) {
xor_no_simd(state, data, state, block_size);
if ((ret = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
goto exit;
}
data_length -= block_size;
data += block_size;
}
/* If there is data left over that wasn't aligned to a block */
if (data_length > 0) {
memcpy(&cmac->unprocessed_block[cmac->unprocessed_len], data, data_length);
cmac->unprocessed_len += data_length;
}
exit:
return ret;
}
psa_status_t esp_cmac_mac_update(esp_cmac_operation_t *cmac, const uint8_t *data, size_t data_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (PSA_ALG_FULL_LENGTH_MAC(cmac->alg) == PSA_ALG_CMAC) {
status = esp_cmac_mac_update_internal(cmac, data, data_length);
} else if (PSA_ALG_IS_HMAC(cmac->alg)) {
status = esp_sha_hash_update(&cmac->hmac_operation, data, data_length);
} else {
(void) cmac;
(void) data;
(void) data_length;
status = PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
static inline unsigned mbedtls_ct_uint_if_else_0(uint32_t condition, unsigned if1)
{
return (unsigned) (condition & if1);
}
static int cmac_multiply_by_u(unsigned char *output,
const unsigned char *input,
size_t blocksize)
{
const unsigned char R_128 = 0x87;
unsigned char R_n;
uint32_t overflow = 0x00;
int i;
if (blocksize == PSA_AES_BLOCK_SIZE) {
R_n = R_128;
}
#if defined(PSA_WANT_KEY_TYPE_DES)
else if (blocksize == PSA_DES_BLOCK_SIZE) {
const unsigned char R_64 = 0x1B;
R_n = R_64;
}
#endif
else {
return PSA_ERROR_INVALID_ARGUMENT;
}
for (i = (int) blocksize - 4; i >= 0; i -= 4) {
uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
uint32_t new_overflow = i32 >> 31;
i32 = (i32 << 1) | overflow;
MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
overflow = new_overflow;
}
// R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);
unsigned char msb = (input[0] >> 7) & 1;
output[blocksize - 1] ^= (unsigned char)(msb * R_n);
return 0;
}
static int cmac_generate_subkeys(psa_cipher_operation_t *ctx, size_t block_size,
unsigned char *K1, unsigned char *K2)
{
int ret = PSA_ERROR_CORRUPTION_DETECTED;
unsigned char L[PSA_CMAC_MAX_BLOCK_SIZE];
size_t olen;
mbedtls_platform_zeroize(L, sizeof(L));
/* Calculate Ek(0) */
if ((ret = psa_cipher_update(ctx, L, block_size, L, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
goto exit;
}
/*
* Generate K1 and K2
*/
if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {
goto exit;
}
if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {
goto exit;
}
exit:
mbedtls_platform_zeroize(L, sizeof(L));
return ret;
}
static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],
size_t padded_block_len,
const unsigned char *last_block,
size_t last_block_len)
{
size_t j;
for (j = 0; j < padded_block_len; j++) {
if (j < last_block_len) {
padded_block[j] = last_block[j];
} else if (j == last_block_len) {
padded_block[j] = 0x80;
} else {
padded_block[j] = 0x00;
}
}
}
static psa_status_t esp_cmac_mac_finish_internal(
esp_cmac_operation_t *cmac,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t olen, block_size;
unsigned char *state, *last_block;
unsigned char K1[PSA_CMAC_MAX_BLOCK_SIZE];
unsigned char K2[PSA_CMAC_MAX_BLOCK_SIZE];
unsigned char M_last[PSA_CMAC_MAX_BLOCK_SIZE];
if (cmac == NULL || mac == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
state = cmac->state;
block_size = cmac->cipher_block_length;
mbedtls_platform_zeroize(K1, sizeof(K1));
mbedtls_platform_zeroize(K2, sizeof(K2));
cmac_generate_subkeys(&cmac->cipher_ctx, block_size, K1, K2);
last_block = cmac->unprocessed_block;
/* Calculate last block */
if (cmac->unprocessed_len < block_size) {
cmac_pad(M_last, block_size, last_block, cmac->unprocessed_len);
xor_no_simd(M_last, M_last, K2, block_size);
} else {
/* Last block is complete block */
xor_no_simd(M_last, last_block, K1, block_size);
}
xor_no_simd(state, M_last, state, block_size);
if ((status = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
goto exit;
}
memcpy(mac, state, mac_size);
*mac_length = mac_size;
exit:
mbedtls_platform_zeroize(K1, sizeof(K1));
mbedtls_platform_zeroize(K2, sizeof(K2));
cmac->unprocessed_len = 0;
mbedtls_platform_zeroize(cmac->unprocessed_block, sizeof(cmac->unprocessed_block));
mbedtls_platform_zeroize(state, PSA_CMAC_MAX_BLOCK_SIZE);
return status;
}
psa_status_t esp_cmac_mac_finish(
esp_cmac_operation_t *cmac,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (PSA_ALG_FULL_LENGTH_MAC(cmac->alg) == PSA_ALG_CMAC) {
status = esp_cmac_mac_finish_internal(cmac, mac, mac_size, mac_length);
} else if (PSA_ALG_IS_HMAC(cmac->alg)) {
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(cmac->alg);
// status = esp_sha_hash_finish(&cmac->hmac_operation, mac, mac_size, mac_length);
uint8_t tmp[PSA_HASH_MAX_SIZE];
// psa_algorithm_t hash_alg = hmac->alg;
size_t hash_size = 0;
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
// psa_status_t status;
status = esp_sha_hash_finish(&cmac->hmac_operation, tmp, sizeof(tmp), &hash_size);
if (status != PSA_SUCCESS) {
return status;
}
/* From here on, tmp needs to be wiped. */
status = esp_sha_hash_setup(&cmac->hmac_operation, hash_alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_sha_hash_update(&cmac->hmac_operation, cmac->opad, block_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_sha_hash_update(&cmac->hmac_operation, tmp, hash_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_sha_hash_finish(&cmac->hmac_operation, tmp, sizeof(tmp), &hash_size);
if (status != PSA_SUCCESS) {
goto exit;
}
memcpy(mac, tmp, mac_size);
*mac_length = mac_size;
exit:
mbedtls_platform_zeroize(tmp, hash_size);
} else {
(void) cmac;
(void) mac;
(void) mac_length;
(void) mac_size;
status = PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
psa_status_t esp_cmac_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_cmac_operation_t operation = {0};
memset(&operation, 0, sizeof(operation));
status = esp_cmac_mac_setup(&operation,
attributes, key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (input_length > 0) {
status = esp_cmac_mac_update(&operation, input, input_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
size_t actual_mac_length = 0;
status = esp_cmac_mac_finish(&operation, mac, mac_size, &actual_mac_length);
if (status == PSA_SUCCESS) {
*mac_length = actual_mac_length;
}
exit:
esp_cmac_mac_abort(&operation);
return status;
}
psa_status_t esp_cmac_mac_verify_finish(
esp_cmac_operation_t *operation,
const uint8_t *mac,
size_t mac_length)
{
uint8_t actual_mac[PSA_MAC_MAX_SIZE];
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (operation == NULL || mac == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (mac_length > sizeof(actual_mac)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
size_t actual_mac_length = 0;
status = esp_cmac_mac_finish(operation, actual_mac, mac_length, &actual_mac_length);
if (status == PSA_SUCCESS) {
if (memcmp(actual_mac, mac, mac_length) == 0) {
return PSA_SUCCESS;
} else {
return PSA_ERROR_INVALID_SIGNATURE;
}
}
return status;
}
@@ -29,6 +29,32 @@ static int esp_sha1_starts(esp_sha1_context *ctx) {
return ESP_OK; return ESP_OK;
} }
// int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[64])
// {
// esp_sha_acquire_hardware();
// esp_sha_set_mode(ctx->mode);
// esp_internal_sha_update_state(ctx);
// #if SOC_SHA_SUPPORT_DMA
// if (sha_operation_mode(64) == SHA_DMA_MODE) {
// int ret = esp_sha_dma(SHA1, data, 64, NULL, 0, ctx->first_block);
// if (ret != 0) {
// esp_sha_release_hardware();
// return ret;
// }
// } else
// #endif /* SOC_SHA_SUPPORT_DMA */
// {
// esp_sha_block(ctx->mode, data, ctx->first_block);
// }
// esp_sha_read_digest_state(ctx->mode, ctx->state);
// esp_sha_release_hardware();
// return 0;
// }
static void esp_internal_sha1_block_process(esp_sha1_context *ctx, const uint8_t *data) static void esp_internal_sha1_block_process(esp_sha1_context *ctx, const uint8_t *data)
{ {
esp_sha_block(SHA1, data, ctx->first_block); esp_sha_block(SHA1, data, ctx->first_block);
@@ -168,17 +168,25 @@ psa_status_t esp_sha256_driver_compute(
size_t hash_size, size_t hash_size,
size_t *hash_length) size_t *hash_length)
{ {
printf("SHA256 Driver Compute\n"); // printf("SHA256 Driver Compute\n");
if (!hash || !hash_length) { if (!hash || !hash_length) {
return PSA_ERROR_INVALID_ARGUMENT; return PSA_ERROR_INVALID_ARGUMENT;
} }
if (alg != PSA_ALG_SHA_256 && alg != PSA_ALG_SHA_224) { if (alg != PSA_ALG_SHA_256
#if SOC_SHA_SUPPORT_SHA224
&& alg != PSA_ALG_SHA_224
#endif // SOC_SHA_SUPPORT_SHA224
) {
return PSA_ERROR_NOT_SUPPORTED; return PSA_ERROR_NOT_SUPPORTED;
} }
if (hash_size < PSA_HASH_LENGTH(alg)) { if (hash_size < PSA_HASH_LENGTH(alg)) {
return PSA_ERROR_BUFFER_TOO_SMALL; return PSA_ERROR_BUFFER_TOO_SMALL;
} }
#if SOC_SHA_SUPPORT_SHA224
int mode = (alg == PSA_ALG_SHA_224) ? SHA2_224 : SHA2_256; int mode = (alg == PSA_ALG_SHA_224) ? SHA2_224 : SHA2_256;
#else
int mode = SHA2_256;
#endif // SOC_SHA_SUPPORT_SHA224
int ret = esp_sha256_starts(ctx, mode); int ret = esp_sha256_starts(ctx, mode);
if (ret != ESP_OK) { if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE; return PSA_ERROR_HARDWARE_FAILURE;
@@ -229,9 +237,12 @@ psa_status_t esp_sha256_driver_finish(
if (ret != ESP_OK) { if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE; return PSA_ERROR_HARDWARE_FAILURE;
} }
#if SOC_SHA_SUPPORT_SHA224
if (sha_type == ESP_SHA_OPERATION_TYPE_SHA224) { if (sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
*hash_length = PSA_HASH_LENGTH(PSA_ALG_SHA_224); *hash_length = PSA_HASH_LENGTH(PSA_ALG_SHA_224);
} else if (sha_type == ESP_SHA_OPERATION_TYPE_SHA256) { } else
#endif // SOC_SHA_SUPPORT_SHA224
if (sha_type == ESP_SHA_OPERATION_TYPE_SHA256) {
*hash_length = PSA_HASH_LENGTH(PSA_ALG_SHA_256); *hash_length = PSA_HASH_LENGTH(PSA_ALG_SHA_256);
} else { } else {
return PSA_ERROR_NOT_SUPPORTED; return PSA_ERROR_NOT_SUPPORTED;
@@ -16,6 +16,9 @@
#include "esp_sha_internal.h" #include "esp_sha_internal.h"
#include "sha/sha_core.h" #include "sha/sha_core.h"
#include "esp_err.h" #include "esp_err.h"
#include "sdkconfig.h"
#if CONFIG_SOC_SHA_SUPPORT_SHA512
#ifndef PUT_UINT64_BE #ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \ #define PUT_UINT64_BE(n,b,i) \
@@ -51,7 +54,7 @@ static int esp_sha512_starts(esp_sha512_context *ctx, int mode) {
static int esp_internal_sha_update_state(esp_sha512_context *ctx) static int esp_internal_sha_update_state(esp_sha512_context *ctx)
{ {
if (ctx->sha_state == ESP_SHA512_STATE_INIT) { if (ctx->sha_state == ESP_SHA512_STATE_INIT) {
if (ctx->mode == SHA2_512T) { if (ctx->mode == SHA2_512) {
int ret = -1; int ret = -1;
if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) { if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) {
return ret; return ret;
@@ -179,9 +182,12 @@ static int esp_sha512_finish(esp_sha512_context *ctx, unsigned char *output)
return ret; return ret;
} }
#if SOC_SHA_SUPPORT_SHA384
if (ctx->mode == SHA2_384) { if (ctx->mode == SHA2_384) {
memcpy(output, ctx->state, 48); memcpy(output, ctx->state, 48);
} else { } else
#endif // SOC_SHA_SUPPORT_SHA384
{
memcpy(output, ctx->state, 64); memcpy(output, ctx->state, 64);
} }
@@ -207,7 +213,10 @@ psa_status_t esp_sha512_driver_compute(
if (hash_size < PSA_HASH_LENGTH(alg)) { if (hash_size < PSA_HASH_LENGTH(alg)) {
return PSA_ERROR_BUFFER_TOO_SMALL; return PSA_ERROR_BUFFER_TOO_SMALL;
} }
int mode = (alg == PSA_ALG_SHA_384) ? SHA2_384 : SHA2_512; int mode = SHA2_512;
#if SOC_SHA_SUPPORT_SHA384
mode = (alg == PSA_ALG_SHA_384) ? SHA2_384 : SHA2_512;
#endif // SOC_SHA_SUPPORT_SHA384
int ret = esp_sha512_starts(ctx, mode); int ret = esp_sha512_starts(ctx, mode);
if (ret != ESP_OK) { if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE; return PSA_ERROR_HARDWARE_FAILURE;
@@ -271,3 +280,5 @@ psa_status_t esp_sha512_driver_finish(
return PSA_SUCCESS; return PSA_SUCCESS;
} }
#endif // SOC_SHA_SUPPORT_SHA512
@@ -21,17 +21,6 @@ static const unsigned char sha256_padding[64] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };
static void esp_internal_sha_update_state(esp_sha1_context *ctx)
{
if (ctx->sha_state == ESP_SHA256_STATE_INIT) {
ctx->first_block = true;
ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS;
} else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) {
ctx->first_block = false;
// esp_sha_write_digest_state(SHA1, ctx->state);
}
}
static int esp_internal_sha256_parallel_engine_process( esp_sha256_context *ctx, const unsigned char data[64], bool read_digest ) static int esp_internal_sha256_parallel_engine_process( esp_sha256_context *ctx, const unsigned char data[64], bool read_digest )
{ {
if (ctx->sha_state == ESP_SHA256_STATE_INIT) { if (ctx->sha_state == ESP_SHA256_STATE_INIT) {
@@ -0,0 +1,92 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#if defined(ESP_AES_DRIVER_ENABLED)
#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#endif
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_aes_contexts.h"
psa_status_t esp_aes_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *iv,
size_t iv_length,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t esp_crypto_aes_encrypt_setup(
esp_aes_operation_t *esp_aes_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t esp_crypto_aes_set_iv(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *iv, size_t iv_length);
psa_status_t esp_crypto_aes_update(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size,
size_t *output_length);
psa_status_t esp_crypto_aes_finish(
esp_aes_operation_t *esp_aes_driver_ctx,
uint8_t *output, size_t output_size,
size_t *output_length);
psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_ctx);
psa_status_t esp_aes_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key, size_t key_length,
psa_algorithm_t alg,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
psa_status_t esp_aes_cipher_decrypt_setup(
esp_aes_operation_t *esp_aes_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t esp_aes_cipher_encrypt_setup(
esp_aes_operation_t *esp_aes_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t esp_aes_cipher_set_iv(
esp_aes_operation_t *operation,
const uint8_t *iv,
size_t iv_length);
psa_status_t esp_aes_cipher_update(
esp_aes_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t esp_aes_cipher_finish(
esp_aes_operation_t *operation,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t esp_aes_cipher_abort(
esp_aes_operation_t *operation);
#endif /* ESP_AES_DRIVER_ENABLED */
@@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
/**
* \file psa_crypto_driver_esp_sha_contexts.h
*
* \brief Context structure definitions for ESP SHA hardware driver.
*
* This file contains the context structures used by the ESP SHA driver
* for PSA Crypto API. These definitions are completely standalone and
* do not include any PSA Crypto headers to avoid circular dependencies.
*
* \note This file may not be included directly. It is included by
* crypto_driver_contexts_primitives.h.
*/
#include <stdint.h>
#include <stdbool.h>
#if defined(ESP_AES_DRIVER_ENABLED)
#define ESP_MBEDTLS_AES_MAX_BLOCK_LENGTH 16
#define ESP_MBEDTLS_AES_MAX_IV_LENGTH 16
typedef struct {
void *esp_aes_ctx;
uint8_t iv[ESP_MBEDTLS_AES_MAX_IV_LENGTH];
uint8_t unprocessed_data[ESP_MBEDTLS_AES_MAX_BLOCK_LENGTH];
size_t unprocessed_len;
psa_algorithm_t aes_alg;
psa_encrypt_or_decrypt_t mode;
uint8_t block_length;
} esp_aes_operation_t;
typedef struct {
void *esp_aes_gcm_ctx;
psa_encrypt_or_decrypt_t mode;
} esp_aes_gcm_operation_t;
#endif /* ESP_AES_DRIVER_ENABLED */
@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
// #include_next "mbedtls/gcm.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
#if (defined(ESP_AES_DRIVER_ENABLED) || defined(MBEDTLS_HARDWARE_GCM))
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_aes_contexts.h"
psa_status_t esp_crypto_aes_gcm_encrypt_setup(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t esp_crypto_aes_gcm_decrypt_setup(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t esp_crypto_aes_gcm_set_nonce(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const uint8_t *nonce,
size_t nonce_length);
psa_status_t esp_crypto_aes_gcm_update_ad(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const uint8_t *aad,
size_t aad_length);
psa_status_t esp_crypto_aes_gcm_update(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t esp_crypto_aes_gcm_finish(
esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx,
uint8_t *output,
size_t output_size,
size_t *output_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length);
psa_status_t esp_crypto_aes_gcm_abort(esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx);
psa_status_t esp_crypto_aes_gcm_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length);
psa_status_t esp_crypto_aes_gcm_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length);
#endif /* ESP_AES_DRIVER_ENABLED */
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#if defined(ESP_AES_DRIVER_ENABLED)
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_cmac_contexts.h"
psa_status_t esp_cmac_mac_compute(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t esp_cmac_mac_abort(esp_cmac_operation_t *operation);
psa_status_t esp_cmac_mac_setup(esp_cmac_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
psa_status_t esp_cmac_mac_update(esp_cmac_operation_t *cmac,
const uint8_t *data,
size_t data_length);
psa_status_t esp_cmac_mac_finish(
esp_cmac_operation_t *hmac,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t esp_cmac_mac_verify_finish(
esp_cmac_operation_t *operation,
const uint8_t *mac,
size_t mac_length);
#endif /* ESP_AES_DRIVER_ENABLED */
@@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#if defined(ESP_AES_DRIVER_ENABLED) || defined(PSA_CRYPTO_DRIVER_TEST)
#if defined(ESP_SHA_DRIVER_ENABLED)
#include "psa_crypto_driver_esp_sha_contexts.h"
#include "psa_crypto_driver_esp_sha.h"
#endif /* ESP_SHA_DRIVER_ENABLED */
#define PSA_AES_BLOCK_SIZE PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)
#define PSA_DES_BLOCK_SIZE PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_DES)
#if defined(PSA_WANT_KEY_TYPE_AES)
#define PSA_CMAC_MAX_BLOCK_SIZE PSA_AES_BLOCK_SIZE /**< The longest block used by CMAC is that of AES. */
#else
#define PSA_CMAC_MAX_BLOCK_SIZE PSA_DES_BLOCK_SIZE /**< The longest block used by CMAC is that of 3DES. */
#endif
typedef struct {
/** The CMAC key identifier for cipher operations */
psa_key_id_t key_id;
/** The internal state of the CMAC algorithm. */
unsigned char state[PSA_CMAC_MAX_BLOCK_SIZE];
/** Unprocessed data - either data that was not block aligned and is still
* pending processing, or the final block. */
unsigned char unprocessed_block[PSA_CMAC_MAX_BLOCK_SIZE];
/** The length of data pending processing. */
size_t unprocessed_len;
uint8_t cipher_block_length;
struct psa_cipher_operation_s cipher_ctx;
psa_algorithm_t alg;
#if defined(ESP_SHA_DRIVER_ENABLED)
esp_sha_hash_operation_t hmac_operation;
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
#endif /* ESP_SHA_DRIVER_ENABLED */
} esp_cmac_operation_t;
#endif /* ESP_AES_DRIVER_ENABLED */
@@ -10,8 +10,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <esp_system.h> #include <esp_system.h>
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS #define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "mbedtls/aes.h" #include "psa/crypto.h"
#include "mbedtls/gcm.h"
#include "unity.h" #include "unity.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
@@ -22,25 +21,49 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
{ {
const unsigned CALLS = 256; const unsigned CALLS = 256;
const unsigned CALL_SZ = 32 * 1024; const unsigned CALL_SZ = 32 * 1024;
mbedtls_aes_context ctx;
float elapsed_usec; float elapsed_usec;
uint8_t iv[16]; uint8_t iv[16];
uint8_t key[16]; uint8_t key[16];
psa_status_t status = psa_crypto_init();
if (status != PSA_SUCCESS) {
TEST_FAIL_MESSAGE("PSA crypto initialization failed");
}
memset(iv, 0xEE, 16); memset(iv, 0xEE, 16);
memset(key, 0x44, 16); memset(key, 0x44, 16);
// allocate internal memory // allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf); TEST_ASSERT_NOT_NULL(buf);
mbedtls_aes_init(&ctx); psa_key_id_t key_id;
mbedtls_aes_setkey_enc(&ctx, key, 128); 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);
status = psa_import_key(&attributes, key, sizeof(key), &key_id);
if (status != PSA_SUCCESS) {
TEST_FAIL_MESSAGE("Failed to import key");
}
psa_cipher_operation_t operation = psa_cipher_operation_init();
status = psa_cipher_encrypt_setup(&operation, key_id, PSA_ALG_CBC_NO_PADDING);
if (status != PSA_SUCCESS) {
TEST_FAIL_MESSAGE("Failed to setup AES encryption");
}
status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
if (status != PSA_SUCCESS) {
TEST_FAIL_MESSAGE("Failed to set IV for AES encryption");
}
ccomp_timer_start(); ccomp_timer_start();
size_t output_length = 0;
for (int c = 0; c < CALLS; c++) { for (int c = 0; c < CALLS; c++) {
memset(buf, 0xAA, CALL_SZ); memset(buf, 0xAA, CALL_SZ);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, buf, buf); psa_cipher_update(&operation, buf, CALL_SZ, buf, CALL_SZ, &output_length);
} }
psa_cipher_finish(&operation, buf + CALL_SZ - 16, 16, &output_length);
elapsed_usec = ccomp_timer_stop(); elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches /* Sanity check: make sure the last ciphertext block matches
@@ -63,15 +86,19 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
}; };
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
mbedtls_aes_free(&ctx); // mbedtls_aes_free(&ctx);
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
free(buf); free(buf);
mbedtls_psa_crypto_free();
// bytes/usec = MB/sec // bytes/usec = MB/sec
float mb_sec = (CALL_SZ * CALLS) / elapsed_usec; float mb_sec = (CALL_SZ * CALLS) / elapsed_usec;
printf("Encryption rate %.3fMB/sec\n", mb_sec); printf("Encryption rate %.3fMB/sec\n", mb_sec);
// Commenting out this for now as we do not have hardware support with PSA // Commenting out this for now as we do not have hardware support with PSA
// #ifdef CONFIG_MBEDTLS_HARDWARE_AES #ifdef CONFIG_MBEDTLS_HARDWARE_AES
// // Don't put a hard limit on software AES performance // Don't put a hard limit on software AES performance
// TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
// #endif #endif
} }
@@ -0,0 +1,632 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_private/periph_ctrl.h"
#include "mbedtls/aes.h"
#include "mbedtls/cipher.h"
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_256[] = {
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,
};
TEST_CASE("PSA AES-CTR multipart", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 16;
const size_t part_size = 8;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CTR;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA AES-ECB multipart", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 112;
const size_t iv_SZ = 16;
const size_t part_size = 16;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA AES-CBC multipart", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 112; // Multiple of block size (16)
const size_t iv_SZ = 16;
const size_t part_size = 16; // Process one block at a time
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
#if 0
TEST_CASE("PSA AES-CBC-PKCS7 multipart", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
// Test both aligned and unaligned sizes
const size_t SZ1 = 112; // Multiple of block size (16)
const size_t SZ2 = 123; // Not a multiple of block size
const size_t iv_SZ = 16;
const size_t part_size = 16;
uint8_t *plaintext1 = malloc(SZ1);
uint8_t *ciphertext1 = malloc(SZ1 + 16); // Extra block for padding
uint8_t *decryptedtext1 = malloc(SZ1);
uint8_t *plaintext2 = malloc(SZ2);
uint8_t *ciphertext2 = malloc(SZ2 + 16); // Extra block for padding
uint8_t *decryptedtext2 = malloc(SZ2);
uint8_t iv[iv_SZ];
// Initialize test data
memset(plaintext1, 0x3A, SZ1);
memset(plaintext2, 0x3B, SZ2);
memset(decryptedtext1, 0x0, SZ1);
memset(decryptedtext2, 0x0, SZ2);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Test 1: Block-aligned input */
{
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3C, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
// Process all blocks except the last one
for (size_t offset = 0; offset < SZ1 - part_size; offset += part_size) {
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext1 + offset, part_size,
ciphertext1 + total_out_len, part_size, &out_len));
total_out_len += out_len;
}
// Process the last block separately
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext1 + SZ1 - part_size, part_size,
ciphertext1 + total_out_len, part_size + 16, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext1 + total_out_len,
16, &out_len)); // Space for padding block
total_out_len += out_len;
// The output size should be the input size rounded up to the next multiple of 16
TEST_ASSERT_EQUAL_size_t((SZ1 + 16), total_out_len); // Should include padding block
ESP_LOGI("TAG", "Decryption");
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
size_t dec_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < total_out_len; offset += part_size) {
size_t this_part = total_out_len - offset < part_size ? total_out_len - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext1 + offset, this_part,
decryptedtext1 + dec_len, SZ1 - dec_len, &out_len));
dec_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext1 + dec_len,
SZ1 - dec_len, &out_len));
dec_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ1, dec_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext1, decryptedtext1, SZ1);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
}
/* Test 2: Non-block-aligned input */
{
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3D, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ2; offset += part_size) {
size_t this_part = SZ2 - offset < part_size ? SZ2 - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext2 + offset, this_part,
ciphertext2 + total_out_len, SZ2 + 16 - total_out_len, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext2 + total_out_len,
SZ2 + 16 - total_out_len, &out_len));
total_out_len += out_len;
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
size_t dec_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < total_out_len; offset += part_size) {
size_t this_part = total_out_len - offset < part_size ? total_out_len - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext2 + offset, this_part,
decryptedtext2 + dec_len, SZ2 - dec_len, &out_len));
dec_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext2 + dec_len,
SZ2 - dec_len, &out_len));
dec_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ2, dec_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext2, decryptedtext2, SZ2);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
}
/* Cleanup */
free(plaintext1);
free(ciphertext1);
free(decryptedtext1);
free(plaintext2);
free(ciphertext2);
free(decryptedtext2);
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
#endif
TEST_CASE("PSA AES-CFB multipart", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 16;
const size_t part_size = 8;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CFB;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA AES-OFB multipart", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 16;
const size_t part_size = 8;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_OFB;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA AES-CBC one-shot", "[psa-aes]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 1600;
const size_t iv_SZ = 16;
// allocate internal memory
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *ciphertext = heap_caps_malloc(SZ + iv_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(psa_import_key(&attributes, key_256, sizeof(key_256), &key_id), PSA_SUCCESS);
psa_reset_key_attributes(&attributes);
size_t ciphertext_len = 0;
/* Encrypt the plaintext */
TEST_ASSERT_EQUAL(psa_cipher_encrypt(key_id, alg, plaintext, SZ, ciphertext, SZ + iv_SZ, &ciphertext_len), PSA_SUCCESS);
TEST_ASSERT_EQUAL_size_t(ciphertext_len, SZ + iv_SZ);
size_t decryptedtext_len = 0;
/* Decrypt the ciphertext */
TEST_ASSERT_EQUAL(psa_cipher_decrypt(key_id, alg, ciphertext, SZ + iv_SZ, decryptedtext, SZ, &decryptedtext_len), PSA_SUCCESS);
TEST_ASSERT_EQUAL_size_t(decryptedtext_len, SZ);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
@@ -0,0 +1,212 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_256[] = {
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,
};
TEST_CASE("PSA AES-GCM multipart", "[psa-aes-gcm]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
const size_t part_size = 8;
size_t tag_length = 0;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
uint8_t tag[tag_SZ];
uint8_t aad[aad_SZ];
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_aead_operation_t enc_op = PSA_AEAD_OPERATION_INIT;
size_t out_len, total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&enc_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&enc_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&enc_op, aad, aad_SZ));
// Process the plaintext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Finish encryption and get the tag
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_finish(&enc_op,
ciphertext + total_out_len,
SZ - total_out_len,
&out_len,
tag,
tag_SZ,
&tag_length));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_aead_operation_t dec_op = PSA_AEAD_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&dec_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&dec_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&dec_op, aad, aad_SZ));
// Process the ciphertext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Verify the tag and finish decryption
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_verify(&dec_op,
decryptedtext + total_out_len,
SZ - total_out_len,
&out_len,
tag,
tag_SZ));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_aead_abort(&enc_op);
psa_aead_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA AES-GCM one-shot", "[psa-aes-gcm]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
// Allocate memory with proper alignment
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ + tag_SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t *iv = malloc(iv_SZ);
uint8_t *aad = malloc(aad_SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
TEST_ASSERT_NOT_NULL(iv);
TEST_ASSERT_NOT_NULL(aad);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(ciphertext, 0, SZ + tag_SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
size_t output_length;
/* One-shot encrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
plaintext, SZ,
ciphertext, SZ + tag_SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ + tag_SZ, output_length);
/* One-shot decrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
ciphertext, SZ + tag_SZ,
decryptedtext, SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ, output_length);
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
free(iv);
free(aad);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
@@ -0,0 +1,426 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* PSA CMAC test
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "psa/crypto.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_memory_utils.h"
#if CONFIG_MBEDTLS_CMAC_C
static const uint8_t key_128[] = {
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
};
static const uint8_t key_256[] = {
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 test_data[] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
};
// Expected CMAC values from the mbedtls implementation
static const uint8_t expected_cmac_128[] = {
0x93, 0xae, 0x18, 0x36, 0xdf, 0xbd, 0x91, 0x06,
0xa5, 0xd1, 0x84, 0x5c, 0xe5, 0x61, 0x02, 0xe2,
};
static const uint8_t expected_cmac_256[] = {
0x35, 0x17, 0x99, 0xb0, 0xfd, 0xb1, 0x5b, 0x47,
0x98, 0xe3, 0x47, 0xef, 0xa3, 0xb4, 0xe1, 0x89,
};
static const uint8_t expected_cmac_zero_length[] = {
0xd8, 0xa8, 0x58, 0x43, 0x62, 0xe9, 0x93, 0xf8,
0xd5, 0x29, 0x24, 0xf6, 0x39, 0x07, 0xc4, 0x88,
};
TEST_CASE("PSA CMAC AES-128 test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Calculate CMAC
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
ESP_LOGI("PSA CMAC AES-128", "Status: %ld", status);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
ESP_LOG_BUFFER_HEXDUMP("CMAC AES-128", cmac, cmac_length, ESP_LOG_INFO);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
// Verify CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
expected_cmac_128, sizeof(expected_cmac_128));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC AES-256 test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 256);
// Import the key
status = psa_import_key(&attributes, key_256, sizeof(key_256), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Calculate CMAC
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_256, cmac, 16);
// Verify CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
expected_cmac_256, sizeof(expected_cmac_256));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC AES-128 multipart test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Test multipart operation with different chunk sizes
for (size_t chunk_size = 1; chunk_size < sizeof(test_data); chunk_size++) {
// Setup operation
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_CMAC);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Process data in chunks
for (size_t offset = 0; offset < sizeof(test_data); offset += chunk_size) {
size_t current_chunk_size = (offset + chunk_size > sizeof(test_data)) ?
(sizeof(test_data) - offset) : chunk_size;
status = psa_mac_update(&operation, test_data + offset, current_chunk_size);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
// Finish operation
status = psa_mac_sign_finish(&operation, cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
// Verify result
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
}
// Cleanup
psa_destroy_key(key_id);
free(cmac);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC AES-128 multipart verify test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
// Verify CMAC multipart
psa_mac_operation_t verify_operation = PSA_MAC_OPERATION_INIT;
status = psa_mac_verify_setup(&verify_operation, key_id, PSA_ALG_CMAC);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_update(&verify_operation, test_data, sizeof(test_data));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify_finish(&verify_operation, cmac, cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Modify one byte of cmac and check for failure
cmac[0] = cmac[0] + 1;
status = psa_mac_verify_setup(&verify_operation, key_id, PSA_ALG_CMAC);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_update(&verify_operation, test_data, sizeof(test_data));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify_finish(&verify_operation, cmac, cmac_length);
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC zero-length test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Calculate CMAC on zero-length data
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
NULL, 0,
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_zero_length, cmac, 16);
// Verify CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
NULL, 0,
expected_cmac_zero_length, sizeof(expected_cmac_zero_length));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC memory alignment test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate memory with different capabilities
uint8_t *cmac_internal = heap_caps_malloc(16, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *cmac_dma = heap_caps_malloc(16, MALLOC_CAP_DMA|MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(cmac_internal);
TEST_ASSERT_NOT_NULL(cmac_dma);
size_t cmac_length_internal = 0;
size_t cmac_length_dma = 0;
// Calculate CMAC with internal memory
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac_internal, 16,
&cmac_length_internal);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length_internal);
// Calculate CMAC with DMA-capable memory
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac_dma, 16,
&cmac_length_dma);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length_dma);
// Results should be identical
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac_internal, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac_dma, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(cmac_internal, cmac_dma, 16);
// Cleanup
psa_destroy_key(key_id);
free(cmac_internal);
free(cmac_dma);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC verify failure test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = psa_crypto_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Create an invalid CMAC by modifying one byte
uint8_t invalid_cmac[16];
memcpy(invalid_cmac, expected_cmac_128, 16);
invalid_cmac[0] ^= 0x01; // Flip one bit
// Verify should fail with the modified CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
invalid_cmac, sizeof(invalid_cmac));
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status);
// Verify should succeed with the correct CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
expected_cmac_128, sizeof(expected_cmac_128));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
#endif /* CONFIG_MBEDTLS_CMAC_C */
@@ -0,0 +1,210 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_256[] = {
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,
};
TEST_CASE("PSA ARIA-GCM multipart", "[psa-gcm]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
const size_t part_size = 8;
// Allocate memory with proper alignment
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ + tag_SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t *iv = malloc(iv_SZ);
uint8_t *aad = malloc(aad_SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
TEST_ASSERT_NOT_NULL(iv);
TEST_ASSERT_NOT_NULL(aad);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(ciphertext, 0, SZ + tag_SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ARIA);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_aead_operation_t enc_op = PSA_AEAD_OPERATION_INIT;
size_t out_len, total_out_len = 0;
size_t tag_length = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&enc_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&enc_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&enc_op, aad, aad_SZ));
// Process the plaintext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Finish encryption and get the tag
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_finish(&enc_op,
ciphertext + total_out_len,
SZ + tag_SZ - total_out_len,
&out_len,
ciphertext + SZ,
tag_SZ,
&tag_length));
total_out_len += out_len;
/* Decrypt */
psa_aead_operation_t dec_op = PSA_AEAD_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&dec_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&dec_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&dec_op, aad, aad_SZ));
// Process the ciphertext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Verify the tag and finish decryption
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_verify(&dec_op,
decryptedtext + total_out_len,
SZ - total_out_len,
&out_len,
ciphertext + SZ,
tag_SZ));
total_out_len += out_len;
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
free(iv);
free(aad);
psa_aead_abort(&enc_op);
psa_aead_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
TEST_CASE("PSA ARIA-GCM one-shot", "[psa-gcm]")
{
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
// Allocate memory with proper alignment
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ + tag_SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t *iv = malloc(iv_SZ);
uint8_t *aad = malloc(aad_SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
TEST_ASSERT_NOT_NULL(iv);
TEST_ASSERT_NOT_NULL(aad);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(ciphertext, 0, SZ + tag_SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
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, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ARIA);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
size_t output_length;
/* One-shot encrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
plaintext, SZ,
ciphertext, SZ + tag_SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ + tag_SZ, output_length);
/* One-shot decrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
ciphertext, SZ + tag_SZ,
decryptedtext, SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ, output_length);
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
free(iv);
free(aad);
/* Destroy the key */
psa_destroy_key(key_id);
mbedtls_psa_crypto_free();
}
@@ -20,7 +20,9 @@
#include "test_mbedtls_utils.h" #include "test_mbedtls_utils.h"
#include "psa/crypto.h" #include "psa/crypto.h"
TEST_CASE("mbedtls SHA performance", "[mbedtls]") #include "psa/crypto.h"
TEST_CASE("psa SHA256 performance", "[mbedtls]")
{ {
const unsigned CALLS = 256; const unsigned CALLS = 256;
const unsigned CALL_SZ = 16 * 1024; const unsigned CALL_SZ = 16 * 1024;
@@ -61,8 +63,8 @@ TEST_CASE("mbedtls SHA performance", "[mbedtls]")
// bytes/usec = MB/sec // bytes/usec = MB/sec
float mb_sec = (CALL_SZ * CALLS) / elapsed_usec; float mb_sec = (CALL_SZ * CALLS) / elapsed_usec;
printf("SHA256 rate %.3fMB/sec\n", mb_sec); printf("SHA256 rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_SHA // #ifdef CONFIG_MBEDTLS_HARDWARE_SHA
// Don't put a hard limit on software SHA performance // // Don't put a hard limit on software SHA performance
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); // TEST_PERFORMANCE_CCOMP_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif // #endif
} }
@@ -431,7 +431,7 @@ int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
} }
#ifdef MBEDTLS_SHA1_C #if (defined(MBEDTLS_SHA1_C) || defined(PSA_WANT_ALG_SHA_1))
int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac) const u8 *addr[], const size_t *len, u8 *mac)
{ {
@@ -326,14 +326,12 @@ int esp_fast_psk(const char *password, size_t password_len, const uint8_t *ssid,
// Set up key derivation // Set up key derivation
status = psa_key_derivation_setup(&operation, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)); status = psa_key_derivation_setup(&operation, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1));
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
printf("Failed to set up key derivation: %d\n", status);
goto cleanup; goto cleanup;
} }
// Set iteration count // Set iteration count
status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, iterations); status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, iterations);
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
printf("Failed to set iteration count: %d\n", status);
goto cleanup; goto cleanup;
} }
@@ -341,7 +339,6 @@ int esp_fast_psk(const char *password, size_t password_len, const uint8_t *ssid,
status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT,
ssid, ssid_len); ssid, ssid_len);
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
printf("Failed to add salt: %d\n", status);
goto cleanup; goto cleanup;
} }
@@ -349,14 +346,12 @@ int esp_fast_psk(const char *password, size_t password_len, const uint8_t *ssid,
status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD, status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_PASSWORD,
(const uint8_t*)password, password_len); (const uint8_t*)password, password_len);
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
printf("Failed to add password: %d\n", status);
goto cleanup; goto cleanup;
} }
// Generate output // Generate output
status = psa_key_derivation_output_bytes(&operation, output, output_len); status = psa_key_derivation_output_bytes(&operation, output, output_len);
if (status != PSA_SUCCESS) { if (status != PSA_SUCCESS) {
printf("Failed to generate output: %d\n", status);
goto cleanup; goto cleanup;
} }
@@ -59,7 +59,7 @@
#error "TLS not enabled in mbedtls config" #error "TLS not enabled in mbedtls config"
#endif #endif
#if !defined(MBEDTLS_SHA256_C) #if (!defined(MBEDTLS_SHA256_C) && !defined(PSA_WANT_ALG_SHA_256))
#error "SHA256 is disabled in mbedtls config" #error "SHA256 is disabled in mbedtls config"
#endif #endif
+109 -66
View File
@@ -23,9 +23,7 @@
#include "esp_blufi_api.h" #include "esp_blufi_api.h"
#include "blufi_example.h" #include "blufi_example.h"
#include "mbedtls/aes.h" #include "psa/crypto.h"
#include "mbedtls/dhm.h"
#include "mbedtls/md5.h"
#include "esp_crc.h" #include "esp_crc.h"
/* /*
@@ -40,10 +38,10 @@
struct blufi_security { struct blufi_security {
#define DH_SELF_PUB_KEY_LEN 128
#define DH_PARAM_LEN_MAX 1024 #define DH_PARAM_LEN_MAX 1024
#define DH_SELF_PUB_KEY_LEN 256
uint8_t self_public_key[DH_SELF_PUB_KEY_LEN]; uint8_t self_public_key[DH_SELF_PUB_KEY_LEN];
#define SHARE_KEY_LEN 128 #define SHARE_KEY_LEN 256
uint8_t share_key[SHARE_KEY_LEN]; uint8_t share_key[SHARE_KEY_LEN];
size_t share_len; size_t share_len;
#define PSK_LEN 16 #define PSK_LEN 16
@@ -51,17 +49,10 @@ struct blufi_security {
uint8_t *dh_param; uint8_t *dh_param;
int dh_param_len; int dh_param_len;
uint8_t iv[16]; uint8_t iv[16];
mbedtls_dhm_context dhm; psa_key_id_t aes_key;
mbedtls_aes_context aes;
}; };
static struct blufi_security *blufi_sec; static struct blufi_security *blufi_sec;
static int myrand( void *rng_state, unsigned char *output, size_t len )
{
esp_fill_random(output, len);
return( 0 );
}
extern void btc_blufi_report_error(esp_blufi_error_state_t state); extern void btc_blufi_report_error(esp_blufi_error_state_t state);
void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free) void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free)
@@ -72,7 +63,6 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
return; return;
} }
int ret;
uint8_t type = data[0]; uint8_t type = data[0];
if (blufi_sec == NULL) { if (blufi_sec == NULL) {
@@ -116,56 +106,77 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
return; return;
} }
uint8_t *param = blufi_sec->dh_param; uint8_t *param = blufi_sec->dh_param;
memcpy(blufi_sec->dh_param, &data[1], blufi_sec->dh_param_len); memcpy(blufi_sec->dh_param, &data[1], blufi_sec->dh_param_len);
ret = mbedtls_dhm_read_params(&blufi_sec->dhm, &param, &param[blufi_sec->dh_param_len]); size_t p_len = (param[0] << 8) | param[1];
if (ret) { param += 2 + p_len;
BLUFI_ERROR("%s read param failed %d\n", __func__, ret);
btc_blufi_report_error(ESP_BLUFI_READ_PARAM_ERROR); size_t g_len = (param[0] << 8) | param[1];
param += 2 + g_len;
size_t pub_len = (param[0] << 8) | param[1];
param += 2;
ESP_LOGI("blfi", "P len %d, G len %d, pub len %d", p_len, g_len, pub_len);
psa_key_type_t key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
size_t key_bits = 2048;
ESP_LOGI("blfi", "DH param len %d, bits %d", blufi_sec->dh_param_len, key_bits);
psa_algorithm_t alg = PSA_ALG_FFDH;
psa_key_attributes_t attributes = psa_key_attributes_init();
psa_set_key_type(&attributes, key_type);
psa_set_key_bits(&attributes, key_bits);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_key_id_t private_key = 0;
psa_status_t status = psa_generate_key(&attributes, &private_key);
if (status != PSA_SUCCESS) {
BLUFI_ERROR("%s psa_generate_key failed %d\n", __func__, status);
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
return; return;
} }
free(blufi_sec->dh_param); psa_reset_key_attributes(&attributes);
blufi_sec->dh_param = NULL; size_t public_key_len = 0;
status = psa_export_public_key(private_key, blufi_sec->self_public_key, DH_SELF_PUB_KEY_LEN, &public_key_len);\
const int dhm_len = mbedtls_dhm_get_len(&blufi_sec->dhm); if (status != PSA_SUCCESS) {
BLUFI_ERROR("%s psa_export_public_key failed %d\n", __func__, status);
if (dhm_len > DH_SELF_PUB_KEY_LEN) { psa_destroy_key(private_key);
BLUFI_ERROR("%s dhm len not support %d\n", __func__, dhm_len); btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR);
return; return;
} }
ret = mbedtls_dhm_make_public(&blufi_sec->dhm, dhm_len, blufi_sec->self_public_key, DH_SELF_PUB_KEY_LEN, myrand, NULL); status = psa_raw_key_agreement(alg, private_key, param, pub_len, blufi_sec->share_key, SHARE_KEY_LEN, &blufi_sec->share_len);
if (ret) { psa_destroy_key(private_key);
BLUFI_ERROR("%s make public failed %d\n", __func__, ret); if (status != PSA_SUCCESS) {
btc_blufi_report_error(ESP_BLUFI_MAKE_PUBLIC_ERROR); BLUFI_ERROR("%s psa_raw_key_agreement failed %d\n", __func__, status);
free(blufi_sec->dh_param);
blufi_sec->dh_param = NULL;
return; return;
} }
ret = mbedtls_dhm_calc_secret( &blufi_sec->dhm, size_t hash_length = 0;
blufi_sec->share_key, status = psa_hash_compute(PSA_ALG_MD5, blufi_sec->share_key, blufi_sec->share_len, blufi_sec->psk, PSK_LEN, &hash_length);
SHARE_KEY_LEN, if (status != PSA_SUCCESS) {
&blufi_sec->share_len, BLUFI_ERROR("%s psa_hash_compute failed %d\n", __func__, status);
myrand, NULL);
if (ret) {
BLUFI_ERROR("%s mbedtls_dhm_calc_secret failed %d\n", __func__, ret);
btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR);
return;
}
ret = mbedtls_md5(blufi_sec->share_key, blufi_sec->share_len, blufi_sec->psk);
if (ret) {
BLUFI_ERROR("%s mbedtls_md5 failed %d\n", __func__, ret);
btc_blufi_report_error(ESP_BLUFI_CALC_MD5_ERROR); btc_blufi_report_error(ESP_BLUFI_CALC_MD5_ERROR);
return; return;
} }
mbedtls_aes_setkey_enc(&blufi_sec->aes, blufi_sec->psk, PSK_LEN * 8); // mbedtls_aes_setkey_enc(&blufi_sec->aes, blufi_sec->psk, PSK_LEN * 8);
attributes = psa_key_attributes_init();
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, PSK_LEN * 8);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
status = psa_import_key(&attributes, blufi_sec->psk, PSK_LEN, &blufi_sec->aes_key);
if (status != PSA_SUCCESS) {
BLUFI_ERROR("%s psa_import_key failed %d\n", __func__, status);
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
return;
}
/* alloc output data */ /* alloc output data */
*output_data = &blufi_sec->self_public_key[0]; *output_data = &blufi_sec->self_public_key[0];
*output_len = dhm_len; *output_len = public_key_len;
*need_free = false; *need_free = false;
} }
@@ -181,40 +192,76 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
int blufi_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len) int blufi_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len)
{ {
int ret;
size_t iv_offset = 0;
uint8_t iv0[16]; uint8_t iv0[16];
if (!blufi_sec) { if (!blufi_sec) {
return -1; return -1;
} }
memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv)); psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
iv0[0] = iv8; /* set iv8 as the iv0[0] */ psa_status_t status = psa_cipher_encrypt_setup(&operation, blufi_sec->aes_key, PSA_ALG_CFB);
if (status != PSA_SUCCESS) {
ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_ENCRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data);
if (ret) {
return -1; return -1;
} }
return crypt_len; memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv));
iv0[0] = iv8;
status = psa_cipher_set_iv(&operation, iv0, sizeof(iv0));
if (status != PSA_SUCCESS) {
psa_cipher_abort(&operation);
return -1;
}
size_t encrypt_out_len = 0;
status = psa_cipher_update(&operation, crypt_data, crypt_len, crypt_data, crypt_len, &encrypt_out_len);
if (status != PSA_SUCCESS) {
psa_cipher_abort(&operation);
return -1;
}
status = psa_cipher_finish(&operation, crypt_data, crypt_len, &encrypt_out_len);
if (status != PSA_SUCCESS) {
psa_cipher_abort(&operation);
return -1;
}
return encrypt_out_len;
} }
int blufi_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len) int blufi_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len)
{ {
int ret;
size_t iv_offset = 0;
uint8_t iv0[16]; uint8_t iv0[16];
if (!blufi_sec) { if (!blufi_sec) {
return -1; return -1;
} }
memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv)); psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
iv0[0] = iv8; /* set iv8 as the iv0[0] */ psa_status_t status = psa_cipher_decrypt_setup(&operation, blufi_sec->aes_key, PSA_ALG_CFB);
if (status != PSA_SUCCESS) {
return -1;
}
ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_DECRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data); memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv));
if (ret) { iv0[0] = iv8;
status = psa_cipher_set_iv(&operation, iv0, sizeof(iv0));
if (status != PSA_SUCCESS) {
psa_cipher_abort(&operation);
return -1;
}
size_t encrypt_out_len = 0;
status = psa_cipher_update(&operation, crypt_data, crypt_len, crypt_data, crypt_len, &encrypt_out_len);
if (status != PSA_SUCCESS) {
psa_cipher_abort(&operation);
return -1;
}
status = psa_cipher_finish(&operation, crypt_data, crypt_len, &encrypt_out_len);
if (status != PSA_SUCCESS) {
psa_cipher_abort(&operation);
return -1; return -1;
} }
@@ -236,9 +283,6 @@ esp_err_t blufi_security_init(void)
memset(blufi_sec, 0x0, sizeof(struct blufi_security)); memset(blufi_sec, 0x0, sizeof(struct blufi_security));
mbedtls_dhm_init(&blufi_sec->dhm);
mbedtls_aes_init(&blufi_sec->aes);
memset(blufi_sec->iv, 0x0, sizeof(blufi_sec->iv)); memset(blufi_sec->iv, 0x0, sizeof(blufi_sec->iv));
return 0; return 0;
} }
@@ -252,8 +296,7 @@ void blufi_security_deinit(void)
free(blufi_sec->dh_param); free(blufi_sec->dh_param);
blufi_sec->dh_param = NULL; blufi_sec->dh_param = NULL;
} }
mbedtls_dhm_free(&blufi_sec->dhm); psa_destroy_key(blufi_sec->aes_key);
mbedtls_aes_free(&blufi_sec->aes);
memset(blufi_sec, 0x0, sizeof(struct blufi_security)); memset(blufi_sec, 0x0, sizeof(struct blufi_security));
@@ -16,7 +16,8 @@
#include "esp_mac.h" #include "esp_mac.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "mbedtls/sha256.h" // #include "mbedtls/sha256.h"
#include "psa/crypto.h"
#include "esp_ble_mesh_common_api.h" #include "esp_ble_mesh_common_api.h"
#include "esp_ble_mesh_networking_api.h" #include "esp_ble_mesh_networking_api.h"
@@ -32,6 +33,8 @@
#include "genie_mesh.h" #include "genie_mesh.h"
#include "ble_mesh_example_init.h" #include "ble_mesh_example_init.h"
#include "ble_mesh_example_nvs.h" #include "ble_mesh_example_nvs.h"
#include "psa/crypto_struct.h"
#include "psa/crypto_values.h"
static const char *TAG = "genie_demo"; static const char *TAG = "genie_demo";
@@ -1335,7 +1338,12 @@ void config_triples(void)
ESP_LOGI(TAG, "authvalue_string: %s", authvalue_string); ESP_LOGI(TAG, "authvalue_string: %s", authvalue_string);
uint8_t sha256_out[32] = {0}; uint8_t sha256_out[32] = {0};
mbedtls_sha256((const unsigned char *)authvalue_string, strlen(authvalue_string), sha256_out, 0); size_t hash_length = 0;
psa_status_t status = psa_hash_compute(PSA_ALG_SHA_256, (const uint8_t *)authvalue_string, strlen(authvalue_string), sha256_out, sizeof(sha256_out), &hash_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to compute hash, status: %ld", status);
return;
}
memcpy(static_val, sha256_out, 16); memcpy(static_val, sha256_out, 16);
provision.static_val = static_val; provision.static_val = static_val;
@@ -1 +1,2 @@
CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y CONFIG_EXAMPLE_WIFI_SSID_PWD_FROM_STDIN=y
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x6000,
phy_init, data, phy, , 0x1000,
factory, app, factory, , 0x170000,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, , 0x6000,
4 phy_init, data, phy, , 0x1000,
5 factory, app, factory, , 0x170000,
@@ -18,3 +18,5 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# On chips with USB serial, disable secondary console which does not make sense when using console component # On chips with USB serial, disable secondary console which does not make sense when using console component
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_SIZE=y
@@ -2,6 +2,8 @@
# in this exact order for cmake to work correctly # in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.22) cmake_minimum_required(VERSION 3.22)
list(APPEND sdkconfig_defaults ${CMAKE_CURRENT_SOURCE_DIR}/mbedtls_preset_clang.conf)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# Note: not setting set(COMPONENTS main) here, this app should build all the components # Note: not setting set(COMPONENTS main) here, this app should build all the components
project(clang_build_test) project(clang_build_test)
@@ -0,0 +1,3 @@
# For clang build test, size optimization build fails as the compiler
# crashes trying to create a build. For this test, we can safely skip this optimization
CONFIG_MBEDTLS_COMPILER_OPTIMIZATION_NONE=y