fix(mbedtls): Enable h/w accel for CMAC and HMAC operations

- Refactor ESP-MAC drivers
This commit is contained in:
harshal.patil
2026-01-20 18:51:56 +05:30
parent 4984738936
commit 53072bfa9d
18 changed files with 920 additions and 884 deletions
+6 -8
View File
@@ -188,10 +188,6 @@ set(mbedtls_targets mbedtls mbedx509 tfpsacrypto builtin)
target_include_directories(tfpsacrypto PUBLIC "port/include")
if(CONFIG_MBEDTLS_HARDWARE_SHA OR CONFIG_MBEDTLS_HARDWARE_AES)
target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include")
endif()
message(STATUS "Setting up mbedtls configuration")
foreach(target ${mbedtls_targets})
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")
@@ -361,8 +357,9 @@ if(CONFIG_SOC_SHA_SUPPORTED)
"${COMPONENT_DIR}/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c"
"${COMPONENT_DIR}/port/psa_driver/esp_sha/${SHA_PERIPHERAL_TYPE}/psa_crypto_driver_esp_sha256.c"
"${COMPONENT_DIR}/port/psa_driver/esp_sha/${SHA_PERIPHERAL_TYPE}/psa_crypto_driver_esp_sha512.c"
"${COMPONENT_DIR}/port/sha/esp_sha.c")
"${COMPONENT_DIR}/port/sha/esp_sha.c"
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac.c"
)
endif()
target_sources(tfpsacrypto PRIVATE
"${COMPONENT_DIR}/port/psa_driver/esp_sha/${SHA_PERIPHERAL_TYPE}/psa_crypto_driver_esp_sha1.c"
@@ -411,9 +408,10 @@ if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES)
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c"
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c"
)
if(CONFIG_MBEDTLS_HARDWARE_SHA)
if(CONFIG_MBEDTLS_CMAC_C)
target_compile_definitions(tfpsacrypto PRIVATE ESP_CMAC_DRIVER_ENABLED)
target_sources(tfpsacrypto PRIVATE
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c"
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_cmac.c"
)
endif()
endif()
@@ -28,6 +28,9 @@ set(GEN_FILES OFF CACHE BOOL "mbedtls: use pre-generated source files")
# Needed to for include_next includes to work from within mbedtls
include_directories("${COMPONENT_DIR}/port/include")
# Add PSA driver include directory globally for mbedtls targets
include_directories("${COMPONENT_DIR}/port/psa_driver/include")
# Import mbedtls library targets
add_subdirectory(mbedtls)
@@ -82,9 +85,10 @@ if(CONFIG_SOC_AES_SUPPORTED)
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c"
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c"
)
if(CONFIG_MBEDTLS_HARDWARE_SHA)
if(CONFIG_MBEDTLS_CMAC_C)
target_compile_definitions(tfpsacrypto PRIVATE ESP_CMAC_DRIVER_ENABLED)
target_sources(tfpsacrypto PRIVATE
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c"
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_cmac.c"
)
endif()
endif()
@@ -99,7 +103,9 @@ if(CONFIG_SOC_SHA_SUPPORTED)
"${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha256.c"
"${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha512.c"
"${COMPONENT_DIR}/port/sha/core/sha.c"
"${COMPONENT_DIR}/port/sha/esp_sha.c")
"${COMPONENT_DIR}/port/sha/esp_sha.c"
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac.c"
)
endif()
if(CONFIG_MBEDTLS_ROM_MD5)
@@ -15,7 +15,6 @@
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include <string.h>
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "aes/esp_aes.h"
#include "aes/esp_aes_gcm.h"
#include "esp_aes_internal.h"
@@ -14,7 +14,99 @@
#include "constant_time_internal.h"
#include "esp_log.h"
static psa_status_t esp_crypto_aes_ecb_update(
static const char *TAG = "psa_crypto_driver_esp_aes";
static psa_status_t esp_aes_cipher_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_NOT_SUPPORTED;
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) {
free(ctx);
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_aes_cipher_setup(esp_aes_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg, PSA_CRYPTO_DRIVER_ENCRYPT);
}
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_aes_cipher_setup(esp_aes_driver_ctx, attributes,
key_buffer, key_buffer_size,
alg, PSA_CRYPTO_DRIVER_DECRYPT);
}
psa_status_t esp_aes_cipher_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_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)
@@ -74,7 +166,7 @@ exit:
return status;
}
static psa_status_t esp_crypto_aes_cbc_update(
static psa_status_t esp_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,
@@ -166,10 +258,12 @@ exit:
return mbedtls_to_psa_error(ret);
}
psa_status_t esp_crypto_aes_update(
psa_status_t esp_aes_cipher_update(
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
int ret = -1;
@@ -187,7 +281,7 @@ psa_status_t esp_crypto_aes_update(
}
if (output_size < expected_output_size) {
ESP_LOGE("TAG", "Output buffer too small: have %zu, need %zu", output_size, expected_output_size);
ESP_LOGE(TAG, "Output buffer too small: have %zu, need %zu", output_size, expected_output_size);
return PSA_ERROR_BUFFER_TOO_SMALL;
}
@@ -199,7 +293,7 @@ psa_status_t esp_crypto_aes_update(
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,
ret = esp_aes_ecb_update(esp_aes_driver_ctx,
input,
input_length,
output,
@@ -249,7 +343,7 @@ psa_status_t esp_crypto_aes_update(
#endif /* CONFIG_MBEDTLS_CIPHER_MODE_OFB */
case PSA_ALG_CBC_NO_PADDING:
case PSA_ALG_CBC_PKCS7:
ret = esp_crypto_aes_cbc_update(esp_aes_driver_ctx,
ret = esp_aes_cbc_update(esp_aes_driver_ctx,
input,
input_length,
output,
@@ -314,9 +408,10 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
}
psa_status_t esp_crypto_aes_finish(
psa_status_t esp_aes_cipher_finish(
esp_aes_operation_t *esp_aes_driver_ctx,
uint8_t *output, size_t output_size,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
int ret = -1;
@@ -421,7 +516,8 @@ exit:
return status;
}
psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_ctx)
psa_status_t esp_aes_cipher_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) {
@@ -432,85 +528,6 @@ psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_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_NOT_SUPPORTED;
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) {
free(ctx);
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,
@@ -533,58 +550,42 @@ psa_status_t esp_aes_cipher_encrypt(
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to setup encryption: %ld", status);
ESP_LOGE(TAG, "Failed to setup encryption: %ld", status);
goto exit;
}
if (iv_length > 0) {
status = esp_crypto_aes_set_iv(&esp_aes_driver_ctx, iv, iv_length);
status = esp_aes_cipher_set_iv(&esp_aes_driver_ctx, iv, iv_length);
if (status != PSA_SUCCESS) {
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to set IV: %ld", status);
ESP_LOGE(TAG, "Failed to set IV: %ld", status);
goto exit;
}
}
status = esp_crypto_aes_update(&esp_aes_driver_ctx, input, input_length,
status = esp_aes_cipher_update(&esp_aes_driver_ctx, input, input_length,
output, output_size,
&update_output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to update: %ld", status);
ESP_LOGE(TAG, "Failed to update: %ld", status);
goto exit;
}
status = esp_crypto_aes_finish(&esp_aes_driver_ctx,
status = esp_aes_cipher_finish(&esp_aes_driver_ctx,
mbedtls_buffer_offset(output, update_output_length),
output_size - update_output_length, &finish_output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to finish: %ld", status);
ESP_LOGE(TAG, "Failed to finish: %ld", status);
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_LOGE("esp_aes_cipher_encrypt", "Failed to abort: %ld", status);
esp_crypto_aes_abort(&esp_aes_driver_ctx);
}
esp_aes_cipher_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,
@@ -601,85 +602,44 @@ psa_status_t esp_aes_cipher_decrypt(
key, key_length,
alg);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to setup decryption: %ld", status);
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,
status = esp_aes_cipher_set_iv(&esp_aes_driver_ctx,
input, iv_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to set IV: %ld", status);
goto exit;
}
}
status = esp_crypto_aes_update(&esp_aes_driver_ctx,
status = esp_aes_cipher_update(&esp_aes_driver_ctx,
mbedtls_buffer_offset_const(input, iv_length),
input_length - iv_length,
output, output_size, &olength);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to update: %ld", status);
goto exit;
}
accumulated_length = olength;
status = esp_crypto_aes_finish(&esp_aes_driver_ctx,
status = esp_aes_cipher_finish(&esp_aes_driver_ctx,
mbedtls_buffer_offset(output, accumulated_length),
output_size - accumulated_length, &olength);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to finish: %ld", status);
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);
}
esp_aes_cipher_abort(&esp_aes_driver_ctx);
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;
}
@@ -1,623 +0,0 @@
/*
* 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) \
do { \
mbedtls_put_unaligned_uint32((data) + (offset), \
(MBEDTLS_IS_BIG_ENDIAN) \
? (uint32_t) (n) \
: MBEDTLS_BSWAP32((uint32_t) (n))); \
} while (0)
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)
{
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 (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 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);
/* 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) {
return status;
}
/* After hashing, key_buffer_size is set to the hash size, which
* should be <= block_size. Verify this for static analysis. */
if (key_buffer_size > block_size) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
}
/* 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) {
/* Additional safety check: ensure key fits in ipad buffer */
if (key_buffer_size > sizeof(ipad)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
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;
}
/* Only fill remaining bytes if key_buffer_size < block_size.
* When key_buffer_size == block_size, the entire buffer is already
* processed, so no padding is needed. This check also prevents
* out-of-bounds pointer arithmetic (ipad + key_buffer_size would be
* out of bounds when key_buffer_size == block_size == sizeof(ipad)). */
if (key_buffer_size < block_size) {
/* At this point: key_buffer_size < block_size <= sizeof(ipad),
* so ipad + key_buffer_size is guaranteed to be within bounds. */
size_t fill_size = block_size - key_buffer_size;
memset(ipad + key_buffer_size, 0x36, fill_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;
}
/* Only fill remaining bytes if key_buffer_size < block_size.
* When key_buffer_size == block_size, the entire buffer is already
* processed, so no padding is needed. This check also prevents
* out-of-bounds pointer arithmetic (operation->opad + key_buffer_size
* would be out of bounds when key_buffer_size == block_size == sizeof(operation->opad)). */
if (key_buffer_size < block_size) {
/* At this point: key_buffer_size < block_size <= sizeof(operation->opad),
* so operation->opad + key_buffer_size is guaranteed to be within bounds. */
size_t fill_size = block_size - key_buffer_size;
memset(operation->opad + key_buffer_size, 0x5C, fill_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 {
(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;
/* 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;
}
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;
}
/* CMAC output is always the cipher block size, regardless of requested mac_size */
size_t output_length = (mac_size < block_size) ? mac_size : block_size;
memcpy(mac, state, output_length);
*mac_length = output_length;
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);
uint8_t tmp[PSA_HASH_MAX_SIZE];
size_t hash_size = 0;
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
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, sizeof(actual_mac), &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;
}
@@ -0,0 +1,403 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_cmac.h"
#include "psa_crypto_driver_esp_cmac_contexts.h"
#include "psa_crypto_driver_esp_aes.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) \
do { \
mbedtls_put_unaligned_uint32((data) + (offset), \
(MBEDTLS_IS_BIG_ENDIAN) \
? (uint32_t) (n) \
: MBEDTLS_BSWAP32((uint32_t) (n))); \
} while (0)
psa_status_t esp_cmac_abort(esp_cmac_operation_t *esp_cmac_ctx)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = psa_destroy_key(esp_cmac_ctx->key_id);
if (status != PSA_SUCCESS) {
return status;
}
status = esp_aes_cipher_abort(&esp_cmac_ctx->esp_aes_ctx);
if (status != PSA_SUCCESS) {
return status;
}
mbedtls_platform_zeroize(esp_cmac_ctx, sizeof(esp_cmac_operation_t));
return status;
}
psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_ctx,
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;
memset(esp_cmac_ctx, 0, sizeof(*esp_cmac_ctx));
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 cmac_aes_key_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, cmac_aes_key_alg);
/* Import key for cipher operations */
status = psa_import_key(&key_attributes, key_buffer, key_buffer_size, &esp_cmac_ctx->key_id);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_aes_cipher_encrypt_setup(&esp_cmac_ctx->esp_aes_ctx, &key_attributes, key_buffer, key_buffer_size, cmac_aes_key_alg);
if (status != PSA_SUCCESS) {
psa_destroy_key(esp_cmac_ctx->key_id);
goto exit;
}
psa_reset_key_attributes(&key_attributes);
esp_cmac_ctx->alg = alg;
esp_cmac_ctx->unprocessed_len = 0;
esp_cmac_ctx->cipher_block_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
mbedtls_platform_zeroize(esp_cmac_ctx->state, sizeof(esp_cmac_ctx->state));
mbedtls_platform_zeroize(esp_cmac_ctx->unprocessed_block, sizeof(esp_cmac_ctx->unprocessed_block));
exit:
psa_reset_key_attributes(&key_attributes);
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];
}
}
psa_status_t esp_cmac_update(esp_cmac_operation_t *esp_cmac_ctx, const uint8_t *data, size_t data_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t n, j, olen, block_size;
unsigned char *state;
if (esp_cmac_ctx == NULL || data == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
state = esp_cmac_ctx->state;
block_size = esp_cmac_ctx->cipher_block_length;
/* Is there data still to process from the last call, that's greater in
* size than a block? */
if (esp_cmac_ctx->unprocessed_len > 0 && data_length > block_size - esp_cmac_ctx->unprocessed_len) {
memcpy(&esp_cmac_ctx->unprocessed_block[esp_cmac_ctx->unprocessed_len], data, block_size - esp_cmac_ctx->unprocessed_len);
xor_no_simd(state, esp_cmac_ctx->unprocessed_block, state, block_size);
if ((status = esp_aes_cipher_update(&esp_cmac_ctx->esp_aes_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
goto exit;
}
data += block_size - esp_cmac_ctx->unprocessed_len;
data_length -= block_size - esp_cmac_ctx->unprocessed_len;
esp_cmac_ctx->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 ((status = esp_aes_cipher_update(&esp_cmac_ctx->esp_aes_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
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(&esp_cmac_ctx->unprocessed_block[esp_cmac_ctx->unprocessed_len], data, data_length);
esp_cmac_ctx->unprocessed_len += data_length;
}
status = PSA_SUCCESS;
exit:
return status;
}
static psa_status_t cmac_multiply_by_u(unsigned char *output,
const unsigned char *input,
size_t blocksize)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
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 {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
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;
}
unsigned char msb = (input[0] >> 7) & 1;
output[blocksize - 1] ^= (unsigned char)(msb * R_n);
status = PSA_SUCCESS;
exit:
return status;
}
static psa_status_t cmac_generate_subkeys(esp_aes_operation_t *esp_aes_driver_ctx, size_t block_size,
uint8_t *K1, uint8_t *K2)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
uint8_t L[PSA_CMAC_MAX_BLOCK_SIZE];
size_t olen;
mbedtls_platform_zeroize(L, sizeof(L));
/* Calculate Ek(0) */
if ((status = esp_aes_cipher_update(esp_aes_driver_ctx, L, block_size, L, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
goto exit;
}
/*
* Generate K1 and K2
*/
if ((status = cmac_multiply_by_u(K1, L, block_size)) != PSA_SUCCESS) {
goto exit;
}
if ((status = cmac_multiply_by_u(K2, K1, block_size)) != PSA_SUCCESS) {
goto exit;
}
exit:
mbedtls_platform_zeroize(L, sizeof(L));
return status;
}
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;
}
}
}
psa_status_t esp_cmac_finish(
esp_cmac_operation_t *esp_cmac_ctx,
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 (esp_cmac_ctx == NULL || mac == NULL || mac_size == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
state = esp_cmac_ctx->state;
block_size = esp_cmac_ctx->cipher_block_length;
mbedtls_platform_zeroize(K1, sizeof(K1));
mbedtls_platform_zeroize(K2, sizeof(K2));
cmac_generate_subkeys(&esp_cmac_ctx->esp_aes_ctx, block_size, K1, K2);
last_block = esp_cmac_ctx->unprocessed_block;
/* Calculate last block */
if (esp_cmac_ctx->unprocessed_len < block_size) {
cmac_pad(M_last, block_size, last_block, esp_cmac_ctx->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 = esp_aes_cipher_update(&esp_cmac_ctx->esp_aes_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
goto exit;
}
/* CMAC output is always the cipher block size, regardless of requested mac_size */
size_t output_length = (mac_size < block_size) ? mac_size : block_size;
memcpy(mac, state, output_length);
*mac_length = output_length;
exit:
mbedtls_platform_zeroize(K1, sizeof(K1));
mbedtls_platform_zeroize(K2, sizeof(K2));
esp_cmac_ctx->unprocessed_len = 0;
mbedtls_platform_zeroize(esp_cmac_ctx->unprocessed_block, sizeof(esp_cmac_ctx->unprocessed_block));
mbedtls_platform_zeroize(state, PSA_CMAC_MAX_BLOCK_SIZE);
return status;
}
psa_status_t esp_cmac_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 esp_cmac_ctx = {0};
status = esp_cmac_setup(&esp_cmac_ctx,
attributes, key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (input_length > 0) {
status = esp_cmac_update(&esp_cmac_ctx, input, input_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
size_t actual_mac_length = 0;
status = esp_cmac_finish(&esp_cmac_ctx, mac, mac_size, &actual_mac_length);
if (status == PSA_SUCCESS) {
*mac_length = actual_mac_length;
}
exit:
esp_cmac_abort(&esp_cmac_ctx);
return status;
}
psa_status_t esp_cmac_verify_finish(
esp_cmac_operation_t *esp_cmac_ctx,
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 (esp_cmac_ctx == 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_finish(esp_cmac_ctx, actual_mac, sizeof(actual_mac), &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;
}
@@ -0,0 +1,250 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_hmac.h"
#include "psa_crypto_driver_esp_hmac_contexts.h"
psa_status_t esp_hmac_abort(esp_hmac_operation_t *esp_hmac_ctx)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = esp_sha_hash_abort(&esp_hmac_ctx->esp_sha_ctx);
if (status != PSA_SUCCESS) {
return status;
}
mbedtls_platform_zeroize(esp_hmac_ctx, sizeof(esp_hmac_operation_t));
return status;
}
psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
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;
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);
if (esp_hmac_ctx == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_operation_t));
/* 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 check against the ipad buffer also covers opad since both
* have the same size (PSA_HMAC_MAX_HASH_BLOCK_SIZE). */
if ((block_size > sizeof(ipad)) || (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) {
return status;
}
/* After hashing, key_buffer_size is set to the hash size, which
* should be <= block_size. Verify this for static analysis. */
if (key_buffer_size > block_size) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
}
/* 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) {
/* Additional safety check: ensure key fits in ipad buffer */
if (key_buffer_size > sizeof(ipad)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
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;
}
/* Only fill remaining bytes if key_buffer_size < block_size.
* When key_buffer_size == block_size, the entire buffer is already
* processed, so no padding is needed. This check also prevents
* out-of-bounds pointer arithmetic (ipad + key_buffer_size would be
* out of bounds when key_buffer_size == block_size == sizeof(ipad)). */
if (key_buffer_size < block_size) {
/* At this point: key_buffer_size < block_size <= sizeof(ipad),
* so ipad + key_buffer_size is guaranteed to be within bounds. */
size_t fill_size = block_size - key_buffer_size;
memset(ipad + key_buffer_size, 0x36, fill_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++) {
esp_hmac_ctx->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
}
/* Only fill remaining bytes if key_buffer_size < block_size.
* When key_buffer_size == block_size, the entire buffer is already
* processed, so no padding is needed. This check also prevents
* out-of-bounds pointer arithmetic (esp_hmac_ctx->opad + key_buffer_size
* would be out of bounds when key_buffer_size == block_size == sizeof(esp_hmac_ctx->opad)). */
if (key_buffer_size < block_size) {
/* At this point: key_buffer_size < block_size <= sizeof(esp_hmac_ctx->opad),
* so esp_hmac_ctx->opad + key_buffer_size is guaranteed to be within bounds. */
size_t fill_size = block_size - key_buffer_size;
memset(esp_hmac_ctx->opad + key_buffer_size, 0x5C, fill_size);
}
status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg);
if (status != PSA_SUCCESS) {
return status;
}
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, ipad, block_size);
if (status != PSA_SUCCESS) {
return status;
}
esp_hmac_ctx->alg = alg;
return status;
}
psa_status_t esp_hmac_update(esp_hmac_operation_t *esp_hmac_ctx, const uint8_t *data, size_t data_length)
{
return esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, data, data_length);
}
psa_status_t esp_hmac_finish(
esp_hmac_operation_t *esp_hmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg);
uint8_t tmp[PSA_HASH_MAX_SIZE];
size_t hash_size = 0;
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size);
if (status != PSA_SUCCESS) {
return status;
}
/* From here on, tmp needs to be wiped. */
status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, esp_hmac_ctx->opad, block_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, tmp, hash_size);
if (status != PSA_SUCCESS) {
goto exit;
}
status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, 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);
return status;
}
psa_status_t esp_hmac_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_hmac_operation_t esp_hmac_ctx = {0};
status = esp_hmac_setup(&esp_hmac_ctx,
attributes, key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (input_length > 0) {
status = esp_hmac_update(&esp_hmac_ctx, input, input_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
size_t actual_mac_length = 0;
status = esp_hmac_finish(&esp_hmac_ctx, mac, mac_size, &actual_mac_length);
if (status == PSA_SUCCESS) {
*mac_length = actual_mac_length;
}
exit:
esp_hmac_abort(&esp_hmac_ctx);
return status;
}
psa_status_t esp_hmac_verify_finish(
esp_hmac_operation_t *esp_hmac_ctx,
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 (esp_hmac_ctx == 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_hmac_finish(esp_hmac_ctx, actual_mac, sizeof(actual_mac), &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;
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -30,29 +30,6 @@ psa_status_t esp_aes_cipher_encrypt(
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,
@@ -73,12 +50,12 @@ psa_status_t esp_aes_cipher_encrypt_setup(
psa_algorithm_t alg);
psa_status_t esp_aes_cipher_set_iv(
esp_aes_operation_t *operation,
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *iv,
size_t iv_length);
psa_status_t esp_aes_cipher_update(
esp_aes_operation_t *operation,
esp_aes_operation_t *esp_aes_driver_ctx,
const uint8_t *input,
size_t input_length,
uint8_t *output,
@@ -86,13 +63,13 @@ psa_status_t esp_aes_cipher_update(
size_t *output_length);
psa_status_t esp_aes_cipher_finish(
esp_aes_operation_t *operation,
esp_aes_operation_t *esp_aes_driver_ctx,
uint8_t *output,
size_t output_size,
size_t *output_length);
psa_status_t esp_aes_cipher_abort(
esp_aes_operation_t *operation);
esp_aes_operation_t *esp_aes_driver_ctx);
#endif /* ESP_AES_DRIVER_ENABLED */
#ifdef __cplusplus
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,46 +9,43 @@
extern "C" {
#endif
#if defined(ESP_AES_DRIVER_ENABLED)
#if defined(ESP_CMAC_DRIVER_ENABLED)
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_cmac_contexts.h"
psa_status_t esp_cmac_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_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_abort(esp_cmac_operation_t *esp_cmac_ctx);
psa_status_t esp_cmac_mac_abort(esp_cmac_operation_t *operation);
psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_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_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_update(esp_cmac_operation_t *esp_cmac_ctx,
const uint8_t *data,
size_t data_length);
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_finish(esp_cmac_operation_t *esp_cmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_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_verify_finish(esp_cmac_operation_t *esp_cmac_ctx,
const uint8_t *mac,
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 */
#endif /* ESP_CMAC_DRIVER_ENABLED */
#ifdef __cplusplus
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,21 +10,12 @@
extern "C" {
#endif
#if defined(ESP_AES_DRIVER_ENABLED) || defined(PSA_CRYPTO_DRIVER_TEST)
#if defined(ESP_CMAC_DRIVER_ENABLED)
#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 */
#include "psa_crypto_driver_esp_aes_contexts.h"
#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
#define PSA_CMAC_MAX_BLOCK_SIZE PSA_AES_BLOCK_SIZE
typedef struct {
/** The CMAC key identifier for cipher operations */
@@ -42,16 +33,12 @@ typedef struct {
uint8_t cipher_block_length;
struct psa_cipher_operation_s cipher_ctx;
esp_aes_operation_t esp_aes_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 */
#endif /* ESP_CMAC_DRIVER_ENABLED */
#ifdef __cplusplus
}
@@ -0,0 +1,52 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if defined(ESP_SHA_DRIVER_ENABLED)
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_hmac_contexts.h"
psa_status_t esp_hmac_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_hmac_abort(esp_hmac_operation_t *esp_hmac_ctx);
psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_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_hmac_update(esp_hmac_operation_t *esp_hmac_ctx,
const uint8_t *data,
size_t data_length);
psa_status_t esp_hmac_finish(esp_hmac_operation_t *esp_hmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t esp_hmac_verify_finish(esp_hmac_operation_t *esp_hmac_ctx,
const uint8_t *mac,
size_t mac_length);
#endif /* ESP_SHA_DRIVER_ENABLED */
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#if defined(ESP_SHA_DRIVER_ENABLED)
#include "psa_crypto_driver_esp_sha_contexts.h"
#include "psa_crypto_driver_esp_sha.h"
typedef struct {
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
psa_algorithm_t alg;
esp_sha_hash_operation_t esp_sha_ctx;
} esp_hmac_operation_t;
#endif /* ESP_SHA_DRIVER_ENABLED */
#ifdef __cplusplus
}
#endif
@@ -8,7 +8,9 @@
#include "psa/crypto.h"
#include "unity.h"
#include "esp_log.h"
#include "sdkconfig.h"
#if CONFIG_MBEDTLS_ARIA_C
/*
ARIA-256-ECB Encrypt - RFC 5794 test vector
Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
@@ -90,3 +92,4 @@ TEST_CASE("PSA ARIA-256-ECB encrypt test vector", "[psa][psa_cipher][aria]")
psa_destroy_key(dec_key_id);
}
#endif /* CONFIG_MBEDTLS_ARIA_C */
@@ -85,10 +85,9 @@ TEST_CASE("PSA CMAC AES-128 test", "[psa_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
@@ -11,6 +11,9 @@
#include "psa/crypto.h"
#include "unity.h"
#include "sdkconfig.h"
#if CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER
static const uint8_t key_256[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -206,3 +209,4 @@ TEST_CASE("PSA ARIA-GCM one-shot", "[psa-gcm]")
/* Destroy the key */
psa_destroy_key(key_id);
}
#endif /* CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER */
@@ -61,7 +61,7 @@
#error "SHA256 is disabled in mbedtls config"
#endif
#if !defined(MBEDTLS_AES_C)
#if (!defined(MBEDTLS_AES_C) && !defined(PSA_WANT_KEY_TYPE_AES))
#error "AES support is disabled in mbedtls config"
#endif
-4
View File
@@ -464,11 +464,7 @@ components/log/host_test/log_test/main/log_test.cpp
components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py
components/mbedtls/port/aes/esp_aes_xts.c
components/mbedtls/port/include/aes/esp_aes.h
components/mbedtls/port/include/aes_alt.h
components/mbedtls/port/include/bignum_impl.h
components/mbedtls/port/include/sha1_alt.h
components/mbedtls/port/include/sha256_alt.h
components/mbedtls/port/include/sha512_alt.h
components/mbedtls/port/sha/parallel_engine/sha.c
components/protocomm/include/transports/protocomm_console.h
components/protocomm/include/transports/protocomm_httpd.h