mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(mbedtls): adds AES drivers with PSA
This commit is contained in:
@@ -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-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-C5 | | | | | ![alt text][supported] | ![alt text][supported] |[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-H4 | | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-H4) |
|
||||
|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] |since v5.5.1, [Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-supported-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-preview-orange "preview"
|
||||
|
||||
+3
-4
@@ -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-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-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-C61 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|ESP32-H4 | | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-H4) |
|
||||
|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] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|
||||
|ESP32-C61 | | | | |![alt text][supported] |![alt text][supported] | 自 v5.5.1 开始,[芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|
||||
|
||||
[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"
|
||||
|
||||
@@ -666,9 +666,8 @@ esp_err_t esp_mbedtls_server_session_ticket_ctx_init(esp_tls_server_session_tick
|
||||
int ret;
|
||||
esp_err_t esp_ret;
|
||||
if ((ret = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx,
|
||||
mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE,
|
||||
MBEDTLS_CIPHER_AES_256_GCM,
|
||||
CONFIG_ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT)) != 0) {
|
||||
PSA_ALG_GCM, PSA_KEY_TYPE_AES, 256,
|
||||
86400)) != 0) {
|
||||
ESP_LOGE(TAG, "mbedtls_ssl_ticket_setup returned -0x%04X", -ret);
|
||||
mbedtls_print_error_msg(ret);
|
||||
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
|
||||
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);
|
||||
|
||||
// Decrypt
|
||||
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);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
// Decrypt
|
||||
memcpy(nonce, iv, 16);
|
||||
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);
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
// Decrypt
|
||||
memcpy(nonce, iv, 16);
|
||||
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);
|
||||
|
||||
esp_aes_free(&ctx);
|
||||
@@ -168,12 +200,12 @@ static void test_cfb8_aes(size_t buffer_size, const uint8_t expected_cipher_end[
|
||||
|
||||
// Encrypt
|
||||
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);
|
||||
|
||||
// Decrypt
|
||||
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);
|
||||
|
||||
esp_aes_free(&ctx);
|
||||
@@ -205,13 +237,13 @@ static void test_cfb128_aes(size_t buffer_size, const uint8_t expected_cipher_en
|
||||
|
||||
// Encrypt
|
||||
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);
|
||||
|
||||
// Decrypt
|
||||
nc_off = 0;
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if SOC_GCM_SUPPORTED
|
||||
#if CONFIG_SOC_AES_SUPPORT_GCM
|
||||
#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])
|
||||
{
|
||||
@@ -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_AES_SUPPORT_DMA */
|
||||
#endif // CONFIG_SOC_AES_SUPPORT_GCM
|
||||
|
||||
TEST(aes, cbc_aes_256_block_test)
|
||||
{
|
||||
@@ -339,7 +372,7 @@ TEST(aes, cfb128_aes_256_long_dma_test)
|
||||
|
||||
#endif
|
||||
|
||||
#if SOC_GCM_SUPPORTED
|
||||
#if CONFIG_SOC_AES_SUPPORT_GCM
|
||||
TEST(aes, gcm_aes_dma_test)
|
||||
{
|
||||
size_t length = 16;
|
||||
@@ -372,6 +405,7 @@ TEST(aes, gcm_aes_long_dma_test)
|
||||
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
|
||||
#endif /* SOC_GCM_SUPPORTED */
|
||||
#endif /* SOC_AES_SUPPORT_DMA */
|
||||
#endif /* CONFIG_SOC_AES_SUPPORT_GCM */
|
||||
|
||||
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, cfb128_aes_256_long_dma_test);
|
||||
#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);
|
||||
#endif /* CONFIG_SOC_AES_SUPPORT_GCM */
|
||||
#if CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT
|
||||
RUN_TEST_CASE(aes, gcm_aes_long_dma_test);
|
||||
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
|
||||
|
||||
@@ -177,7 +177,7 @@ endif()
|
||||
# Core libraries from the mbedTLS project
|
||||
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")
|
||||
target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include")
|
||||
endif()
|
||||
@@ -268,7 +268,7 @@ if(SHA_PERIPHERAL_TYPE STREQUAL "core")
|
||||
elseif(CONFIG_SOC_SHA_CRYPTO_DMA)
|
||||
set(SHA_CORE_SRCS "${COMPONENT_DIR}/port/sha/core/esp_sha_crypto_dma_impl.c")
|
||||
endif()
|
||||
target_sources(tfpsacrypto PRIVATE "${SHA_CORE_SRCS}")
|
||||
target_sources(builtin PRIVATE "${SHA_CORE_SRCS}")
|
||||
endif()
|
||||
|
||||
if(AES_PERIPHERAL_TYPE STREQUAL "dma")
|
||||
@@ -363,9 +363,18 @@ endif()
|
||||
# )
|
||||
# endif()
|
||||
|
||||
# if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES)
|
||||
# target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c")
|
||||
# endif()
|
||||
if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES)
|
||||
target_compile_definitions(tfpsacrypto PRIVATE ESP_AES_DRIVER_ENABLED)
|
||||
target_include_directories(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/include/aes")
|
||||
target_sources(tfpsacrypto PRIVATE
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_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)
|
||||
# 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")
|
||||
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)
|
||||
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)
|
||||
target_compile_options(${COMPONENT_LIB} INTERFACE "-O2")
|
||||
target_compile_options(${COMPONENT_LIB} ${compiler_linkage_type} "-O2")
|
||||
endif()
|
||||
|
||||
if(CONFIG_MBEDTLS_DYNAMIC_BUFFER)
|
||||
|
||||
@@ -3,7 +3,7 @@ menu "mbedTLS"
|
||||
menu "Core Configuration"
|
||||
choice MBEDTLS_COMPILER_OPTIMIZATION
|
||||
prompt "Compiler optimization level"
|
||||
default MBEDTLS_COMPILER_OPTIMIZATION_NONE
|
||||
default MBEDTLS_COMPILER_OPTIMIZATION_SIZE
|
||||
help
|
||||
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.
|
||||
@@ -1487,7 +1487,7 @@ menu "mbedTLS"
|
||||
|
||||
config MBEDTLS_HARDWARE_SHA
|
||||
bool "Enable hardware SHA acceleration"
|
||||
default y
|
||||
default n
|
||||
depends on !SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_SHA_SUPPORTED
|
||||
help
|
||||
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
|
||||
#define MBEDTLS_GCM_ALT
|
||||
#ifdef CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER
|
||||
@@ -1968,6 +1959,31 @@
|
||||
#undef MBEDTLS_AES_C
|
||||
#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
|
||||
*
|
||||
@@ -2950,24 +2966,23 @@
|
||||
#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
|
||||
* library/mbedtls_md.c
|
||||
* library/md.c
|
||||
* library/ssl_tls.c
|
||||
* library/ssl*_client.c
|
||||
* library/ssl*_server.c=
|
||||
* library/ssl_cookie.c
|
||||
*
|
||||
* This module adds support for SHA-224 and SHA-256.
|
||||
* This module is required for the SSL/TLS 1.2 PRF function.
|
||||
* This module adds support for SHA-384 and SHA-512.
|
||||
*/
|
||||
#ifdef CONFIG_MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#ifdef CONFIG_MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#else
|
||||
#undef MBEDTLS_SHA256_C
|
||||
#undef MBEDTLS_SHA512_C
|
||||
#undef PSA_WANT_ALG_SHA_512
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -2992,23 +3007,56 @@
|
||||
#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
|
||||
* library/md.c
|
||||
* library/mbedtls_md.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
|
||||
#define MBEDTLS_SHA512_C
|
||||
#ifdef CONFIG_MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#else
|
||||
#undef MBEDTLS_SHA512_C
|
||||
#undef PSA_WANT_ALG_SHA_512
|
||||
#undef MBEDTLS_SHA256_C
|
||||
#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
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,52 +10,52 @@
|
||||
#define MBEDTLS_PLATFORM_GET_ENTROPY_ALT
|
||||
#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_RIPEMD160_C
|
||||
#define MBEDTLS_RIPEMD160_C
|
||||
#else
|
||||
#undef MBEDTLS_RIPEMD160_C
|
||||
#undef PSA_WANT_ALG_RIPEMD160
|
||||
#endif
|
||||
// #ifdef CONFIG_MBEDTLS_RIPEMD160_C
|
||||
// #define MBEDTLS_RIPEMD160_C
|
||||
// #else
|
||||
// #undef MBEDTLS_RIPEMD160_C
|
||||
// #undef PSA_WANT_ALG_RIPEMD160
|
||||
// #endif
|
||||
|
||||
#if CONFIG_MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#else
|
||||
#undef MBEDTLS_SHA1_C
|
||||
#undef PSA_WANT_ALG_SHA_1
|
||||
#endif
|
||||
// #if CONFIG_MBEDTLS_SHA1_C
|
||||
// #define MBEDTLS_SHA1_C
|
||||
// #else
|
||||
// #undef MBEDTLS_SHA1_C
|
||||
// #undef PSA_WANT_ALG_SHA_1
|
||||
// #endif
|
||||
|
||||
#if CONFIG_MBEDTLS_SHA384_C
|
||||
#define MBEDTLS_SHA384_C
|
||||
#else
|
||||
#undef MBEDTLS_SHA384_C
|
||||
#undef PSA_WANT_ALG_SHA_384
|
||||
#endif
|
||||
// #if CONFIG_MBEDTLS_SHA384_C
|
||||
// #define MBEDTLS_SHA384_C
|
||||
// #else
|
||||
// #undef MBEDTLS_SHA384_C
|
||||
// #undef PSA_WANT_ALG_SHA_384
|
||||
// #endif
|
||||
|
||||
#if CONFIG_MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#else
|
||||
#undef MBEDTLS_SHA512_C
|
||||
#undef PSA_WANT_ALG_SHA_512
|
||||
#endif
|
||||
// #if CONFIG_MBEDTLS_SHA512_C
|
||||
// #define MBEDTLS_SHA512_C
|
||||
// #else
|
||||
// #undef MBEDTLS_SHA512_C
|
||||
// #undef PSA_WANT_ALG_SHA_512
|
||||
// #endif
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_CAMELLIA_C
|
||||
#error "MBEDTLS_CAMELLIA_C defined in config"
|
||||
#define MBEDTLS_CAMELLIA_C
|
||||
#else
|
||||
#undef MBEDTLS_CAMELLIA_C
|
||||
#undef PSA_WANT_KEY_TYPE_CAMELLIA
|
||||
#endif
|
||||
// #ifdef CONFIG_MBEDTLS_CAMELLIA_C
|
||||
// #error "MBEDTLS_CAMELLIA_C defined in config"
|
||||
// #define MBEDTLS_CAMELLIA_C
|
||||
// #else
|
||||
// #undef MBEDTLS_CAMELLIA_C
|
||||
// #undef PSA_WANT_KEY_TYPE_CAMELLIA
|
||||
// #endif
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_MD5_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#else
|
||||
#undef MBEDTLS_MD5_C
|
||||
#undef PSA_WANT_ALG_MD5
|
||||
#endif
|
||||
// #ifdef CONFIG_MBEDTLS_MD5_C
|
||||
// #define MBEDTLS_MD5_C
|
||||
// #else
|
||||
// #undef MBEDTLS_MD5_C
|
||||
// #undef PSA_WANT_ALG_MD5
|
||||
// #endif
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#else
|
||||
#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
#undef PSA_WANT_ECC_SECP_R1_384
|
||||
#endif
|
||||
// #ifdef CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
// #define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
// #else
|
||||
// #undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||
// #undef PSA_WANT_ECC_SECP_R1_384
|
||||
// #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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
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_length)
|
||||
{
|
||||
printf("SHA256 Driver Compute\n");
|
||||
// printf("SHA256 Driver Compute\n");
|
||||
if (!hash || !hash_length) {
|
||||
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;
|
||||
}
|
||||
if (hash_size < PSA_HASH_LENGTH(alg)) {
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
#if SOC_SHA_SUPPORT_SHA224
|
||||
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);
|
||||
if (ret != ESP_OK) {
|
||||
return PSA_ERROR_HARDWARE_FAILURE;
|
||||
@@ -229,9 +237,12 @@ psa_status_t esp_sha256_driver_finish(
|
||||
if (ret != ESP_OK) {
|
||||
return PSA_ERROR_HARDWARE_FAILURE;
|
||||
}
|
||||
#if SOC_SHA_SUPPORT_SHA224
|
||||
if (sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
|
||||
*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);
|
||||
} else {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include "esp_sha_internal.h"
|
||||
#include "sha/sha_core.h"
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_SOC_SHA_SUPPORT_SHA512
|
||||
|
||||
#ifndef PUT_UINT64_BE
|
||||
#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)
|
||||
{
|
||||
if (ctx->sha_state == ESP_SHA512_STATE_INIT) {
|
||||
if (ctx->mode == SHA2_512T) {
|
||||
if (ctx->mode == SHA2_512) {
|
||||
int ret = -1;
|
||||
if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) {
|
||||
return ret;
|
||||
@@ -179,9 +182,12 @@ static int esp_sha512_finish(esp_sha512_context *ctx, unsigned char *output)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if SOC_SHA_SUPPORT_SHA384
|
||||
if (ctx->mode == SHA2_384) {
|
||||
memcpy(output, ctx->state, 48);
|
||||
} else {
|
||||
} else
|
||||
#endif // SOC_SHA_SUPPORT_SHA384
|
||||
{
|
||||
memcpy(output, ctx->state, 64);
|
||||
}
|
||||
|
||||
@@ -207,7 +213,10 @@ psa_status_t esp_sha512_driver_compute(
|
||||
if (hash_size < PSA_HASH_LENGTH(alg)) {
|
||||
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);
|
||||
if (ret != ESP_OK) {
|
||||
return PSA_ERROR_HARDWARE_FAILURE;
|
||||
@@ -271,3 +280,5 @@ psa_status_t esp_sha512_driver_finish(
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // SOC_SHA_SUPPORT_SHA512
|
||||
|
||||
-11
@@ -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
|
||||
};
|
||||
|
||||
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 )
|
||||
{
|
||||
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 <esp_system.h>
|
||||
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
|
||||
#include "mbedtls/aes.h"
|
||||
#include "mbedtls/gcm.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "unity.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_heap_caps.h"
|
||||
@@ -22,25 +21,49 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
|
||||
{
|
||||
const unsigned CALLS = 256;
|
||||
const unsigned CALL_SZ = 32 * 1024;
|
||||
mbedtls_aes_context ctx;
|
||||
float elapsed_usec;
|
||||
uint8_t iv[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(key, 0x44, 16);
|
||||
|
||||
// allocate internal memory
|
||||
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
TEST_ASSERT_NOT_NULL(buf);
|
||||
mbedtls_aes_init(&ctx);
|
||||
mbedtls_aes_setkey_enc(&ctx, key, 128);
|
||||
psa_key_id_t key_id;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
|
||||
psa_set_key_algorithm(&attributes, PSA_ALG_CBC_NO_PADDING);
|
||||
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
|
||||
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();
|
||||
size_t output_length = 0;
|
||||
for (int c = 0; c < CALLS; c++) {
|
||||
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();
|
||||
|
||||
/* 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);
|
||||
|
||||
mbedtls_aes_free(&ctx);
|
||||
// mbedtls_aes_free(&ctx);
|
||||
psa_destroy_key(key_id);
|
||||
psa_reset_key_attributes(&attributes);
|
||||
free(buf);
|
||||
|
||||
mbedtls_psa_crypto_free();
|
||||
|
||||
// bytes/usec = MB/sec
|
||||
float mb_sec = (CALL_SZ * CALLS) / elapsed_usec;
|
||||
printf("Encryption rate %.3fMB/sec\n", mb_sec);
|
||||
// Commenting out this for now as we do not have hardware support with PSA
|
||||
// #ifdef CONFIG_MBEDTLS_HARDWARE_AES
|
||||
// // Don't put a hard limit on software AES performance
|
||||
// TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
|
||||
// #endif
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_AES
|
||||
// Don't put a hard limit on software AES performance
|
||||
TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
|
||||
#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 "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 CALL_SZ = 16 * 1024;
|
||||
@@ -61,8 +63,8 @@ TEST_CASE("mbedtls SHA performance", "[mbedtls]")
|
||||
// bytes/usec = MB/sec
|
||||
float mb_sec = (CALL_SZ * CALLS) / elapsed_usec;
|
||||
printf("SHA256 rate %.3fMB/sec\n", mb_sec);
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_SHA
|
||||
// Don't put a hard limit on software SHA performance
|
||||
TEST_PERFORMANCE_CCOMP_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
|
||||
#endif
|
||||
// #ifdef CONFIG_MBEDTLS_HARDWARE_SHA
|
||||
// // Don't put a hard limit on software SHA performance
|
||||
// TEST_PERFORMANCE_CCOMP_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
|
||||
// #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);
|
||||
}
|
||||
|
||||
#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,
|
||||
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
|
||||
status = psa_key_derivation_setup(&operation, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1));
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf("Failed to set up key derivation: %d\n", status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Set iteration count
|
||||
status = psa_key_derivation_input_integer(&operation, PSA_KEY_DERIVATION_INPUT_COST, iterations);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf("Failed to set iteration count: %d\n", status);
|
||||
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,
|
||||
ssid, ssid_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf("Failed to add salt: %d\n", status);
|
||||
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,
|
||||
(const uint8_t*)password, password_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf("Failed to add password: %d\n", status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Generate output
|
||||
status = psa_key_derivation_output_bytes(&operation, output, output_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
printf("Failed to generate output: %d\n", status);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
#error "TLS not enabled in mbedtls config"
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_SHA256_C)
|
||||
#if (!defined(MBEDTLS_SHA256_C) && !defined(PSA_WANT_ALG_SHA_256))
|
||||
#error "SHA256 is disabled in mbedtls config"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
#include "esp_blufi_api.h"
|
||||
#include "blufi_example.h"
|
||||
|
||||
#include "mbedtls/aes.h"
|
||||
#include "mbedtls/dhm.h"
|
||||
#include "mbedtls/md5.h"
|
||||
#include "psa/crypto.h"
|
||||
#include "esp_crc.h"
|
||||
|
||||
/*
|
||||
@@ -40,10 +38,10 @@
|
||||
|
||||
|
||||
struct blufi_security {
|
||||
#define DH_SELF_PUB_KEY_LEN 128
|
||||
#define DH_PARAM_LEN_MAX 1024
|
||||
#define DH_SELF_PUB_KEY_LEN 256
|
||||
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];
|
||||
size_t share_len;
|
||||
#define PSK_LEN 16
|
||||
@@ -51,17 +49,10 @@ struct blufi_security {
|
||||
uint8_t *dh_param;
|
||||
int dh_param_len;
|
||||
uint8_t iv[16];
|
||||
mbedtls_dhm_context dhm;
|
||||
mbedtls_aes_context aes;
|
||||
psa_key_id_t aes_key;
|
||||
};
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int ret;
|
||||
uint8_t type = data[0];
|
||||
|
||||
if (blufi_sec == NULL) {
|
||||
@@ -116,56 +106,77 @@ void blufi_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_da
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uint8_t *param = blufi_sec->dh_param;
|
||||
memcpy(blufi_sec->dh_param, &data[1], blufi_sec->dh_param_len);
|
||||
ret = mbedtls_dhm_read_params(&blufi_sec->dhm, ¶m, ¶m[blufi_sec->dh_param_len]);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s read param failed %d\n", __func__, ret);
|
||||
btc_blufi_report_error(ESP_BLUFI_READ_PARAM_ERROR);
|
||||
size_t p_len = (param[0] << 8) | param[1];
|
||||
param += 2 + p_len;
|
||||
|
||||
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;
|
||||
}
|
||||
free(blufi_sec->dh_param);
|
||||
blufi_sec->dh_param = NULL;
|
||||
|
||||
const int dhm_len = mbedtls_dhm_get_len(&blufi_sec->dhm);
|
||||
|
||||
if (dhm_len > DH_SELF_PUB_KEY_LEN) {
|
||||
BLUFI_ERROR("%s dhm len not support %d\n", __func__, dhm_len);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR);
|
||||
psa_reset_key_attributes(&attributes);
|
||||
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);\
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_export_public_key failed %d\n", __func__, status);
|
||||
psa_destroy_key(private_key);
|
||||
btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mbedtls_dhm_make_public(&blufi_sec->dhm, dhm_len, blufi_sec->self_public_key, DH_SELF_PUB_KEY_LEN, myrand, NULL);
|
||||
if (ret) {
|
||||
BLUFI_ERROR("%s make public failed %d\n", __func__, ret);
|
||||
btc_blufi_report_error(ESP_BLUFI_MAKE_PUBLIC_ERROR);
|
||||
status = psa_raw_key_agreement(alg, private_key, param, pub_len, blufi_sec->share_key, SHARE_KEY_LEN, &blufi_sec->share_len);
|
||||
psa_destroy_key(private_key);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_raw_key_agreement failed %d\n", __func__, status);
|
||||
free(blufi_sec->dh_param);
|
||||
blufi_sec->dh_param = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ret = mbedtls_dhm_calc_secret( &blufi_sec->dhm,
|
||||
blufi_sec->share_key,
|
||||
SHARE_KEY_LEN,
|
||||
&blufi_sec->share_len,
|
||||
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);
|
||||
size_t hash_length = 0;
|
||||
status = psa_hash_compute(PSA_ALG_MD5, blufi_sec->share_key, blufi_sec->share_len, blufi_sec->psk, PSK_LEN, &hash_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
BLUFI_ERROR("%s psa_hash_compute failed %d\n", __func__, status);
|
||||
btc_blufi_report_error(ESP_BLUFI_CALC_MD5_ERROR);
|
||||
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 */
|
||||
*output_data = &blufi_sec->self_public_key[0];
|
||||
*output_len = dhm_len;
|
||||
*output_len = public_key_len;
|
||||
*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 ret;
|
||||
size_t iv_offset = 0;
|
||||
uint8_t iv0[16];
|
||||
|
||||
if (!blufi_sec) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv));
|
||||
iv0[0] = iv8; /* set iv8 as the iv0[0] */
|
||||
|
||||
ret = mbedtls_aes_crypt_cfb128(&blufi_sec->aes, MBEDTLS_AES_ENCRYPT, crypt_len, &iv_offset, iv0, crypt_data, crypt_data);
|
||||
if (ret) {
|
||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||
psa_status_t status = psa_cipher_encrypt_setup(&operation, blufi_sec->aes_key, PSA_ALG_CFB);
|
||||
if (status != PSA_SUCCESS) {
|
||||
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 ret;
|
||||
size_t iv_offset = 0;
|
||||
uint8_t iv0[16];
|
||||
|
||||
if (!blufi_sec) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(iv0, blufi_sec->iv, sizeof(blufi_sec->iv));
|
||||
iv0[0] = iv8; /* set iv8 as the iv0[0] */
|
||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||
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);
|
||||
if (ret) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -236,9 +283,6 @@ esp_err_t blufi_security_init(void)
|
||||
|
||||
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));
|
||||
return 0;
|
||||
}
|
||||
@@ -252,8 +296,7 @@ void blufi_security_deinit(void)
|
||||
free(blufi_sec->dh_param);
|
||||
blufi_sec->dh_param = NULL;
|
||||
}
|
||||
mbedtls_dhm_free(&blufi_sec->dhm);
|
||||
mbedtls_aes_free(&blufi_sec->aes);
|
||||
psa_destroy_key(blufi_sec->aes_key);
|
||||
|
||||
memset(blufi_sec, 0x0, sizeof(struct blufi_security));
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
#include "esp_mac.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_networking_api.h"
|
||||
@@ -32,6 +33,8 @@
|
||||
#include "genie_mesh.h"
|
||||
#include "ble_mesh_example_init.h"
|
||||
#include "ble_mesh_example_nvs.h"
|
||||
#include "psa/crypto_struct.h"
|
||||
#include "psa/crypto_values.h"
|
||||
|
||||
static const char *TAG = "genie_demo";
|
||||
|
||||
@@ -1335,7 +1338,12 @@ void config_triples(void)
|
||||
ESP_LOGI(TAG, "authvalue_string: %s", authvalue_string);
|
||||
|
||||
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);
|
||||
provision.static_val = static_val;
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
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,
|
||||
|
@@ -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
|
||||
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
|
||||
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)
|
||||
# Note: not setting set(COMPONENTS main) here, this app should build all the components
|
||||
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
|
||||
Reference in New Issue
Block a user