feat(mbedtls): Introduce ESP-HMAC PSA opaque driver

This commit is contained in:
harshal.patil
2026-01-31 00:45:11 +05:30
parent 53072bfa9d
commit ae459b5204
15 changed files with 729 additions and 141 deletions
+10 -1
View File
@@ -353,12 +353,13 @@ endif()
if(CONFIG_SOC_SHA_SUPPORTED)
if(CONFIG_MBEDTLS_HARDWARE_SHA)
target_compile_definitions(tfpsacrypto PRIVATE ESP_SHA_DRIVER_ENABLED)
target_compile_definitions(tfpsacrypto PRIVATE ESP_HMAC_TRANSPARENT_DRIVER_ENABLED)
target_sources(tfpsacrypto PRIVATE
"${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/psa_driver/esp_mac/psa_crypto_driver_esp_hmac.c"
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c"
)
endif()
target_sources(tfpsacrypto PRIVATE
@@ -374,6 +375,14 @@ if(CONFIG_MBEDTLS_ROM_MD5)
)
endif()
if(CONFIG_SOC_HMAC_SUPPORTED)
target_compile_definitions(tfpsacrypto PRIVATE ESP_HMAC_OPAQUE_DRIVER_ENABLED)
target_sources(tfpsacrypto PRIVATE
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_opaque.c"
)
target_link_libraries(tfpsacrypto PRIVATE idf::efuse)
endif()
if(CONFIG_SOC_DIG_SIGN_SUPPORTED)
target_sources(tfpsacrypto PRIVATE
"${COMPONENT_DIR}/port/esp_ds/esp_rsa_sign_alt.c"
@@ -97,6 +97,7 @@ endif()
# SHA implementation
if(CONFIG_SOC_SHA_SUPPORTED)
target_compile_definitions(tfpsacrypto PRIVATE ESP_SHA_DRIVER_ENABLED)
target_compile_definitions(tfpsacrypto PRIVATE ESP_HMAC_TRANSPARENT_DRIVER_ENABLED)
target_sources(tfpsacrypto PRIVATE
"${COMPONENT_DIR}/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c"
"${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha1.c"
@@ -104,7 +105,7 @@ if(CONFIG_SOC_SHA_SUPPORTED)
"${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/psa_driver/esp_mac/psa_crypto_driver_esp_hmac.c"
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac_transparent.c"
)
endif()
@@ -194,6 +194,8 @@
#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
#define MBEDTLS_PSA_ACCEL_ALG_SHA_224
#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
#define MBEDTLS_PSA_ACCEL_ALG_HMAC
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC
#if SOC_SHA_SUPPORT_SHA512
#define MBEDTLS_PSA_ACCEL_ALG_SHA_384
#define MBEDTLS_PSA_ACCEL_ALG_SHA_512
@@ -0,0 +1,224 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_hmac_opaque.h"
#include "esp_efuse.h"
#include "esp_efuse_chip.h"
#include "hal/hmac_types.h"
#include "esp_hmac.h"
static bool validate_hmac_opaque_key_attributes(const esp_hmac_opaque_key_t *opaque_key)
{
// efuse_block is uint8_t, so it's always >= 0 (EFUSE_BLK0)
if (opaque_key->efuse_block < EFUSE_BLK_MAX && esp_efuse_get_key_purpose(opaque_key->efuse_block) == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
return true;
}
return false;
}
psa_status_t esp_hmac_import_key_opaque(
const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits)
{
if (!attributes || !data || !key_buffer || !key_buffer_length || !bits) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (key_buffer_size < sizeof(esp_hmac_opaque_key_t) || data_length < sizeof(esp_hmac_opaque_key_t)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
const esp_hmac_opaque_key_t *opaque_key = (const esp_hmac_opaque_key_t *) data;
bool valid = validate_hmac_opaque_key_attributes(opaque_key);
if (!valid) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memcpy(key_buffer, opaque_key, sizeof(esp_hmac_opaque_key_t));
*key_buffer_length = sizeof(esp_hmac_opaque_key_t);
*bits = psa_get_key_bits(attributes);
return PSA_SUCCESS;
}
psa_status_t esp_hmac_abort_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx)
{
if (!esp_hmac_ctx) {
mbedtls_platform_zeroize(esp_hmac_ctx, sizeof(esp_hmac_opaque_operation_t));
}
return PSA_SUCCESS;
}
psa_status_t esp_hmac_setup_opaque(
esp_hmac_opaque_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)
{
if (!esp_hmac_ctx || !attributes || !key_buffer || !key_buffer_size || !alg) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (key_buffer_size < sizeof(esp_hmac_opaque_key_t)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (!PSA_ALG_IS_HMAC(alg)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(alg);
if (hash_alg != PSA_ALG_SHA_256) {
return PSA_ERROR_NOT_SUPPORTED;
}
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_opaque_operation_t));
const esp_hmac_opaque_key_t *opaque_key = (const esp_hmac_opaque_key_t *) key_buffer;
if (!validate_hmac_opaque_key_attributes(opaque_key)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
esp_hmac_ctx->opaque_key = opaque_key;
return PSA_SUCCESS;
}
static hmac_key_id_t translate_efuse_block_to_hmac_key_id(uint8_t efuse_block)
{
return (hmac_key_id_t) (efuse_block - EFUSE_BLK_KEY0);
}
psa_status_t esp_hmac_update_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx, const uint8_t *data, size_t data_length)
{
if (!esp_hmac_ctx || !data || data_length == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
hmac_key_id_t hmac_key_id = HMAC_KEY_MAX;
#if SOC_KEY_MANAGER_HMAC_KEY_DEPLOY
if (esp_hmac_ctx->opaque_key->use_km_key) {
hmac_key_id = HMAC_KEY_KM;
} else
#endif /* SOC_KEY_MANAGER_HMAC_KEY_DEPLOY */
{
hmac_key_id = translate_efuse_block_to_hmac_key_id(esp_hmac_ctx->opaque_key->efuse_block);
}
esp_err_t hmac_ret = esp_hmac_calculate(hmac_key_id, data, data_length, esp_hmac_ctx->hmac);
if (hmac_ret == ESP_ERR_INVALID_ARG) {
return PSA_ERROR_INVALID_ARGUMENT;
} else if (hmac_ret == ESP_FAIL) {
return PSA_ERROR_HARDWARE_FAILURE;
} else if (hmac_ret == ESP_OK) {
return PSA_SUCCESS;
}
return PSA_ERROR_CORRUPTION_DETECTED;
}
psa_status_t esp_hmac_finish_opaque(
esp_hmac_opaque_operation_t *esp_hmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
{
if (!esp_hmac_ctx || !mac || !mac_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (mac_size < ESP_HMAC_RESULT_SIZE) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
memcpy(mac, esp_hmac_ctx->hmac, ESP_HMAC_RESULT_SIZE);
*mac_length = ESP_HMAC_RESULT_SIZE;
return PSA_SUCCESS;
}
psa_status_t esp_hmac_compute_opaque(
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_opaque_operation_t esp_hmac_ctx = {0};
status = esp_hmac_setup_opaque(&esp_hmac_ctx, attributes, key_buffer, key_buffer_size, alg);
if (status != PSA_SUCCESS) {
return status;
}
status = esp_hmac_update_opaque(&esp_hmac_ctx, input, input_length);
if (status != PSA_SUCCESS) {
return status;
}
status = esp_hmac_finish_opaque(&esp_hmac_ctx, mac, mac_size, mac_length);
if (status != PSA_SUCCESS) {
return status;
}
return PSA_SUCCESS;
}
psa_status_t esp_hmac_verify_finish_opaque(
esp_hmac_opaque_operation_t *esp_hmac_ctx,
const uint8_t *mac,
size_t mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
uint8_t actual_mac[ESP_HMAC_RESULT_SIZE];
size_t actual_mac_length = 0;
status = esp_hmac_finish_opaque(esp_hmac_ctx, actual_mac, sizeof(actual_mac), &actual_mac_length);
if (status != PSA_SUCCESS) {
return status;
}
if (memcmp(mac, actual_mac, mac_length) != 0) {
return PSA_ERROR_INVALID_SIGNATURE;
}
return PSA_SUCCESS;
}
/**
* @brief Get the size of the ESP HMAC opaque key
*
* @param key_type Key type
* @param key_bits Key bits
* @return size_t Size of the ESP HMAC opaque key
*/
size_t esp_hmac_opaque_size_function(
psa_key_type_t key_type,
size_t key_bits)
{
(void)key_type;
(void)key_bits;
// Opaque keys always use the same size structure
return sizeof(esp_hmac_opaque_key_t);
}
@@ -6,11 +6,10 @@
#include <string.h>
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_hmac.h"
#include "psa_crypto_driver_esp_hmac_contexts.h"
#include "psa_crypto_driver_esp_hmac_transparent.h"
#include "psa_crypto_driver_esp_sha.h"
psa_status_t esp_hmac_abort(esp_hmac_operation_t *esp_hmac_ctx)
psa_status_t esp_hmac_abort_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
@@ -19,11 +18,11 @@ psa_status_t esp_hmac_abort(esp_hmac_operation_t *esp_hmac_ctx)
return status;
}
mbedtls_platform_zeroize(esp_hmac_ctx, sizeof(esp_hmac_operation_t));
mbedtls_platform_zeroize(esp_hmac_ctx, sizeof(esp_hmac_transparent_operation_t));
return status;
}
psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
@@ -40,7 +39,12 @@ psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
return PSA_ERROR_INVALID_ARGUMENT;
}
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_operation_t));
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_transparent_operation_t));
status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg);
if (status != PSA_SUCCESS) {
goto error;
}
/* Sanity checks on block_size, to guarantee that there won't be a buffer
* overflow below. This should never trigger if the hash algorithm
@@ -48,19 +52,21 @@ psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
/* 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;
status = PSA_ERROR_NOT_SUPPORTED;
goto error;
}
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;
goto error;
}
/* 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;
status = PSA_ERROR_CORRUPTION_DETECTED;
goto error;
}
}
/* A 0-length key is not commonly used in HMAC when used as a MAC,
@@ -70,7 +76,8 @@ psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
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;
status = PSA_ERROR_INVALID_ARGUMENT;
goto error;
}
memcpy(ipad, key_buffer, key_buffer_size);
}
@@ -110,28 +117,29 @@ psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
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;
goto error;
}
esp_hmac_ctx->alg = alg;
return status;
error:
esp_hmac_abort_transparent(esp_hmac_ctx);
return status;
}
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_update_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx, const uint8_t *data, size_t data_length)
{
if (esp_hmac_ctx == NULL || data == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
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,
psa_status_t esp_hmac_finish_transparent(
esp_hmac_transparent_operation_t *esp_hmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_length)
@@ -143,6 +151,10 @@ psa_status_t esp_hmac_finish(
size_t hash_size = 0;
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
if (esp_hmac_ctx == NULL || mac == NULL || mac_length == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size);
if (status != PSA_SUCCESS) {
return status;
@@ -169,16 +181,19 @@ psa_status_t esp_hmac_finish(
goto exit;
}
memcpy(mac, tmp, mac_size);
*mac_length = mac_size;
if (mac_size < hash_size) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
memcpy(mac, tmp, hash_size);
*mac_length = hash_size;
exit:
mbedtls_platform_zeroize(tmp, hash_size);
return status;
}
psa_status_t esp_hmac_compute(
psa_status_t esp_hmac_compute_transparent(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
@@ -190,9 +205,9 @@ psa_status_t esp_hmac_compute(
size_t *mac_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
esp_hmac_operation_t esp_hmac_ctx = {0};
esp_hmac_transparent_operation_t esp_hmac_ctx = {0};
status = esp_hmac_setup(&esp_hmac_ctx,
status = esp_hmac_setup_transparent(&esp_hmac_ctx,
attributes, key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
@@ -200,27 +215,27 @@ psa_status_t esp_hmac_compute(
}
if (input_length > 0) {
status = esp_hmac_update(&esp_hmac_ctx, input, input_length);
status = esp_hmac_update_transparent(&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);
status = esp_hmac_finish_transparent(&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);
esp_hmac_abort_transparent(&esp_hmac_ctx);
return status;
}
psa_status_t esp_hmac_verify_finish(
esp_hmac_operation_t *esp_hmac_ctx,
psa_status_t esp_hmac_verify_finish_transparent(
esp_hmac_transparent_operation_t *esp_hmac_ctx,
const uint8_t *mac,
size_t mac_length)
{
@@ -237,14 +252,13 @@ psa_status_t esp_hmac_verify_finish(
size_t actual_mac_length = 0;
status = esp_hmac_finish(esp_hmac_ctx, actual_mac, sizeof(actual_mac), &actual_mac_length);
status = esp_hmac_finish_transparent(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;
if (memcmp(actual_mac, mac, mac_length) != 0) {
status = PSA_ERROR_INVALID_SIGNATURE;
}
}
mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
return status;
}
@@ -1,52 +0,0 @@
/*
* 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,104 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#if defined(ESP_HMAC_OPAQUE_DRIVER_ENABLED)
#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_hmac_opaque_contexts.h"
/**
* @brief ESP HMAC opaque PSA driver location
*
* Vendor-specific location for ESP hardware HMAC keys.
* Bits 8-31 are location, using vendor flag (0x800000) + ESP vendor ID.
*/
#define PSA_KEY_LOCATION_ESP_HMAC ((psa_key_location_t) 0x800002)
/**
* @brief Construct a lifetime for ESP HMAC keys with default persistence
*/
#define PSA_KEY_LIFETIME_ESP_HMAC \
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \
PSA_KEY_PERSISTENCE_DEFAULT, \
PSA_KEY_LOCATION_ESP_HMAC)
/**
* @brief Construct a volatile lifetime for ESP HMAC keys
*/
#define PSA_KEY_LIFETIME_ESP_HMAC_VOLATILE \
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \
PSA_KEY_PERSISTENCE_VOLATILE, \
PSA_KEY_LOCATION_ESP_HMAC)
/**
* @brief Import an ESP HMAC key reference (not actual key material)
*
* This function imports an opaque reference to a key stored in eFuse or Key Manager.
* The import data should contain the esp_hmac_opaque_key_t structure.
*
* @param attributes Key attributes
* @param data Import data (esp_hmac_opaque_key_t)
* @param data_length Length of import data
* @param key_buffer Output buffer for opaque key
* @param key_buffer_size Size of output buffer
* @param key_buffer_length Actual key buffer length
* @param bits Key size in bits
* @return psa_status_t
*/
psa_status_t esp_hmac_import_key_opaque(const psa_key_attributes_t *attributes,
const uint8_t *data,
size_t data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length,
size_t *bits);
size_t esp_hmac_opaque_size_function(psa_key_type_t key_type, size_t key_bits);
psa_status_t esp_hmac_compute_opaque(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_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx);
psa_status_t esp_hmac_setup_opaque(esp_hmac_opaque_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_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx,
const uint8_t *data,
size_t data_length);
psa_status_t esp_hmac_finish_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t esp_hmac_verify_finish_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx,
const uint8_t *mac,
size_t mac_length);
#ifdef __cplusplus
}
#endif
#endif /* ESP_HMAC_OPAQUE_DRIVER_ENABLED */
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "soc/soc_caps.h"
#include "psa/crypto_driver_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Size of HMAC result in bytes (the opaque driver only supports SHA-256 based HMAC)
*/
#define ESP_HMAC_RESULT_SIZE PSA_HASH_LENGTH(PSA_ALG_HMAC(PSA_ALG_SHA_256))
/**
* @brief Structure to store opaque HMAC key.
*/
typedef struct {
bool use_km_key; /**< Use key deployed in the key manager */
uint8_t efuse_block; /**< eFuse block id for HMAC key */
} esp_hmac_opaque_key_t;
/**
* @brief Structure to store opaque HMAC operation context.
*/
typedef struct {
const esp_hmac_opaque_key_t *opaque_key; /**< Pointer to the opaque key structure */
uint8_t hmac[ESP_HMAC_RESULT_SIZE]; /**< Buffer to store the HMAC result */
} esp_hmac_opaque_operation_t;
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#if defined(ESP_HMAC_TRANSPARENT_DRIVER_ENABLED)
#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
#endif
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_hmac_transparent_contexts.h"
#ifdef __cplusplus
extern "C" {
#endif
psa_status_t esp_hmac_compute_transparent(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_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx);
psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_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_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx,
const uint8_t *data,
size_t data_length);
psa_status_t esp_hmac_finish_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx,
uint8_t *mac,
size_t mac_size,
size_t *mac_length);
psa_status_t esp_hmac_verify_finish_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx,
const uint8_t *mac,
size_t mac_length);
#ifdef __cplusplus
}
#endif
#endif /* ESP_HMAC_TRANSPARENT_DRIVER_ENABLED */
@@ -6,22 +6,22 @@
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "psa/crypto_driver_common.h"
#include "psa_crypto_driver_esp_sha_contexts.h"
#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"
#if defined(ESP_HMAC_TRANSPARENT_DRIVER_ENABLED)
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 */
} esp_hmac_transparent_operation_t;
#endif /* ESP_HMAC_TRANSPARENT_DRIVER_ENABLED */
#ifdef __cplusplus
}
+154 -30
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -8,9 +8,13 @@
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_128[] = {
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
#include "esp_log.h"
static const uint8_t key_256[] = {
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, 0x20,
};
static const uint8_t test_data[] = {
@@ -20,44 +24,164 @@ static const uint8_t test_data[] = {
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
};
static const uint8_t expected_hmac_128[] = {
0x00, 0x7a, 0x5a, 0xd6, 0x54, 0x96, 0x5b, 0xcd,
0x30, 0xc1, 0x60, 0x62, 0xec, 0xac, 0x75, 0xfb,
0x87, 0x71, 0x0e, 0x13
static const uint8_t expected_hmac_sha1[] = {
0xb7, 0xb4, 0x9b, 0xc1, 0x8a, 0x88, 0x43, 0xa2,
0xbb, 0x34, 0xdf, 0x27, 0xfe, 0x6c, 0x9b, 0x1b,
0xbf, 0x4b, 0x57, 0xb5,
};
static const uint8_t expected_hmac_sha256[] = {
0xc4, 0x45, 0xa1, 0xfc, 0x3f, 0x7e, 0x1b, 0xfc,
0x4a, 0x33, 0x19, 0xfc, 0x68, 0xa5, 0x8e, 0xf1,
0x81, 0x0f, 0x99, 0x70, 0x32, 0x06, 0x2c, 0xcb,
0x50, 0xd7, 0x15, 0x78, 0x82, 0x10, 0xbe, 0xc6,
};
// Helper function to set up key attributes for HMAC
static void setup_hmac_key_attributes(psa_key_attributes_t *attributes,
psa_algorithm_t alg,
psa_key_lifetime_t lifetime)
{
psa_set_key_usage_flags(attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(attributes, alg);
psa_set_key_type(attributes, PSA_KEY_TYPE_HMAC);
psa_set_key_bits(attributes, 256);
psa_set_key_lifetime(attributes, lifetime);
}
// Helper function to perform HMAC compute and verify (single-shot)
static void test_hmac_compute_and_verify(psa_key_id_t key_id,
psa_algorithm_t alg,
const uint8_t *data,
size_t data_len,
const uint8_t *expected_mac,
size_t expected_mac_len)
{
psa_status_t status;
size_t hmac_length = PSA_HASH_LENGTH(alg);
uint8_t *hmac = malloc(hmac_length);
TEST_ASSERT_NOT_NULL(hmac);
size_t mac_length = 0;
status = psa_mac_compute(key_id, alg, data, data_len,
hmac, hmac_length, &mac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify(key_id, alg, data, data_len,
expected_mac, expected_mac_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
free(hmac);
}
// Helper function to perform HMAC multipart sign operation
static void test_hmac_multipart_sign(psa_mac_operation_t *op,
psa_key_id_t key_id,
psa_algorithm_t alg,
const uint8_t *data,
size_t data_len,
uint8_t *mac,
size_t mac_size,
size_t *mac_len)
{
psa_status_t status;
status = psa_mac_sign_setup(op, key_id, alg);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_update(op, data, data_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_sign_finish(op, mac, mac_size, mac_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
// Helper function to perform HMAC multipart verify operation
static void test_hmac_multipart_verify(psa_mac_operation_t *op,
psa_key_id_t key_id,
psa_algorithm_t alg,
const uint8_t *data,
size_t data_len,
const uint8_t *mac,
size_t mac_len)
{
psa_status_t status;
status = psa_mac_verify_setup(op, key_id, alg);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_update(op, data, data_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify_finish(op, mac, mac_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
TEST_CASE("PSA HMAC SHA-1 test", "[psa_hmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_1);
// Initialize PSA Crypto
status = PSA_SUCCESS;
// TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
setup_hmac_key_attributes(&attributes, alg, PSA_KEY_LIFETIME_VOLATILE);
// 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_HMAC(PSA_ALG_SHA_1));
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
psa_set_key_bits(&attributes, 128);
uint8_t *hmac = malloc(PSA_HASH_LENGTH(PSA_ALG_SHA_1));
TEST_ASSERT_NOT_NULL(hmac);
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
size_t mac_length = 0;
status = psa_mac_compute(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_1),
test_data, sizeof(test_data),
hmac, PSA_HASH_LENGTH(PSA_ALG_SHA_1), &mac_length);
status = psa_import_key(&attributes, key_256, sizeof(key_256), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_1),
test_data, sizeof(test_data),
expected_hmac_128, sizeof(expected_hmac_128));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
test_hmac_compute_and_verify(key_id, alg, test_data, sizeof(test_data),
expected_hmac_sha1, sizeof(expected_hmac_sha1));
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
}
TEST_CASE("PSA HMAC SHA-256 test", "[psa_hmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
setup_hmac_key_attributes(&attributes, alg, PSA_KEY_LIFETIME_VOLATILE);
status = psa_import_key(&attributes, key_256, sizeof(key_256), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
test_hmac_compute_and_verify(key_id, alg, test_data, sizeof(test_data),
expected_hmac_sha256, sizeof(expected_hmac_sha256));
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
}
TEST_CASE("PSA HMAC SHA-256 multipart test", "[psa_hmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
size_t hmac_length = PSA_HASH_LENGTH(alg);
size_t mac_len = 0;
setup_hmac_key_attributes(&attributes, alg, PSA_KEY_LIFETIME_VOLATILE);
uint8_t *hmac = malloc(hmac_length);
TEST_ASSERT_NOT_NULL(hmac);
status = psa_import_key(&attributes, key_256, sizeof(key_256), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
psa_mac_operation_t op = PSA_MAC_OPERATION_INIT;
test_hmac_multipart_sign(&op, key_id, alg, test_data, sizeof(test_data),
hmac, hmac_length, &mac_len);
test_hmac_multipart_verify(&op, key_id, alg, test_data, sizeof(test_data),
expected_hmac_sha256, sizeof(expected_hmac_sha256));
psa_reset_key_attributes(&attributes);
psa_mac_abort(&op);
psa_destroy_key(key_id);
free(hmac);
}