Merge branch 'fix/align_sw_psa_drivers_and_hw_esp_psa_drivers_v6.1' into 'release/v6.1'

Align s/w and h/w PSA drivers (v6.1)

See merge request espressif/esp-idf!49704
This commit is contained in:
Mahavir Jain
2026-07-02 15:22:15 +05:30
25 changed files with 1157 additions and 596 deletions

View File

@@ -34,12 +34,18 @@ static psa_status_t esp_aes_cipher_setup(
goto exit;
}
/* Cross-check the attributes against the buffer size; per-target HW
* key-size support is enforced by esp_aes_setkey below. */
if (psa_get_key_bits(attributes) != key_buffer_size * 8) {
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;
@@ -56,17 +62,17 @@ static psa_status_t esp_aes_cipher_setup(
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));
status = mbedtls_to_psa_error(esp_aes_setkey(ctx, key_buffer, key_buffer_size * 8));
if (status != PSA_SUCCESS) {
esp_aes_cipher_abort(esp_aes_driver_ctx);
return status;
}
exit:
return status;
}
@@ -98,6 +104,14 @@ psa_status_t esp_aes_cipher_set_iv(
const uint8_t *iv,
size_t iv_length)
{
if (esp_aes_driver_ctx == NULL || esp_aes_driver_ctx->esp_aes_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
if (iv == NULL && iv_length > 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (iv_length != PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, esp_aes_driver_ctx->aes_alg)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -268,6 +282,19 @@ psa_status_t esp_aes_cipher_update(
{
int ret = -1;
size_t expected_output_size;
if (output_length == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if ((input == NULL && input_length > 0) ||
(output == NULL && output_size > 0)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_aes_driver_ctx == NULL || esp_aes_driver_ctx->esp_aes_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
*output_length = 0;
if (!PSA_ALG_IS_STREAM_CIPHER(esp_aes_driver_ctx->aes_alg)) {
@@ -378,34 +405,39 @@ static void add_pkcs_padding(unsigned char *output, size_t output_len,
}
}
static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
/* Reports PKCS7 padding validity through *invalid_padding (a constant-time
* condition) instead of the return value, so esp_aes_cipher_finish can fold it
* into the result branchlessly and avoid a padding-oracle branch */
static void get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len,
mbedtls_ct_condition_t *invalid_padding)
{
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));
/* Clamp padding_len to [0, input_len] before the math so out-of-range
* values do not produce a size_t underflow. The bad flag already records
* whether the original value was invalid. */
size_t safe_padding_len = mbedtls_ct_size_if(mbedtls_ct_uint_gt((size_t)padding_len, input_len),
input_len, (size_t)padding_len);
pad_idx = input_len - safe_padding_len;
/* 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);
/* Gate *data_len on the bad flag so it does not leak padding validity. */
*data_len = mbedtls_ct_if(bad, 0, pad_idx);
*invalid_padding = bad;
}
psa_status_t esp_aes_cipher_finish(
@@ -415,9 +447,20 @@ psa_status_t esp_aes_cipher_finish(
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];
uint8_t temp_output_buffer[ESP_MBEDTLS_AES_MAX_BLOCK_LENGTH] = { 0 };
mbedtls_ct_condition_t invalid_padding = mbedtls_ct_bool(0);
if (esp_aes_driver_ctx == NULL || esp_aes_driver_ctx->esp_aes_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
*output_length = 0;
if (output_size > sizeof(temp_output_buffer)) {
output_size = sizeof(temp_output_buffer);
}
if (esp_aes_driver_ctx->unprocessed_len != 0) {
if (esp_aes_driver_ctx->aes_alg == PSA_ALG_ECB_NO_PADDING ||
@@ -427,7 +470,6 @@ psa_status_t esp_aes_cipher_finish(
}
}
*output_length = 0;
switch (esp_aes_driver_ctx->aes_alg) {
case PSA_ALG_ECB_NO_PADDING:
case PSA_ALG_CTR:
@@ -443,15 +485,10 @@ psa_status_t esp_aes_cipher_finish(
* Otherwise, we pad the partial block. */
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);
/* PKCS7 decrypt requires at least one full ciphertext block
* (the trailing block always contains padding). */
status = mbedtls_to_psa_error(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED);
goto exit;
}
ret = esp_aes_crypt_cbc(ctx, esp_aes_driver_ctx->mode,
esp_aes_driver_ctx->block_length,
@@ -459,14 +496,13 @@ psa_status_t esp_aes_cipher_finish(
esp_aes_driver_ctx->unprocessed_data,
temp_output_buffer);
if (ret != 0) {
return mbedtls_to_psa_error(ret);
status = mbedtls_to_psa_error(ret);
goto exit;
}
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);
}
get_pkcs_padding(temp_output_buffer, esp_aes_driver_ctx->block_length,
output_length, &invalid_padding);
} else {
*output_length = esp_aes_driver_ctx->block_length;
}
@@ -481,9 +517,11 @@ psa_status_t esp_aes_cipher_finish(
}
} 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;
status = PSA_SUCCESS;
goto exit;
}
return mbedtls_to_psa_error(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED);
status = mbedtls_to_psa_error(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED);
goto exit;
}
ret = esp_aes_crypt_cbc(ctx, esp_aes_driver_ctx->mode,
@@ -492,7 +530,8 @@ psa_status_t esp_aes_cipher_finish(
esp_aes_driver_ctx->unprocessed_data,
temp_output_buffer);
if (ret != 0) {
return mbedtls_to_psa_error(ret);
status = mbedtls_to_psa_error(ret);
goto exit;
}
*output_length = esp_aes_driver_ctx->block_length;
@@ -503,14 +542,17 @@ psa_status_t esp_aes_cipher_finish(
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;
if (output_size != 0) {
memcpy(output, temp_output_buffer, output_size);
}
status = mbedtls_ct_error_if_else_0(invalid_padding,
PSA_ERROR_INVALID_PADDING);
mbedtls_ct_condition_t buffer_too_small = mbedtls_ct_uint_lt(output_size, *output_length);
status = mbedtls_ct_error_if(buffer_too_small,
PSA_ERROR_BUFFER_TOO_SMALL,
status);
exit:
mbedtls_platform_zeroize(temp_output_buffer, sizeof(temp_output_buffer));
return status;
@@ -519,12 +561,15 @@ exit:
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) {
if (esp_aes_driver_ctx == NULL) {
return PSA_SUCCESS;
}
esp_aes_free(ctx);
free(ctx);
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
if (ctx != NULL) {
esp_aes_free(ctx);
free(ctx);
}
mbedtls_platform_zeroize(esp_aes_driver_ctx, sizeof(*esp_aes_driver_ctx));
return PSA_SUCCESS;
}
@@ -631,15 +676,15 @@ psa_status_t esp_aes_cipher_decrypt(
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:
esp_aes_cipher_abort(&esp_aes_driver_ctx);
{
psa_status_t abort_status = esp_aes_cipher_abort(&esp_aes_driver_ctx);
if (abort_status != PSA_SUCCESS) {
status = abort_status;
}
}
return status;
}

View File

@@ -6,6 +6,7 @@
#include <string.h>
#include "esp_log.h"
#include "psa_crypto_core.h"
#include "mbedtls/platform_util.h"
#include "aes/esp_aes_gcm.h"
#include "psa_crypto_driver_esp_aes_gcm.h"
#include "../include/psa_crypto_driver_esp_aes_contexts.h"
@@ -31,8 +32,16 @@ static psa_status_t esp_crypto_aes_gcm_setup(
goto exit;
}
/* Get the tag length from the algorithm */
/* Get the tag length from the algorithm and reject GCM-disallowed values
* (GCM permits only {4, 8, 12, 13, 14, 15, 16}). */
tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
switch (tag_length) {
case 4: case 8: case 12: case 13: case 14: case 15: case 16:
break;
default:
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
status = PSA_ERROR_NOT_SUPPORTED;
@@ -46,16 +55,14 @@ static psa_status_t esp_crypto_aes_gcm_setup(
}
esp_aes_gcm_init(ctx);
esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx = (void *) ctx;
status = mbedtls_to_psa_error(esp_aes_gcm_setkey(ctx, 2, key_buffer, key_buffer_size * 8));
if (status != PSA_SUCCESS) {
esp_aes_gcm_free(ctx);
free(ctx);
(void)esp_crypto_aes_gcm_abort(esp_aes_gcm_driver_ctx);
goto exit;
}
esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx = (void *) ctx;
esp_aes_gcm_driver_ctx->mode = mode;
esp_aes_gcm_driver_ctx->tag_length = tag_length;
@@ -90,6 +97,9 @@ psa_status_t esp_crypto_aes_gcm_set_nonce(
const uint8_t *nonce,
size_t nonce_length)
{
if (esp_aes_gcm_driver_ctx == NULL || esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
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));
}
@@ -99,6 +109,9 @@ psa_status_t esp_crypto_aes_gcm_update_ad(
const uint8_t *aad,
size_t aad_length)
{
if (esp_aes_gcm_driver_ctx == NULL || esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
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));
}
@@ -114,6 +127,9 @@ psa_status_t esp_crypto_aes_gcm_update(
size_t update_output_length = input_length;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (esp_aes_gcm_driver_ctx == NULL || esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
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) {
@@ -133,6 +149,11 @@ psa_status_t esp_crypto_aes_gcm_finish(
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t finish_output_size = 0;
if (esp_aes_gcm_driver_ctx == NULL || esp_aes_gcm_driver_ctx->esp_aes_gcm_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
size_t requested_tag_length = esp_aes_gcm_driver_ctx->tag_length;
if (tag_size < requested_tag_length) {
@@ -157,17 +178,22 @@ psa_status_t esp_crypto_aes_gcm_finish(
/* Copy only the requested tag length */
memcpy(tag, full_tag, requested_tag_length);
}
mbedtls_platform_zeroize(full_tag, sizeof(full_tag));
return status;
}
psa_status_t esp_crypto_aes_gcm_abort(esp_aes_gcm_operation_t *esp_aes_gcm_driver_ctx)
{
if (esp_aes_gcm_driver_ctx == NULL) {
return PSA_SUCCESS;
}
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);
mbedtls_platform_zeroize(esp_aes_gcm_driver_ctx, sizeof(*esp_aes_gcm_driver_ctx));
return PSA_SUCCESS;
}
@@ -219,6 +245,7 @@ psa_status_t esp_crypto_aes_gcm_encrypt(
memcpy(tag, full_tag, tag_length);
*ciphertext_length = plaintext_length + tag_length;
}
mbedtls_platform_zeroize(full_tag, sizeof(full_tag));
exit:
esp_crypto_aes_gcm_abort(&esp_aes_gcm_driver_ctx);

View File

@@ -17,6 +17,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/bignum.h"
#include "mbedtls/platform_util.h"
#include "esp_assert.h"
#include "esp_fault.h"
#include "esp_crypto_lock.h"
@@ -453,6 +454,14 @@ psa_status_t esp_ecdsa_transparent_verify_hash_start(
return PSA_ERROR_NOT_SUPPORTED;
}
/* HW only implements SECP_R1; reject any other ECC family up front so
* we never derive the curve from key_bits alone. */
psa_key_type_t key_type = psa_get_key_type(attributes);
if (!PSA_KEY_TYPE_IS_ECC(key_type) ||
PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) != PSA_ECC_FAMILY_SECP_R1) {
return PSA_ERROR_NOT_SUPPORTED;
}
size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
esp_ecdsa_curve_t curve = psa_bits_to_ecdsa_curve(key_len);
if (curve == ESP_ECDSA_CURVE_MAX) {
@@ -529,6 +538,17 @@ psa_status_t esp_ecdsa_transparent_verify_hash_start(
change_endianess(public_key_buffer + 1 + key_len, point.y, key_len);
point.len = key_len;
/* Reject the identity (point at infinity, all-zero coords) explicitly —
* esp_ecc_point_verify may not catch it on all peripherals. */
bool qx_zero = true, qy_zero = true;
for (size_t i = 0; i < key_len; i++) {
qx_zero = qx_zero && (point.x[i] == 0);
qy_zero = qy_zero && (point.y[i] == 0);
}
if (qx_zero && qy_zero) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (!esp_ecc_point_verify(&point)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -580,7 +600,7 @@ psa_status_t esp_ecdsa_transparent_verify_hash_complete(esp_ecdsa_transparent_ve
psa_status_t esp_ecdsa_transparent_verify_hash_abort(esp_ecdsa_transparent_verify_hash_operation_t *operation)
{
if (operation) {
memset(operation, 0, sizeof(esp_ecdsa_transparent_verify_hash_operation_t));
mbedtls_platform_zeroize(operation, sizeof(esp_ecdsa_transparent_verify_hash_operation_t));
}
return PSA_SUCCESS;
}
@@ -600,16 +620,12 @@ psa_status_t esp_ecdsa_transparent_verify_hash(
esp_ecdsa_transparent_verify_hash_operation_t operation;
status = esp_ecdsa_transparent_verify_hash_start(&operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length);
if (status != PSA_SUCCESS) {
return status;
if (status == PSA_SUCCESS) {
status = esp_ecdsa_transparent_verify_hash_complete(&operation);
}
status = esp_ecdsa_transparent_verify_hash_complete(&operation);
if (status != PSA_SUCCESS) {
return status;
}
return esp_ecdsa_transparent_verify_hash_abort(&operation);
esp_ecdsa_transparent_verify_hash_abort(&operation);
return status;
}
#endif /* SOC_ECDSA_SUPPORTED */
@@ -710,6 +726,12 @@ static psa_status_t esp_ecdsa_validate_efuse_block(esp_ecdsa_curve_t curve, int
*/
static psa_status_t validate_ecdsa_opaque_key_attributes(const psa_key_attributes_t *attributes, const esp_ecdsa_opaque_key_t *opaque_key)
{
psa_key_type_t key_type = psa_get_key_type(attributes);
if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||
PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) != PSA_ECC_FAMILY_SECP_R1) {
return PSA_ERROR_NOT_SUPPORTED;
}
esp_ecdsa_curve_t expected_curve = psa_bits_to_ecdsa_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
if (expected_curve == ESP_ECDSA_CURVE_MAX || expected_curve != opaque_key->curve) {
@@ -742,6 +764,11 @@ static psa_status_t validate_ecdsa_opaque_key_attributes(const psa_key_attribute
*/
static psa_status_t validate_storage_curve(const psa_key_attributes_t *attributes, esp_ecdsa_curve_t stored_curve)
{
psa_key_type_t key_type = psa_get_key_type(attributes);
if (!PSA_KEY_TYPE_IS_ECC(key_type) ||
PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) != PSA_ECC_FAMILY_SECP_R1) {
return PSA_ERROR_NOT_SUPPORTED;
}
esp_ecdsa_curve_t expected_curve = psa_bits_to_ecdsa_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
if (expected_curve == ESP_ECDSA_CURVE_MAX || expected_curve != stored_curve) {
ESP_LOGE(TAG, "Invalid curve expected");
@@ -1033,6 +1060,12 @@ psa_status_t esp_ecdsa_opaque_sign_hash_complete(
return PSA_ERROR_NOT_SUPPORTED;
}
}
#else
/* Without HW/SW deterministic-ECDSA support, do not silently downgrade
* a deterministic-alg request to randomized. */
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0};
@@ -1069,6 +1102,11 @@ psa_status_t esp_ecdsa_opaque_sign_hash_complete(
ecdsa_curve_t hal_curve = esp_ecdsa_curve_to_hal_curve(curve);
if (hal_curve == (ecdsa_curve_t)-1) {
esp_ecdsa_release_hardware();
#if SOC_KEY_MANAGER_SUPPORTED
if (key_recovery_info) {
esp_key_mgr_deactivate_key(key_recovery_info->key_type);
}
#endif /* SOC_KEY_MANAGER_SUPPORTED */
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -1156,7 +1194,7 @@ psa_status_t esp_ecdsa_opaque_sign_hash_complete(
psa_status_t esp_ecdsa_opaque_sign_hash_abort(esp_ecdsa_opaque_sign_hash_operation_t *operation)
{
if (operation) {
memset(operation, 0, sizeof(esp_ecdsa_opaque_sign_hash_operation_t));
mbedtls_platform_zeroize(operation, sizeof(esp_ecdsa_opaque_sign_hash_operation_t));
}
return PSA_SUCCESS;
}
@@ -1184,12 +1222,9 @@ psa_status_t esp_ecdsa_opaque_sign_hash(
}
status = esp_ecdsa_opaque_sign_hash_complete(&operation, signature, signature_size, signature_length);
if (status != PSA_SUCCESS) {
esp_ecdsa_opaque_sign_hash_abort(&operation);
return status;
}
return esp_ecdsa_opaque_sign_hash_abort(&operation);
esp_ecdsa_opaque_sign_hash_abort(&operation);
return status;
}
psa_status_t esp_ecdsa_opaque_export_public_key(

View File

@@ -6,6 +6,7 @@
#include <string.h>
#include <stdint.h>
#include "mbedtls/platform_util.h"
#include "psa/crypto.h"
#include "psa_crypto_driver_esp_cmac.h"
#include "psa_crypto_driver_esp_cmac_contexts.h"
@@ -66,20 +67,19 @@ static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
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;
if (esp_cmac_ctx == NULL) {
return PSA_SUCCESS;
}
status = esp_aes_cipher_abort(&esp_cmac_ctx->esp_aes_ctx);
if (status != PSA_SUCCESS) {
return status;
if (esp_cmac_ctx->alg == 0) {
return PSA_SUCCESS;
}
(void)psa_destroy_key(esp_cmac_ctx->key_id);
(void)esp_aes_cipher_abort(&esp_cmac_ctx->esp_aes_ctx);
mbedtls_platform_zeroize(esp_cmac_ctx, sizeof(esp_cmac_operation_t));
return status;
return PSA_SUCCESS;
}
psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_ctx,
@@ -89,10 +89,27 @@ psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_ctx,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
if (esp_cmac_ctx == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_cmac_ctx->alg != 0) {
return PSA_ERROR_BAD_STATE;
}
if (PSA_ALG_FULL_LENGTH_MAC(alg) != PSA_ALG_CMAC) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
return PSA_ERROR_NOT_SUPPORTED;
}
memset(esp_cmac_ctx, 0, sizeof(*esp_cmac_ctx));
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
esp_cmac_ctx->alg = alg;
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;
@@ -105,24 +122,21 @@ psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_ctx,
/* 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;
goto error;
}
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;
goto error;
}
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 PSA_SUCCESS;
error:
psa_reset_key_attributes(&key_attributes);
esp_cmac_abort(esp_cmac_ctx);
return status;
}
@@ -140,9 +154,18 @@ psa_status_t esp_cmac_update(esp_cmac_operation_t *esp_cmac_ctx, const uint8_t *
size_t n, j, olen, block_size;
unsigned char *state;
if (esp_cmac_ctx == NULL || data == NULL) {
if (esp_cmac_ctx == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data == NULL && data_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_cmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
if (data_length == 0) {
return PSA_SUCCESS;
}
state = esp_cmac_ctx->state;
block_size = esp_cmac_ctx->cipher_block_length;
@@ -294,12 +317,18 @@ psa_status_t esp_cmac_finish(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_cmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
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);
if ((status = cmac_generate_subkeys(&esp_cmac_ctx->esp_aes_ctx, block_size, K1, K2)) != PSA_SUCCESS) {
goto exit;
}
last_block = esp_cmac_ctx->unprocessed_block;
@@ -324,10 +353,9 @@ psa_status_t esp_cmac_finish(
exit:
mbedtls_platform_zeroize(K1, sizeof(K1));
mbedtls_platform_zeroize(K2, sizeof(K2));
mbedtls_platform_zeroize(M_last, sizeof(M_last));
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);
(void)esp_cmac_abort(esp_cmac_ctx);
return status;
}
@@ -384,7 +412,11 @@ psa_status_t esp_cmac_verify_finish(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (mac_length > sizeof(actual_mac)) {
if (esp_cmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
if (mac_length == 0 || mac_length > sizeof(actual_mac)) {
return PSA_ERROR_INVALID_ARGUMENT;
}

View File

@@ -237,6 +237,10 @@ psa_status_t esp_hmac_setup_opaque(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg != 0) {
return PSA_ERROR_BAD_STATE;
}
if (key_buffer_size < sizeof(esp_hmac_efuse_key_storage_t)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -265,83 +269,120 @@ psa_status_t esp_hmac_setup_opaque(
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_opaque_operation_t));
esp_hmac_ctx->alg = alg;
esp_hmac_ctx->key_buffer = key_buffer;
esp_hmac_ctx->is_persistent = is_persistent;
return PSA_SUCCESS;
}
psa_status_t esp_hmac_update_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx, const uint8_t *data, size_t data_length)
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
static psa_status_t esp_hmac_opaque_resolve_key(const esp_hmac_opaque_operation_t *ctx,
hmac_key_id_t *hmac_key_id,
const esp_key_mgr_key_recovery_info_t **kri)
{
if (!esp_hmac_ctx || !data || data_length == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
const uint8_t *key_buffer = ctx->key_buffer;
*kri = NULL;
if (hmac_storage_get_key_source(key_buffer) == ESP_HMAC_KEY_SOURCE_KEY_MGR) {
*kri = ctx->is_persistent
? &((const esp_hmac_km_key_storage_t *)key_buffer)->key_recovery_info
: ((const esp_hmac_volatile_key_storage_t *)key_buffer)->opaque_key.key_recovery_info;
if (esp_key_mgr_activate_key((esp_key_mgr_key_recovery_info_t *)*kri) != ESP_OK) {
*kri = NULL;
ESP_LOGE("ESP_HMAC_OPAQUE", "Failed to activate key");
return PSA_ERROR_INVALID_HANDLE;
}
*hmac_key_id = HMAC_KEY_KM;
return PSA_SUCCESS;
}
*hmac_key_id = ctx->is_persistent
? ((const esp_hmac_efuse_key_storage_t *)key_buffer)->efuse_key_id
: ((const esp_hmac_volatile_key_storage_t *)key_buffer)->opaque_key.efuse_key_id;
return PSA_SUCCESS;
}
#else
static psa_status_t esp_hmac_opaque_resolve_key(const esp_hmac_opaque_operation_t *ctx,
hmac_key_id_t *hmac_key_id)
{
const uint8_t *key_buffer = ctx->key_buffer;
*hmac_key_id = ctx->is_persistent
? ((const esp_hmac_efuse_key_storage_t *)key_buffer)->efuse_key_id
: ((const esp_hmac_volatile_key_storage_t *)key_buffer)->opaque_key.efuse_key_id;
return PSA_SUCCESS;
}
#endif /* SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD */
static psa_status_t esp_hmac_opaque_calculate(esp_hmac_opaque_operation_t *ctx,
const uint8_t *data, size_t data_length)
{
hmac_key_id_t hmac_key_id = 0;
psa_status_t status;
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
const esp_key_mgr_key_recovery_info_t *key_recovery_info = NULL;
const esp_key_mgr_key_recovery_info_t *kri = NULL;
status = esp_hmac_opaque_resolve_key(ctx, &hmac_key_id, &kri);
#else
status = esp_hmac_opaque_resolve_key(ctx, &hmac_key_id);
#endif /* SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD */
if (!esp_hmac_ctx->is_persistent) {
const esp_hmac_volatile_key_storage_t *ptr_st =
(const esp_hmac_volatile_key_storage_t *)esp_hmac_ctx->key_buffer;
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
esp_hmac_key_source_t key_source = hmac_storage_get_key_source(esp_hmac_ctx->key_buffer);
if (key_source == ESP_HMAC_KEY_SOURCE_KEY_MGR) {
key_recovery_info = ptr_st->opaque_key.key_recovery_info;
esp_err_t err = esp_key_mgr_activate_key((esp_key_mgr_key_recovery_info_t *)key_recovery_info);
if (err != ESP_OK) {
ESP_LOGE("ESP_HMAC_OPAQUE", "Failed to activate key: 0x%x", err);
return PSA_ERROR_INVALID_HANDLE;
}
hmac_key_id = HMAC_KEY_KM;
} else
#endif /* SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD */
{
hmac_key_id = ptr_st->opaque_key.efuse_key_id;
}
} else {
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
esp_hmac_key_source_t key_source = hmac_storage_get_key_source(esp_hmac_ctx->key_buffer);
if (key_source == ESP_HMAC_KEY_SOURCE_KEY_MGR) {
const esp_hmac_km_key_storage_t *km_st =
(const esp_hmac_km_key_storage_t *)esp_hmac_ctx->key_buffer;
key_recovery_info = &km_st->key_recovery_info;
esp_err_t err = esp_key_mgr_activate_key((esp_key_mgr_key_recovery_info_t *)key_recovery_info);
if (err != ESP_OK) {
ESP_LOGE("ESP_HMAC_OPAQUE", "Failed to activate key: 0x%x", err);
return PSA_ERROR_INVALID_HANDLE;
}
hmac_key_id = HMAC_KEY_KM;
} else
#endif /* SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD */
{
const esp_hmac_efuse_key_storage_t *efuse_st =
(const esp_hmac_efuse_key_storage_t *)esp_hmac_ctx->key_buffer;
hmac_key_id = efuse_st->efuse_key_id;
}
if (status != PSA_SUCCESS) {
return status;
}
esp_err_t hmac_ret = esp_hmac_calculate(hmac_key_id, data, data_length, esp_hmac_ctx->hmac);
esp_err_t hmac_ret = esp_hmac_calculate(hmac_key_id, data, data_length, ctx->hmac);
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
if (key_recovery_info) {
esp_key_mgr_deactivate_key(key_recovery_info->key_type);
if (kri) {
esp_key_mgr_deactivate_key(kri->key_type);
}
#endif /* SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD */
if (hmac_ret == ESP_OK) {
ctx->computed = true;
return PSA_SUCCESS;
}
mbedtls_platform_zeroize(ctx->hmac, sizeof(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_update_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx, const uint8_t *data, size_t data_length)
{
if (!esp_hmac_ctx) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data == NULL && data_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
if (esp_hmac_ctx->computed) {
return PSA_ERROR_BAD_STATE;
}
/*
* A zero-length update is a valid no-op. The empty-message MAC is produced
* lazily in finish: the one-shot HW HMAC cannot be fed incrementally, so we
* must not commit a MAC until we know no further (non-empty) data follows.
*/
if (data_length == 0) {
return PSA_SUCCESS;
}
return esp_hmac_opaque_calculate(esp_hmac_ctx, data, data_length);
}
psa_status_t esp_hmac_finish_opaque(
esp_hmac_opaque_operation_t *esp_hmac_ctx,
uint8_t *mac,
@@ -352,12 +393,34 @@ psa_status_t esp_hmac_finish_opaque(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (mac_size < ESP_HMAC_RESULT_SIZE) {
return PSA_ERROR_BUFFER_TOO_SMALL;
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
memcpy(mac, esp_hmac_ctx->hmac, ESP_HMAC_RESULT_SIZE);
*mac_length = ESP_HMAC_RESULT_SIZE;
if (mac_size == 0 || mac_size > ESP_HMAC_RESULT_SIZE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
/*
* No update committed a MAC: the message is empty (e.g. psa_mac_compute()
* over "" or setup->finish with no update). Compute HMAC(key, "") now.
* esp_hmac_calculate() rejects a NULL pointer, so pass a valid zero-length
* buffer rather than NULL.
*/
if (!esp_hmac_ctx->computed) {
const uint8_t empty = 0;
psa_status_t status = esp_hmac_opaque_calculate(esp_hmac_ctx, &empty, 0);
if (status != PSA_SUCCESS) {
return status;
}
}
/* PSA core passes the truncated length as mac_size; copy exactly that
* many bytes to honour PSA_ALG_TRUNCATED_MAC. */
memcpy(mac, esp_hmac_ctx->hmac, mac_size);
*mac_length = mac_size;
mbedtls_platform_zeroize(esp_hmac_ctx->hmac, sizeof(esp_hmac_ctx->hmac));
return PSA_SUCCESS;
}
@@ -379,20 +442,23 @@ psa_status_t esp_hmac_compute_opaque(
status = esp_hmac_setup_opaque(&esp_hmac_ctx, attributes, key_buffer, key_buffer_size, alg);
if (status != PSA_SUCCESS) {
return status;
goto exit;
}
status = esp_hmac_update_opaque(&esp_hmac_ctx, input, input_length);
if (status != PSA_SUCCESS) {
return status;
goto exit;
}
status = esp_hmac_finish_opaque(&esp_hmac_ctx, mac, mac_size, mac_length);
if (status != PSA_SUCCESS) {
return status;
size_t actual_mac_length = 0;
status = esp_hmac_finish_opaque(&esp_hmac_ctx, mac, mac_size, &actual_mac_length);
if (status == PSA_SUCCESS) {
*mac_length = actual_mac_length;
}
return PSA_SUCCESS;
exit:
esp_hmac_abort_opaque(&esp_hmac_ctx);
return status;
}
psa_status_t esp_hmac_verify_finish_opaque(
@@ -404,7 +470,19 @@ psa_status_t esp_hmac_verify_finish_opaque(
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 (esp_hmac_ctx == NULL || mac == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (mac_length == 0 || mac_length > sizeof(actual_mac)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
status = esp_hmac_finish_opaque(esp_hmac_ctx, actual_mac, mac_length, &actual_mac_length);
if (status == PSA_SUCCESS) {
if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) {
status = PSA_ERROR_INVALID_SIGNATURE;

View File

@@ -15,20 +15,22 @@
psa_status_t esp_hmac_abort_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
if (esp_hmac_ctx == NULL) {
return PSA_SUCCESS;
}
if (esp_hmac_ctx->alg == 0) {
return PSA_SUCCESS;
}
#if defined(ESP_MD5_DRIVER_ENABLED)
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg);
if (hash_alg == PSA_ALG_MD5) {
status = esp_md5_hash_abort(&esp_hmac_ctx->md5_ctx);
(void)esp_md5_hash_abort(&esp_hmac_ctx->md5_ctx);
} else
#endif // defined(ESP_MD5_DRIVER_ENABLED)
{
status = esp_sha_hash_abort(&esp_hmac_ctx->esp_sha_ctx);
}
if (status != PSA_SUCCESS) {
return status;
(void)esp_sha_hash_abort(&esp_hmac_ctx->esp_sha_ctx);
}
// Free dynamically allocated opad buffer
@@ -39,7 +41,7 @@ psa_status_t esp_hmac_abort_transparent(esp_hmac_transparent_operation_t *esp_hm
}
mbedtls_platform_zeroize(esp_hmac_ctx, sizeof(esp_hmac_transparent_operation_t));
return status;
return PSA_SUCCESS;
}
psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hmac_ctx,
@@ -59,12 +61,26 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
return PSA_ERROR_INVALID_ARGUMENT;
}
if (!PSA_ALG_IS_HMAC(alg)) {
return PSA_ERROR_NOT_SUPPORTED;
}
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_HMAC) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg != 0) {
return PSA_ERROR_BAD_STATE;
}
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_transparent_operation_t));
esp_hmac_ctx->alg = alg;
// Allocate opad buffer dynamically
esp_hmac_ctx->opad = (uint8_t *)malloc(PSA_HMAC_MAX_HASH_BLOCK_SIZE);
if (esp_hmac_ctx->opad == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto cleanup;
}
memset(esp_hmac_ctx->opad, 0, PSA_HMAC_MAX_HASH_BLOCK_SIZE);
@@ -80,11 +96,9 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
#endif // SOC_SHA_SUPPORT_SHA512
)) {
status = PSA_ERROR_NOT_SUPPORTED;
goto error;
goto cleanup;
}
esp_hmac_ctx->alg = 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. */
@@ -92,7 +106,7 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
* have the same size (PSA_HMAC_MAX_HASH_BLOCK_SIZE). */
if ((block_size > sizeof(ipad)) || (block_size < hash_size)) {
status = PSA_ERROR_NOT_SUPPORTED;
goto error;
goto cleanup;
}
if (key_buffer_size > block_size) {
@@ -107,13 +121,13 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
ipad, sizeof(ipad), &key_buffer_size);
}
if (status != PSA_SUCCESS) {
goto error;
goto cleanup;
}
/* 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) {
status = PSA_ERROR_CORRUPTION_DETECTED;
goto error;
goto cleanup;
}
}
/* A 0-length key is not commonly used in HMAC when used as a MAC,
@@ -124,7 +138,7 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
/* Additional safety check: ensure key fits in ipad buffer */
if (key_buffer_size > sizeof(ipad)) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto error;
goto cleanup;
}
memcpy(ipad, key_buffer, key_buffer_size);
}
@@ -173,7 +187,7 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg);
}
if (status != PSA_SUCCESS) {
goto error;
goto cleanup;
}
#if defined(ESP_MD5_DRIVER_ENABLED)
@@ -185,22 +199,35 @@ psa_status_t esp_hmac_setup_transparent(esp_hmac_transparent_operation_t *esp_hm
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, ipad, block_size);
}
if (status != PSA_SUCCESS) {
goto error;
goto cleanup;
}
return status;
status = PSA_SUCCESS;
error:
esp_hmac_abort_transparent(esp_hmac_ctx);
cleanup:
mbedtls_platform_zeroize(ipad, sizeof(ipad));
if (status != PSA_SUCCESS) {
esp_hmac_abort_transparent(esp_hmac_ctx);
}
return status;
}
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) {
if (esp_hmac_ctx == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data == NULL && data_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
if (data_length == 0) {
return PSA_SUCCESS;
}
#if defined(ESP_MD5_DRIVER_ENABLED)
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg);
@@ -225,6 +252,10 @@ psa_status_t esp_hmac_finish_transparent(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg);
uint8_t tmp[PSA_HASH_MAX_SIZE];
@@ -240,10 +271,21 @@ psa_status_t esp_hmac_finish_transparent(
status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size);
}
if (status != PSA_SUCCESS) {
(void)esp_hmac_abort_transparent(esp_hmac_ctx);
return status;
}
/* From here on, tmp needs to be wiped. */
/* Inner hash finished — abort it before reusing for the outer hash. */
#if defined(ESP_MD5_DRIVER_ENABLED)
if (hash_alg == PSA_ALG_MD5) {
(void)esp_md5_hash_abort(&esp_hmac_ctx->md5_ctx);
} else
#endif // defined(ESP_MD5_DRIVER_ENABLED)
{
(void)esp_sha_hash_abort(&esp_hmac_ctx->esp_sha_ctx);
}
#if defined(ESP_MD5_DRIVER_ENABLED)
if (hash_alg == PSA_ALG_MD5) {
status = esp_md5_hash_setup(&esp_hmac_ctx->md5_ctx, hash_alg);
@@ -301,6 +343,7 @@ psa_status_t esp_hmac_finish_transparent(
exit:
mbedtls_platform_zeroize(tmp, hash_size);
(void)esp_hmac_abort_transparent(esp_hmac_ctx);
return status;
}
@@ -357,7 +400,11 @@ psa_status_t esp_hmac_verify_finish_transparent(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (mac_length > sizeof(actual_mac)) {
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
if (mac_length == 0 || mac_length > sizeof(actual_mac)) {
return PSA_ERROR_INVALID_ARGUMENT;
}

View File

@@ -5,6 +5,7 @@
*/
#include <string.h>
#include "mbedtls/platform_util.h"
#include "psa_crypto_driver_esp_md5.h"
psa_status_t esp_md5_hash_compute(psa_algorithm_t alg,
@@ -20,50 +21,63 @@ psa_status_t esp_md5_hash_compute(psa_algorithm_t alg,
if (input_length > 0 && input == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (alg != PSA_ALG_MD5) {
return PSA_ALG_IS_HASH(alg) ? PSA_ERROR_NOT_SUPPORTED
: PSA_ERROR_INVALID_ARGUMENT;
}
if (hash_size < PSA_HASH_LENGTH(PSA_ALG_MD5)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
if (alg != PSA_ALG_MD5) {
return PSA_ERROR_NOT_SUPPORTED;
}
md5_context_t operation = {0};
esp_rom_md5_init(&operation);
esp_rom_md5_update(&operation, input, input_length);
esp_rom_md5_final(hash, &operation);
md5_context_t ctx = {0};
esp_rom_md5_init(&ctx);
esp_rom_md5_update(&ctx, input, input_length);
esp_rom_md5_final(hash, &ctx);
*hash_length = PSA_HASH_LENGTH(PSA_ALG_MD5);
mbedtls_platform_zeroize(&ctx, sizeof(ctx));
return PSA_SUCCESS;
}
psa_status_t esp_md5_hash_setup(md5_context_t *operation,
psa_status_t esp_md5_hash_setup(esp_md5_hash_operation_t *operation,
psa_algorithm_t alg)
{
if (operation == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (alg != PSA_ALG_MD5) {
return PSA_ERROR_NOT_SUPPORTED;
return PSA_ALG_IS_HASH(alg) ? PSA_ERROR_NOT_SUPPORTED
: PSA_ERROR_INVALID_ARGUMENT;
}
esp_rom_md5_init(operation);
if (operation->is_active) {
return PSA_ERROR_BAD_STATE;
}
esp_rom_md5_init(&operation->md5_ctx);
operation->is_active = true;
return PSA_SUCCESS;
}
psa_status_t esp_md5_hash_update(
md5_context_t *operation,
esp_md5_hash_operation_t *operation,
const uint8_t *input,
size_t input_length )
{
if (operation == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (input_length > 0 && input == NULL) {
if (input == NULL && input_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
esp_rom_md5_update(operation, input, input_length);
if (!operation->is_active) {
return PSA_ERROR_BAD_STATE;
}
if (input_length == 0) {
return PSA_SUCCESS;
}
esp_rom_md5_update(&operation->md5_ctx, input, input_length);
return PSA_SUCCESS;
}
psa_status_t esp_md5_hash_finish(
md5_context_t *operation,
esp_md5_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length)
@@ -71,31 +85,40 @@ psa_status_t esp_md5_hash_finish(
if (operation == NULL || hash == NULL || hash_length == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (!operation->is_active) {
return PSA_ERROR_BAD_STATE;
}
if (hash_size < PSA_HASH_LENGTH(PSA_ALG_MD5)) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
esp_rom_md5_final(hash, operation);
esp_rom_md5_final(hash, &operation->md5_ctx);
*hash_length = PSA_HASH_LENGTH(PSA_ALG_MD5);
mbedtls_platform_zeroize(operation, sizeof(*operation));
return PSA_SUCCESS;
}
psa_status_t esp_md5_hash_abort(md5_context_t *operation)
psa_status_t esp_md5_hash_abort(esp_md5_hash_operation_t *operation)
{
if (operation == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
return PSA_SUCCESS;
}
memset(operation, 0, sizeof(*operation));
mbedtls_platform_zeroize(operation, sizeof(*operation));
return PSA_SUCCESS;
}
psa_status_t esp_md5_hash_clone(
const md5_context_t *source_operation,
md5_context_t *target_operation)
const esp_md5_hash_operation_t *source_operation,
esp_md5_hash_operation_t *target_operation)
{
if (source_operation == NULL || target_operation == NULL) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memcpy(target_operation, source_operation, sizeof(md5_context_t));
if (!source_operation->is_active) {
return PSA_ERROR_BAD_STATE;
}
if (target_operation->is_active) {
return PSA_ERROR_BAD_STATE;
}
memcpy(target_operation, source_operation, sizeof(esp_md5_hash_operation_t));
return PSA_SUCCESS;
}

View File

@@ -82,6 +82,8 @@ psa_status_t esp_rsa_ds_pad_v21_encode(psa_algorithm_t hash_alg,
* @param output_max_len Maximum length of the output buffer
* @param olen Pointer to the length of the output data
* @param hash_alg Hash algorithm identifier
* @param label OAEP label the ciphertext is bound to (may be NULL if label_length is 0)
* @param label_length Length of the label in bytes
* @return psa_status_t
* PSA_ERROR_INVALID_ARGUMENT if arguments are invalid
* PSA_SUCCESS on success
@@ -91,7 +93,9 @@ psa_status_t esp_rsa_ds_pad_oaep_unpad(unsigned char *input,
unsigned char *output,
size_t output_max_len,
size_t *olen,
psa_algorithm_t hash_alg);
psa_algorithm_t hash_alg,
const uint8_t *label,
size_t label_length);
#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 */
#ifdef __cplusplus
}

View File

@@ -14,6 +14,7 @@
#include "psa_crypto_driver_esp_opaque_common.h"
#include "include/psa_crypto_driver_esp_rsa_ds_utilities.h"
#include "mbedtls/platform_util.h"
#include "esp_log.h"
#include "esp_efuse.h"
#include "esp_assert.h"
@@ -412,6 +413,26 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_start(
return PSA_ERROR_NOT_SUPPORTED;
}
#if !defined(CONFIG_MBEDTLS_SSL_PROTO_TLS1_3)
if (PSA_ALG_IS_RSA_PSS(alg)) {
/* PSS encode is only compiled under TLS1.3; fail up front before any
* peripheral lock / allocation. */
return PSA_ERROR_NOT_SUPPORTED;
}
#endif /* !defined(CONFIG_MBEDTLS_SSL_PROTO_TLS1_3) */
/* Cross-check the supplied hash_length against PSA_ALG_GET_HASH(alg).
* For PKCS1V15_SIGN_RAW the hash field is opaque-length data; skip. */
{
psa_algorithm_t hash_alg_check = PSA_ALG_SIGN_GET_HASH(alg);
if (hash_alg_check != PSA_ALG_NONE) {
size_t expected = PSA_HASH_LENGTH(hash_alg_check);
if (expected == 0 || hash_length != expected) {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
}
esp_rsa_ds_key_source_t key_source = ESP_RSA_DS_KEY_SOURCE_EFUSE;
uint16_t rsa_length_bits = 0;
const esp_ds_data_t *ds_data = NULL;
@@ -454,12 +475,21 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_start(
unsigned char *em = heap_caps_malloc_prefer(rsa_len_bytes, 1, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
if (em == NULL) {
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_INSUFFICIENT_MEMORY;
status = PSA_ERROR_INSUFFICIENT_MEMORY;
goto error;
}
/* Derive PSS salt length from the alg: -1 (MBEDTLS_RSA_SALT_LEN_ANY) for
* PSS_ANY_SALT, else the standard FIPS 186-4 fixed length. */
int saltlen = -1;
if (PSA_ALG_IS_RSA_PSS(alg) && !PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {
int klen = (int) rsa_len_bytes;
int hlen = (int) hash_length;
int room = klen - 2 - hlen;
saltlen = (room < 0) ? 0 : ((room > hlen) ? hlen : room);
}
status = esp_rsa_ds_pad(
padding, hash_alg, hash_length, hash, -1, em, rsa_len_bytes);
padding, hash_alg, hash_length, hash, saltlen, em, rsa_len_bytes);
if (status != PSA_SUCCESS) {
goto error;
}
@@ -500,10 +530,13 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_start(
error:
if (em) {
memset(em, 0, rsa_len_bytes);
mbedtls_platform_zeroize(em, rsa_len_bytes);
heap_caps_free(em);
em = NULL;
}
if (status != PSA_SUCCESS) {
esp_rsa_ds_opaque_sign_hash_abort(operation);
}
return status;
}
@@ -530,10 +563,12 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_complete(
return PSA_ERROR_BUFFER_TOO_SMALL;
}
psa_status_t status;
esp_err_t err = esp_ds_finish_sign((void *)operation->sig_buffer, operation->esp_rsa_ds_ctx);
operation->esp_rsa_ds_ctx = NULL;
if (err != ESP_OK) {
return PSA_ERROR_GENERIC_ERROR;
status = PSA_ERROR_GENERIC_ERROR;
goto cleanup;
}
unsigned int words_len = expected_signature_size / 4;
@@ -544,16 +579,11 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_complete(
}
*signature_length = expected_signature_size;
status = PSA_SUCCESS;
esp_rsa_ds_release_ds_lock();
if (operation->sig_buffer) {
memset(operation->sig_buffer, 0, operation->sig_buffer_size);
heap_caps_free(operation->sig_buffer);
operation->sig_buffer = NULL;
}
return PSA_SUCCESS;
cleanup:
(void)esp_rsa_ds_opaque_sign_hash_abort(operation);
return status;
}
psa_status_t esp_rsa_ds_opaque_sign_hash_abort(
@@ -583,7 +613,7 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_abort(
// Free allocated memory if exists
if (operation->sig_buffer) {
memset(operation->sig_buffer, 0, operation->sig_buffer_size);
mbedtls_platform_zeroize(operation->sig_buffer, operation->sig_buffer_size);
heap_caps_free(operation->sig_buffer);
operation->sig_buffer = NULL;
}
@@ -592,7 +622,7 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_abort(
esp_rsa_ds_release_ds_lock();
// Clear the operation structure
memset(operation, 0, sizeof(esp_rsa_ds_opaque_sign_hash_operation_t));
mbedtls_platform_zeroize(operation, sizeof(esp_rsa_ds_opaque_sign_hash_operation_t));
return PSA_SUCCESS;
}
@@ -620,7 +650,6 @@ psa_status_t esp_rsa_ds_opaque_signature_sign_hash(
hash_length
);
if (status != PSA_SUCCESS) {
esp_rsa_ds_opaque_sign_hash_abort(&operation);
return status;
}
@@ -764,10 +793,17 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
size_t input_length, const uint8_t *salt, size_t salt_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
(void)salt;
(void)salt_length;
psa_status_t ret = PSA_ERROR_CORRUPTION_DETECTED;
esp_err_t err = ESP_FAIL;
uint32_t *em_words = NULL;
uint32_t *out_tmp = NULL;
size_t data_len = 0;
bool lock_held = false;
esp_ds_context_t *ds_ctx = NULL;
#if SOC_KEY_MANAGER_SUPPORTED
bool is_km_key_active = false;
esp_key_mgr_key_recovery_info_t *km_ri = NULL;
#endif /* SOC_KEY_MANAGER_SUPPORTED */
if (!attributes || !key || !input || input_length < 1 || !output || !output_length) {
return PSA_ERROR_INVALID_ARGUMENT;
@@ -777,25 +813,37 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
return PSA_ERROR_NOT_SUPPORTED;
}
/* Decrypt requires a private key. The PSA core enforces this via key
* usage, but check the type here as defense-in-depth. */
if (!PSA_KEY_TYPE_IS_RSA(psa_get_key_type(attributes)) ||
!PSA_KEY_TYPE_IS_KEY_PAIR(psa_get_key_type(attributes))) {
return PSA_ERROR_NOT_SUPPORTED;
}
/* PKCS1V15_CRYPT has no label; reject any non-empty salt. */
if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT && salt_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (salt == NULL && salt_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
bool is_persistent = esp_opaque_key_is_persistent(attributes);
esp_rsa_ds_key_source_t key_source = ESP_RSA_DS_KEY_SOURCE_EFUSE;
uint16_t rsa_length_bits = 0;
const esp_ds_data_t *ds_data = NULL;
hmac_key_id_t hmac_key_id = 0;
#if SOC_KEY_MANAGER_SUPPORTED
esp_key_mgr_key_recovery_info_t *km_ri = NULL;
#endif /* SOC_KEY_MANAGER_SUPPORTED */
psa_status_t status = esp_rsa_ds_extract_storage(
ret = esp_rsa_ds_extract_storage(
key, key_length, is_persistent,
&key_source, &rsa_length_bits, &ds_data, &hmac_key_id
#if SOC_KEY_MANAGER_SUPPORTED
, &km_ri
#endif /* SOC_KEY_MANAGER_SUPPORTED */
);
if (status != PSA_SUCCESS) {
return status;
if (ret != PSA_SUCCESS) {
return ret;
}
if (input_length != (rsa_length_bits / 8)) {
@@ -812,13 +860,14 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
if (xSemaphoreTake(s_ds_lock, s_timeout_ms / portTICK_PERIOD_MS) != pdTRUE) {
return PSA_ERROR_GENERIC_ERROR;
}
lock_held = true;
size_t ilen = rsa_length_bits / 8;
size_t data_len = ilen / 4;
uint32_t *em_words = heap_caps_malloc_prefer(sizeof(uint32_t) * data_len, 1, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
data_len = ilen / 4;
em_words = heap_caps_malloc_prefer(sizeof(uint32_t) * data_len, 1, MALLOC_CAP_32BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
if (em_words == NULL) {
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_INSUFFICIENT_MEMORY;
ret = PSA_ERROR_INSUFFICIENT_MEMORY;
goto exit;
}
for (unsigned int i = 0; i < (data_len); i++) {
@@ -826,60 +875,38 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
}
#if SOC_KEY_MANAGER_SUPPORTED
bool is_km_key_active = false;
if (key_source == ESP_RSA_DS_KEY_SOURCE_KEY_MGR) {
err = esp_key_mgr_activate_key(km_ri);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to activate key: 0x%x", err);
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_INVALID_HANDLE;
ret = PSA_ERROR_INVALID_HANDLE;
goto exit;
}
is_km_key_active = true;
}
#endif /* SOC_KEY_MANAGER_SUPPORTED */
esp_ds_context_t *ds_ctx = NULL;
err = esp_ds_start_sign((const void *)em_words,
ds_data,
hmac_key_id,
&ds_ctx);
if (err != ESP_OK) {
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
#if SOC_KEY_MANAGER_SUPPORTED
if (is_km_key_active) {
esp_key_mgr_deactivate_key(km_ri->key_type);
}
#endif /* SOC_KEY_MANAGER_SUPPORTED */
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_GENERIC_ERROR;
ret = PSA_ERROR_GENERIC_ERROR;
goto exit;
}
err = esp_ds_finish_sign((void *)em_words, ds_ctx);
#if SOC_KEY_MANAGER_SUPPORTED
if (is_km_key_active) {
esp_key_mgr_deactivate_key(km_ri->key_type);
}
#endif /* SOC_KEY_MANAGER_SUPPORTED */
ds_ctx = NULL;
if (err != ESP_OK) {
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
esp_rsa_ds_release_ds_lock();
return PSA_ERROR_GENERIC_ERROR;
ret = PSA_ERROR_GENERIC_ERROR;
goto exit;
}
esp_rsa_ds_release_ds_lock();
// Remove padding
uint32_t *out_tmp = heap_caps_malloc_prefer(sizeof(uint32_t) * data_len, 1, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
out_tmp = heap_caps_malloc_prefer(sizeof(uint32_t) * data_len, 1, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
if (out_tmp == NULL) {
memset(em_words, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
return PSA_ERROR_INSUFFICIENT_MEMORY;
ret = PSA_ERROR_INSUFFICIENT_MEMORY;
goto exit;
}
for (unsigned int i = 0; i < (data_len); i++) {
@@ -887,13 +914,12 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
}
size_t unpadded_len = 0;
psa_status_t ret = PSA_ERROR_NOT_SUPPORTED;
if (padding == ESP_RSA_DS_PADDING_PKCS_V15) {
ret = esp_rsa_ds_pad_v15_unpad((unsigned char *)out_tmp, ilen, (unsigned char *)out_tmp, ilen, &unpadded_len);
}
#if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3
else if (padding == ESP_RSA_DS_PADDING_OAEP) {
ret = esp_rsa_ds_pad_oaep_unpad((unsigned char *)out_tmp, ilen, (unsigned char *)out_tmp, ilen, &unpadded_len, PSA_ALG_RSA_OAEP_GET_HASH(alg));
ret = esp_rsa_ds_pad_oaep_unpad((unsigned char *)out_tmp, ilen, (unsigned char *)out_tmp, ilen, &unpadded_len, PSA_ALG_RSA_OAEP_GET_HASH(alg), salt, salt_length);
}
#endif /* CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 */
else {
@@ -916,9 +942,21 @@ psa_status_t esp_rsa_ds_opaque_asymmetric_decrypt(
ret = PSA_SUCCESS;
exit:
memset(em_words, 0, sizeof(uint32_t) * data_len);
memset(out_tmp, 0, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
heap_caps_free(out_tmp);
#if SOC_KEY_MANAGER_SUPPORTED
if (is_km_key_active && km_ri) {
esp_key_mgr_deactivate_key(km_ri->key_type);
}
#endif /* SOC_KEY_MANAGER_SUPPORTED */
if (em_words != NULL) {
mbedtls_platform_zeroize(em_words, sizeof(uint32_t) * data_len);
heap_caps_free(em_words);
}
if (out_tmp != NULL) {
mbedtls_platform_zeroize(out_tmp, sizeof(uint32_t) * data_len);
heap_caps_free(out_tmp);
}
if (lock_held) {
esp_rsa_ds_release_ds_lock();
}
return ret;
}

View File

@@ -43,13 +43,13 @@ static const oid_md_mapping_t oid_md_table[] = {
{ PSA_ALG_NONE, NULL, 0 }
};
static int esp_rsa_ds_get_oid_by_psa_alg(psa_algorithm_t md_alg, const char **oid, size_t *olen)
static psa_status_t esp_rsa_ds_get_oid_by_psa_alg(psa_algorithm_t md_alg, const char **oid, size_t *olen)
{
for (size_t i = 0; oid_md_table[i].md_alg != PSA_ALG_NONE; i++) {
if (oid_md_table[i].md_alg == md_alg) {
*oid = oid_md_table[i].oid;
*olen = oid_md_table[i].oid_len;
return 0;
return PSA_SUCCESS;
}
}
return PSA_ERROR_NOT_SUPPORTED;
@@ -379,14 +379,20 @@ psa_status_t esp_rsa_ds_pad_v21_encode(psa_algorithm_t hash_alg,
hlen = PSA_HASH_LENGTH(hash_alg);
/* Reject hash-less or unknown algorithms up front: hlen == 0 would
* underflow min_slen below and wrap the olen bounds checks. */
if (hlen == 0 || hlen > PSA_HASH_MAX_SIZE) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (saltlen == -1) {
/* Calculate the largest possible salt length, up to the hash size.
* Normally this is the hash length, which is the maximum salt length
* according to FIPS 185-4 <EFBFBD>5.5 (e) and common practice. If there is not
* according to FIPS 186-4 Section 5.5 (e) and common practice. If there is not
* enough room, use the maximum salt length that fits. The constraint is
* that the hash length plus the salt length plus 2 bytes must be at most
* the key length. This complies with FIPS 186-4 <EFBFBD>5.5 (e) and RFC 8017
* (PKCS#1 v2.2) <EFBFBD>9.1.1 step 3. */
* the key length. This complies with FIPS 186-4 Section 5.5 (e) and RFC 8017
* (PKCS#1 v2.2) Section 9.1.1 step 3. */
min_slen = hlen - 2;
if (olen < hlen + min_slen + 2) {
return PSA_ERROR_INVALID_ARGUMENT;
@@ -432,7 +438,6 @@ psa_status_t esp_rsa_ds_pad_v21_encode(psa_algorithm_t hash_alg,
return ret;
}
msb = dst_len * 8 - 1;
sig[0] &= 0xFF >> (olen * 8 - msb);
p += hlen;
@@ -445,7 +450,9 @@ psa_status_t esp_rsa_ds_pad_oaep_unpad(unsigned char *input,
unsigned char *output,
size_t output_max_len,
size_t *olen,
psa_algorithm_t hash_alg)
psa_algorithm_t hash_alg,
const uint8_t *label,
size_t label_length)
{
/* This mirrors mbedtls_rsa_rsaes_oaep_decrypt() in upstream rsa.c.
* Below the public-input sanity check, the unpadding scan operates
@@ -512,6 +519,7 @@ psa_status_t esp_rsa_ds_pad_oaep_unpad(unsigned char *input,
/* Single decision point on the accumulated bit. */
if (bad != MBEDTLS_CT_FALSE) {
*olen = 0;
mbedtls_platform_zeroize(input, ilen);
return PSA_ERROR_INVALID_ARGUMENT;
}

View File

@@ -5,12 +5,13 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD
*/
#include <stdio.h>
#include <string.h>
#include "mbedtls/esp_config.h"
#include "mbedtls/platform_util.h"
#include "psa_crypto_driver_esp_sha.h"
#include "../include/psa_crypto_driver_esp_sha1.h"
#include "esp_sha_internal.h"
@@ -368,21 +369,25 @@ psa_status_t esp_sha1_driver_compute(
int ret = esp_sha1_starts(ctx);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha1_update(ctx, input, input_length);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha1_finish(ctx, hash);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
*hash_length = PSA_HASH_LENGTH(PSA_ALG_SHA_1);
return PSA_SUCCESS;
hw_fail:
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
return PSA_ERROR_HARDWARE_FAILURE;
}
psa_status_t esp_sha1_driver_update(
@@ -426,7 +431,7 @@ psa_status_t esp_sha1_driver_abort(esp_sha1_context *ctx)
if (!ctx) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memset(ctx, 0, sizeof(esp_sha1_context));
mbedtls_platform_zeroize(ctx, sizeof(esp_sha1_context));
return PSA_SUCCESS;
}

View File

@@ -5,12 +5,13 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD
*/
#include <stdio.h>
#include <string.h>
#include "mbedtls/esp_config.h"
#include "mbedtls/platform_util.h"
#include "psa_crypto_driver_esp_sha.h"
#include "../include/psa_crypto_driver_esp_sha256.h"
#include "esp_sha_internal.h"
@@ -190,20 +191,24 @@ psa_status_t esp_sha256_driver_compute(
#endif // SOC_SHA_SUPPORT_SHA224
int ret = esp_sha256_starts(ctx, mode);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha256_update(ctx, input, input_length);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha256_finish(ctx, hash);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
*hash_length = PSA_HASH_LENGTH(alg);
return PSA_SUCCESS;
hw_fail:
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
return PSA_ERROR_HARDWARE_FAILURE;
}
psa_status_t esp_sha256_driver_update(
@@ -260,7 +265,7 @@ psa_status_t esp_sha256_driver_abort(esp_sha256_context *ctx)
if (!ctx) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memset(ctx, 0, sizeof(esp_sha256_context));
mbedtls_platform_zeroize(ctx, sizeof(esp_sha256_context));
return PSA_SUCCESS;
}

View File

@@ -5,12 +5,13 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD
*/
#include <stdio.h>
#include <string.h>
#include "mbedtls/esp_config.h"
#include "mbedtls/platform_util.h"
#include "psa_crypto_driver_esp_sha.h"
#include "../include/psa_crypto_driver_esp_sha512.h"
#include "esp_sha_internal.h"
@@ -219,20 +220,24 @@ psa_status_t esp_sha512_driver_compute(
#endif // SOC_SHA_SUPPORT_SHA384
int ret = esp_sha512_starts(ctx, mode);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha512_update(ctx, input, input_length);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha512_finish(ctx, hash);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
*hash_length = PSA_HASH_LENGTH(alg);
return PSA_SUCCESS;
hw_fail:
mbedtls_platform_zeroize(ctx, sizeof(*ctx));
return PSA_ERROR_HARDWARE_FAILURE;
}
psa_status_t esp_sha512_driver_update(
@@ -286,7 +291,7 @@ psa_status_t esp_sha512_driver_abort(esp_sha512_context *ctx)
if (!ctx) {
return PSA_ERROR_INVALID_ARGUMENT;
}
memset(ctx, 0, sizeof(esp_sha512_context));
mbedtls_platform_zeroize(ctx, sizeof(esp_sha512_context));
return PSA_SUCCESS;
}

View File

@@ -5,7 +5,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD
*/
#include <string.h>
@@ -13,6 +13,7 @@
#include "../include/psa_crypto_driver_esp_sha1.h"
#include "sha/sha_parallel_engine.h"
#include "esp_err.h"
#include "mbedtls/platform_util.h"
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
@@ -77,32 +78,34 @@ int esp_sha1_starts(esp_sha1_context *ctx)
static void esp_sha1_software_process( esp_sha1_context *ctx, const unsigned char data[64] )
{
uint32_t temp, W[16], A, B, C, D, E;
struct {
uint32_t temp, W[16], A, B, C, D, E;
} local;
GET_UINT32_BE( W[ 0], data, 0 );
GET_UINT32_BE( W[ 1], data, 4 );
GET_UINT32_BE( W[ 2], data, 8 );
GET_UINT32_BE( W[ 3], data, 12 );
GET_UINT32_BE( W[ 4], data, 16 );
GET_UINT32_BE( W[ 5], data, 20 );
GET_UINT32_BE( W[ 6], data, 24 );
GET_UINT32_BE( W[ 7], data, 28 );
GET_UINT32_BE( W[ 8], data, 32 );
GET_UINT32_BE( W[ 9], data, 36 );
GET_UINT32_BE( W[10], data, 40 );
GET_UINT32_BE( W[11], data, 44 );
GET_UINT32_BE( W[12], data, 48 );
GET_UINT32_BE( W[13], data, 52 );
GET_UINT32_BE( W[14], data, 56 );
GET_UINT32_BE( W[15], data, 60 );
GET_UINT32_BE( local.W[ 0], data, 0 );
GET_UINT32_BE( local.W[ 1], data, 4 );
GET_UINT32_BE( local.W[ 2], data, 8 );
GET_UINT32_BE( local.W[ 3], data, 12 );
GET_UINT32_BE( local.W[ 4], data, 16 );
GET_UINT32_BE( local.W[ 5], data, 20 );
GET_UINT32_BE( local.W[ 6], data, 24 );
GET_UINT32_BE( local.W[ 7], data, 28 );
GET_UINT32_BE( local.W[ 8], data, 32 );
GET_UINT32_BE( local.W[ 9], data, 36 );
GET_UINT32_BE( local.W[10], data, 40 );
GET_UINT32_BE( local.W[11], data, 44 );
GET_UINT32_BE( local.W[12], data, 48 );
GET_UINT32_BE( local.W[13], data, 52 );
GET_UINT32_BE( local.W[14], data, 56 );
GET_UINT32_BE( local.W[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define R(t) \
( \
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
( W[t & 0x0F] = S(temp,1) ) \
local.temp = local.W[( t - 3 ) & 0x0F] ^ local.W[( t - 8 ) & 0x0F] ^ \
local.W[( t - 14 ) & 0x0F] ^ local.W[ t & 0x0F], \
( local.W[t & 0x0F] = S(local.temp,1) ) \
)
#define P(a,b,c,d,e,x) \
@@ -110,35 +113,35 @@ static void esp_sha1_software_process( esp_sha1_context *ctx, const unsigned cha
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
local.A = ctx->state[0];
local.B = ctx->state[1];
local.C = ctx->state[2];
local.D = ctx->state[3];
local.E = ctx->state[4];
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P( A, B, C, D, E, W[0] );
P( E, A, B, C, D, W[1] );
P( D, E, A, B, C, W[2] );
P( C, D, E, A, B, W[3] );
P( B, C, D, E, A, W[4] );
P( A, B, C, D, E, W[5] );
P( E, A, B, C, D, W[6] );
P( D, E, A, B, C, W[7] );
P( C, D, E, A, B, W[8] );
P( B, C, D, E, A, W[9] );
P( A, B, C, D, E, W[10] );
P( E, A, B, C, D, W[11] );
P( D, E, A, B, C, W[12] );
P( C, D, E, A, B, W[13] );
P( B, C, D, E, A, W[14] );
P( A, B, C, D, E, W[15] );
P( E, A, B, C, D, R(16) );
P( D, E, A, B, C, R(17) );
P( C, D, E, A, B, R(18) );
P( B, C, D, E, A, R(19) );
P( local.A, local.B, local.C, local.D, local.E, local.W[0] );
P( local.E, local.A, local.B, local.C, local.D, local.W[1] );
P( local.D, local.E, local.A, local.B, local.C, local.W[2] );
P( local.C, local.D, local.E, local.A, local.B, local.W[3] );
P( local.B, local.C, local.D, local.E, local.A, local.W[4] );
P( local.A, local.B, local.C, local.D, local.E, local.W[5] );
P( local.E, local.A, local.B, local.C, local.D, local.W[6] );
P( local.D, local.E, local.A, local.B, local.C, local.W[7] );
P( local.C, local.D, local.E, local.A, local.B, local.W[8] );
P( local.B, local.C, local.D, local.E, local.A, local.W[9] );
P( local.A, local.B, local.C, local.D, local.E, local.W[10] );
P( local.E, local.A, local.B, local.C, local.D, local.W[11] );
P( local.D, local.E, local.A, local.B, local.C, local.W[12] );
P( local.C, local.D, local.E, local.A, local.B, local.W[13] );
P( local.B, local.C, local.D, local.E, local.A, local.W[14] );
P( local.A, local.B, local.C, local.D, local.E, local.W[15] );
P( local.E, local.A, local.B, local.C, local.D, R(16) );
P( local.D, local.E, local.A, local.B, local.C, R(17) );
P( local.C, local.D, local.E, local.A, local.B, R(18) );
P( local.B, local.C, local.D, local.E, local.A, R(19) );
#undef K
#undef F
@@ -146,26 +149,26 @@ static void esp_sha1_software_process( esp_sha1_context *ctx, const unsigned cha
#define F(x,y,z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P( A, B, C, D, E, R(20) );
P( E, A, B, C, D, R(21) );
P( D, E, A, B, C, R(22) );
P( C, D, E, A, B, R(23) );
P( B, C, D, E, A, R(24) );
P( A, B, C, D, E, R(25) );
P( E, A, B, C, D, R(26) );
P( D, E, A, B, C, R(27) );
P( C, D, E, A, B, R(28) );
P( B, C, D, E, A, R(29) );
P( A, B, C, D, E, R(30) );
P( E, A, B, C, D, R(31) );
P( D, E, A, B, C, R(32) );
P( C, D, E, A, B, R(33) );
P( B, C, D, E, A, R(34) );
P( A, B, C, D, E, R(35) );
P( E, A, B, C, D, R(36) );
P( D, E, A, B, C, R(37) );
P( C, D, E, A, B, R(38) );
P( B, C, D, E, A, R(39) );
P( local.A, local.B, local.C, local.D, local.E, R(20) );
P( local.E, local.A, local.B, local.C, local.D, R(21) );
P( local.D, local.E, local.A, local.B, local.C, R(22) );
P( local.C, local.D, local.E, local.A, local.B, R(23) );
P( local.B, local.C, local.D, local.E, local.A, R(24) );
P( local.A, local.B, local.C, local.D, local.E, R(25) );
P( local.E, local.A, local.B, local.C, local.D, R(26) );
P( local.D, local.E, local.A, local.B, local.C, R(27) );
P( local.C, local.D, local.E, local.A, local.B, R(28) );
P( local.B, local.C, local.D, local.E, local.A, R(29) );
P( local.A, local.B, local.C, local.D, local.E, R(30) );
P( local.E, local.A, local.B, local.C, local.D, R(31) );
P( local.D, local.E, local.A, local.B, local.C, R(32) );
P( local.C, local.D, local.E, local.A, local.B, R(33) );
P( local.B, local.C, local.D, local.E, local.A, R(34) );
P( local.A, local.B, local.C, local.D, local.E, R(35) );
P( local.E, local.A, local.B, local.C, local.D, R(36) );
P( local.D, local.E, local.A, local.B, local.C, R(37) );
P( local.C, local.D, local.E, local.A, local.B, R(38) );
P( local.B, local.C, local.D, local.E, local.A, R(39) );
#undef K
#undef F
@@ -173,26 +176,26 @@ static void esp_sha1_software_process( esp_sha1_context *ctx, const unsigned cha
#define F(x,y,z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P( A, B, C, D, E, R(40) );
P( E, A, B, C, D, R(41) );
P( D, E, A, B, C, R(42) );
P( C, D, E, A, B, R(43) );
P( B, C, D, E, A, R(44) );
P( A, B, C, D, E, R(45) );
P( E, A, B, C, D, R(46) );
P( D, E, A, B, C, R(47) );
P( C, D, E, A, B, R(48) );
P( B, C, D, E, A, R(49) );
P( A, B, C, D, E, R(50) );
P( E, A, B, C, D, R(51) );
P( D, E, A, B, C, R(52) );
P( C, D, E, A, B, R(53) );
P( B, C, D, E, A, R(54) );
P( A, B, C, D, E, R(55) );
P( E, A, B, C, D, R(56) );
P( D, E, A, B, C, R(57) );
P( C, D, E, A, B, R(58) );
P( B, C, D, E, A, R(59) );
P( local.A, local.B, local.C, local.D, local.E, R(40) );
P( local.E, local.A, local.B, local.C, local.D, R(41) );
P( local.D, local.E, local.A, local.B, local.C, R(42) );
P( local.C, local.D, local.E, local.A, local.B, R(43) );
P( local.B, local.C, local.D, local.E, local.A, R(44) );
P( local.A, local.B, local.C, local.D, local.E, R(45) );
P( local.E, local.A, local.B, local.C, local.D, R(46) );
P( local.D, local.E, local.A, local.B, local.C, R(47) );
P( local.C, local.D, local.E, local.A, local.B, R(48) );
P( local.B, local.C, local.D, local.E, local.A, R(49) );
P( local.A, local.B, local.C, local.D, local.E, R(50) );
P( local.E, local.A, local.B, local.C, local.D, R(51) );
P( local.D, local.E, local.A, local.B, local.C, R(52) );
P( local.C, local.D, local.E, local.A, local.B, R(53) );
P( local.B, local.C, local.D, local.E, local.A, R(54) );
P( local.A, local.B, local.C, local.D, local.E, R(55) );
P( local.E, local.A, local.B, local.C, local.D, R(56) );
P( local.D, local.E, local.A, local.B, local.C, R(57) );
P( local.C, local.D, local.E, local.A, local.B, R(58) );
P( local.B, local.C, local.D, local.E, local.A, R(59) );
#undef K
#undef F
@@ -200,35 +203,38 @@ static void esp_sha1_software_process( esp_sha1_context *ctx, const unsigned cha
#define F(x,y,z) (x ^ y ^ z)
#define K 0xCA62C1D6
P( A, B, C, D, E, R(60) );
P( E, A, B, C, D, R(61) );
P( D, E, A, B, C, R(62) );
P( C, D, E, A, B, R(63) );
P( B, C, D, E, A, R(64) );
P( A, B, C, D, E, R(65) );
P( E, A, B, C, D, R(66) );
P( D, E, A, B, C, R(67) );
P( C, D, E, A, B, R(68) );
P( B, C, D, E, A, R(69) );
P( A, B, C, D, E, R(70) );
P( E, A, B, C, D, R(71) );
P( D, E, A, B, C, R(72) );
P( C, D, E, A, B, R(73) );
P( B, C, D, E, A, R(74) );
P( A, B, C, D, E, R(75) );
P( E, A, B, C, D, R(76) );
P( D, E, A, B, C, R(77) );
P( C, D, E, A, B, R(78) );
P( B, C, D, E, A, R(79) );
P( local.A, local.B, local.C, local.D, local.E, R(60) );
P( local.E, local.A, local.B, local.C, local.D, R(61) );
P( local.D, local.E, local.A, local.B, local.C, R(62) );
P( local.C, local.D, local.E, local.A, local.B, R(63) );
P( local.B, local.C, local.D, local.E, local.A, R(64) );
P( local.A, local.B, local.C, local.D, local.E, R(65) );
P( local.E, local.A, local.B, local.C, local.D, R(66) );
P( local.D, local.E, local.A, local.B, local.C, R(67) );
P( local.C, local.D, local.E, local.A, local.B, R(68) );
P( local.B, local.C, local.D, local.E, local.A, R(69) );
P( local.A, local.B, local.C, local.D, local.E, R(70) );
P( local.E, local.A, local.B, local.C, local.D, R(71) );
P( local.D, local.E, local.A, local.B, local.C, R(72) );
P( local.C, local.D, local.E, local.A, local.B, R(73) );
P( local.B, local.C, local.D, local.E, local.A, R(74) );
P( local.A, local.B, local.C, local.D, local.E, R(75) );
P( local.E, local.A, local.B, local.C, local.D, R(76) );
P( local.D, local.E, local.A, local.B, local.C, R(77) );
P( local.C, local.D, local.E, local.A, local.B, R(78) );
P( local.B, local.C, local.D, local.E, local.A, R(79) );
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[0] += local.A;
ctx->state[1] += local.B;
ctx->state[2] += local.C;
ctx->state[3] += local.D;
ctx->state[4] += local.E;
/* Zeroise buffers and variables to clear sensitive data from memory. */
mbedtls_platform_zeroize(&local, sizeof(local));
}
static int esp_internal_sha1_parallel_engine_process( esp_sha1_context *ctx, const unsigned char data[64], bool read_digest )
@@ -409,6 +415,8 @@ psa_status_t esp_sha1_driver_finish(
return PSA_SUCCESS;
}
psa_status_t esp_sha1_driver_abort(esp_sha1_context *ctx);
psa_status_t esp_sha1_driver_compute(
esp_sha1_context *ctx,
const uint8_t *input,
@@ -423,21 +431,25 @@ psa_status_t esp_sha1_driver_compute(
int ret = esp_sha1_starts(ctx);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha1_update(ctx, input, input_length);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha1_finish(ctx, hash);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
*hash_length = PSA_HASH_LENGTH(PSA_ALG_SHA_1);
return PSA_SUCCESS;
hw_fail:
esp_sha1_driver_abort(ctx);
return PSA_ERROR_HARDWARE_FAILURE;
}
psa_status_t esp_sha1_driver_abort(esp_sha1_context *ctx)
@@ -452,6 +464,6 @@ psa_status_t esp_sha1_driver_abort(esp_sha1_context *ctx)
ctx->operation_mode = ESP_SHA_MODE_SOFTWARE;
}
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
memset(ctx, 0, sizeof(esp_sha1_context));
mbedtls_platform_zeroize(ctx, sizeof(esp_sha1_context));
return PSA_SUCCESS;
}

View File

@@ -5,7 +5,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2025-2026 Espressif Systems (Shanghai) CO LTD
*/
#include <string.h>
@@ -14,6 +14,7 @@
#include "sha/sha_parallel_engine.h"
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "mbedtls/platform_util.h"
/*
* 32-bit integer manipulation macros (big endian)
@@ -122,71 +123,76 @@ static const uint32_t K[] = {
#define R(t) \
( \
W[t] = S1(W[t - 2]) + W[t - 7] + \
S0(W[t - 15]) + W[t - 16] \
local.W[t] = S1(local.W[t - 2]) + local.W[t - 7] + \
S0(local.W[t - 15]) + local.W[t - 16] \
)
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
local.temp1 = h + S3(e) + F1(e,f,g) + (K) + (x); \
local.temp2 = S2(a) + F0(a,b,c); \
d += local.temp1; h = local.temp1 + local.temp2; \
}
static void esp_sha256_software_process(esp_sha256_context *ctx, const unsigned char data[64])
{
uint32_t temp1, temp2, W[64] = {0};
uint32_t A[8] = {0};
struct {
uint32_t temp1, temp2, W[64];
uint32_t A[8];
} local;
unsigned int i = 0;
for ( i = 0; i < 8; i++ ) {
A[i] = ctx->state[i];
local.A[i] = ctx->state[i];
}
#if defined(MBEDTLS_SHA256_SMALLER)
for ( i = 0; i < 64; i++ ) {
if ( i < 16 ) {
GET_UINT32_BE( W[i], data, 4 * i );
GET_UINT32_BE( local.W[i], data, 4 * i );
} else {
R( i );
}
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
local.temp1 = local.A[7]; local.A[7] = local.A[6]; local.A[6] = local.A[5]; local.A[5] = local.A[4]; local.A[4] = local.A[3];
local.A[3] = local.A[2]; local.A[2] = local.A[1]; local.A[1] = local.A[0]; local.A[0] = local.temp1;
}
#else /* MBEDTLS_SHA256_SMALLER */
for ( i = 0; i < 16; i++ ) {
GET_UINT32_BE( W[i], data, 4 * i );
GET_UINT32_BE( local.W[i], data, 4 * i );
}
for ( i = 0; i < 16; i += 8 ) {
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7] );
P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i + 0], K[i + 0] );
P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.W[i + 1], K[i + 1] );
P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.W[i + 2], K[i + 2] );
P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.W[i + 3], K[i + 3] );
P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.W[i + 4], K[i + 4] );
P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.W[i + 5], K[i + 5] );
P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.W[i + 6], K[i + 6] );
P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.W[i + 7], K[i + 7] );
}
for ( i = 16; i < 64; i += 8 ) {
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0] );
P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1] );
P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2] );
P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3] );
P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4] );
P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5] );
P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6] );
P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7] );
P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], R(i + 0), K[i + 0] );
P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], R(i + 1), K[i + 1] );
P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], R(i + 2), K[i + 2] );
P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], R(i + 3), K[i + 3] );
P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], R(i + 4), K[i + 4] );
P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], R(i + 5), K[i + 5] );
P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], R(i + 6), K[i + 6] );
P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], R(i + 7), K[i + 7] );
}
#endif /* MBEDTLS_SHA256_SMALLER */
for ( i = 0; i < 8; i++ ) {
ctx->state[i] += A[i];
ctx->state[i] += local.A[i];
}
/* Zeroise buffers and variables to clear sensitive data from memory. */
mbedtls_platform_zeroize(&local, sizeof(local));
}
static int esp_internal_sha256_parallel_engine_process(esp_sha256_context *ctx, const unsigned char data[64], bool read_digest)
{
@@ -319,7 +325,18 @@ static int esp_sha256_finish(esp_sha256_context *ctx, unsigned char *output)
PUT_UINT32_BE( ctx->state[4], output, 16 );
PUT_UINT32_BE( ctx->state[5], output, 20 );
PUT_UINT32_BE( ctx->state[6], output, 24 );
#if SOC_SHA_SUPPORT_SHA224
/* SHA-224 output is 28 bytes (7 state words); only SHA-256 emits the 8th
* word. Writing state[7] for SHA-224 overflows a contract-valid 28-byte
* output buffer by 4 bytes. Mirrors the mbedtls reference !is224 guard and
* the esp_sha512_finish SHA2_512 guard in this same engine. */
if ( ctx->mode != SHA2_224 ) {
PUT_UINT32_BE( ctx->state[7], output, 28 );
}
#else
PUT_UINT32_BE( ctx->state[7], output, 28 );
#endif /* SOC_SHA_SUPPORT_SHA224 */
out:
@@ -346,6 +363,8 @@ psa_status_t esp_sha256_driver_update(
return PSA_SUCCESS;
}
psa_status_t esp_sha256_driver_abort(esp_sha256_context *ctx);
psa_status_t esp_sha256_driver_compute(
esp_sha256_context *ctx,
psa_algorithm_t alg,
@@ -375,20 +394,24 @@ psa_status_t esp_sha256_driver_compute(
#endif // SOC_SHA_SUPPORT_SHA224
int ret = esp_sha256_starts(ctx, mode);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha256_update(ctx, input, input_length);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha256_finish(ctx, hash);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
*hash_length = PSA_HASH_LENGTH(alg);
return PSA_SUCCESS;
hw_fail:
esp_sha256_driver_abort(ctx);
return PSA_ERROR_HARDWARE_FAILURE;
}
psa_status_t esp_sha256_driver_finish(
@@ -430,6 +453,6 @@ psa_status_t esp_sha256_driver_abort(esp_sha256_context *ctx)
esp_sha_unlock_engine(SHA2_256);
ctx->operation_mode = ESP_SHA_MODE_SOFTWARE;
}
memset(ctx, 0, sizeof(esp_sha256_context));
mbedtls_platform_zeroize(ctx, sizeof(esp_sha256_context));
return PSA_SUCCESS;
}

View File

@@ -14,6 +14,7 @@
#include "sha/sha_parallel_engine.h"
#include "esp_err.h"
#include "soc/soc_caps.h"
#include "mbedtls/platform_util.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
@@ -145,8 +146,10 @@ static const uint64_t K[80] = {
static void esp_sha512_software_process(esp_sha512_context *ctx, const unsigned char data[128])
{
int i;
uint64_t temp1, temp2, W[80];
uint64_t A, B, C, D, E, F, G, H;
struct {
uint64_t temp1, temp2, W[80];
uint64_t A[8];
} local;
#define SHR(x,n) (x >> n)
#define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
@@ -162,49 +165,42 @@ static void esp_sha512_software_process(esp_sha512_context *ctx, const unsigned
#define P(a,b,c,d,e,f,g,h,x,K) \
{ \
temp1 = h + S3(e) + F1(e,f,g) + K + x; \
temp2 = S2(a) + F0(a,b,c); \
d += temp1; h = temp1 + temp2; \
local.temp1 = h + S3(e) + F1(e,f,g) + (K) + (x); \
local.temp2 = S2(a) + F0(a,b,c); \
d += local.temp1; h = local.temp1 + local.temp2; \
}
for ( i = 0; i < 16; i++ ) {
GET_UINT64_BE( W[i], data, i << 3 );
GET_UINT64_BE( local.W[i], data, i << 3 );
}
for ( ; i < 80; i++ ) {
W[i] = S1(W[i - 2]) + W[i - 7] +
S0(W[i - 15]) + W[i - 16];
local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
S0(local.W[i - 15]) + local.W[i - 16];
}
for (i = 0; i < 8; i++) {
local.A[i] = ctx->state[i];
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
F = ctx->state[5];
G = ctx->state[6];
H = ctx->state[7];
i = 0;
do {
P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
} while ( i < 80 );
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
ctx->state[5] += F;
ctx->state[6] += G;
ctx->state[7] += H;
for (i = 0; i < 8; i++) {
ctx->state[i] += local.A[i];
}
mbedtls_platform_zeroize(&local, sizeof(local));
}
static int esp_internal_sha512_parallel_engine_process( esp_sha512_context *ctx, const unsigned char data[128], bool read_digest )
@@ -237,6 +233,7 @@ int esp_internal_sha512_process( esp_sha512_context *ctx, const unsigned char da
{
return esp_internal_sha512_parallel_engine_process(ctx, data, true);
}
static int esp_sha512_update(esp_sha512_context *ctx, const unsigned char *input,
size_t ilen)
{
@@ -349,6 +346,8 @@ out:
return ret;
}
psa_status_t esp_sha512_driver_abort(esp_sha512_context *ctx);
psa_status_t esp_sha512_driver_compute(
esp_sha512_context *ctx,
psa_algorithm_t alg,
@@ -370,20 +369,24 @@ psa_status_t esp_sha512_driver_compute(
int mode = (alg == PSA_ALG_SHA_384) ? SHA2_384 : SHA2_512;
int ret = esp_sha512_starts(ctx, mode);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha512_update(ctx, input, input_length);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
ret = esp_sha512_finish(ctx, hash);
if (ret != ESP_OK) {
return PSA_ERROR_HARDWARE_FAILURE;
goto hw_fail;
}
*hash_length = PSA_HASH_LENGTH(alg);
return PSA_SUCCESS;
hw_fail:
esp_sha512_driver_abort(ctx);
return PSA_ERROR_HARDWARE_FAILURE;
}
psa_status_t esp_sha512_driver_update(
@@ -442,7 +445,7 @@ psa_status_t esp_sha512_driver_abort(esp_sha512_context *ctx)
esp_sha_unlock_engine(sha_type(ctx));
ctx->operation_mode = ESP_SHA_MODE_SOFTWARE;
}
memset(ctx, 0, sizeof(esp_sha512_context));
mbedtls_platform_zeroize(ctx, sizeof(esp_sha512_context));
return PSA_SUCCESS;
}

View File

@@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "mbedtls/esp_config.h"
#include "psa_crypto_driver_esp_sha.h"
@@ -46,8 +47,11 @@ static int esp_sha_driver_check_supported_algorithm(psa_algorithm_t alg) {
return ESP_ERR_NOT_SUPPORTED;
}
static int esp_sha_validate_args(psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size) {
if (!hash) {
static int esp_sha_validate_args(psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, const size_t *hash_length) {
if (!hash || !hash_length) {
return ESP_ERR_INVALID_ARG;
}
if (input == NULL && input_length != 0) {
return ESP_ERR_INVALID_ARG;
}
@@ -72,7 +76,7 @@ psa_status_t esp_sha_hash_compute(
return PSA_ERROR_NOT_SUPPORTED;
}
ret = esp_sha_validate_args(alg, input, input_length, hash, hash_size);
ret = esp_sha_validate_args(alg, input, input_length, hash, hash_size, hash_length);
if (ret == ESP_ERR_INVALID_ARG) {
return PSA_ERROR_INVALID_ARGUMENT;
} else if (ret == ESP_ERR_INVALID_SIZE) {
@@ -87,7 +91,7 @@ psa_status_t esp_sha_hash_compute(
case PSA_ALG_SHA_1:
esp_sha1_context sha1_ctx = {0};
ret = esp_sha1_driver_compute(&sha1_ctx, input, input_length, hash, hash_size, &hash_length_calculated);
memset(&sha1_ctx, 0, sizeof(sha1_ctx));
mbedtls_platform_zeroize(&sha1_ctx, sizeof(sha1_ctx));
*hash_length = hash_length_calculated;
break;
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
@@ -98,7 +102,7 @@ psa_status_t esp_sha_hash_compute(
case PSA_ALG_SHA_256:
esp_sha256_context sha256_ctx = {0};
ret = esp_sha256_driver_compute(&sha256_ctx, alg, input, input_length, hash, hash_size, &hash_length_calculated);
memset(&sha256_ctx, 0, sizeof(sha256_ctx));
mbedtls_platform_zeroize(&sha256_ctx, sizeof(sha256_ctx));
*hash_length = hash_length_calculated;
break;
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_256
@@ -109,7 +113,7 @@ psa_status_t esp_sha_hash_compute(
case PSA_ALG_SHA_512:
esp_sha512_context sha512_ctx = {0};
ret = esp_sha512_driver_compute(&sha512_ctx, alg, input, input_length, hash, hash_size, &hash_length_calculated);
memset(&sha512_ctx, 0, sizeof(sha512_ctx));
mbedtls_platform_zeroize(&sha512_ctx, sizeof(sha512_ctx));
*hash_length = hash_length_calculated;
break;
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
@@ -128,6 +132,9 @@ psa_status_t esp_sha_hash_setup(esp_sha_hash_operation_t *operation, psa_algorit
if (!operation) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (operation->sha_ctx != NULL) {
return PSA_ERROR_BAD_STATE;
}
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (alg == PSA_ALG_SHA_1) {
esp_sha1_context *sha1_ctx = heap_caps_malloc(sizeof(esp_sha1_context), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
@@ -137,7 +144,12 @@ psa_status_t esp_sha_hash_setup(esp_sha_hash_operation_t *operation, psa_algorit
memset(sha1_ctx, 0, sizeof(esp_sha1_context));
operation->sha_ctx = sha1_ctx;
operation->sha_type = ESP_SHA_OPERATION_TYPE_SHA1;
return esp_sha1_starts(sha1_ctx);
int ret = esp_sha1_starts(sha1_ctx);
if (ret != ESP_OK) {
esp_sha_hash_abort(operation);
return PSA_ERROR_HARDWARE_FAILURE;
}
return PSA_SUCCESS;
} else
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
@@ -151,8 +163,8 @@ psa_status_t esp_sha_hash_setup(esp_sha_hash_operation_t *operation, psa_algorit
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memset(sha256_ctx, 0, sizeof(esp_sha256_context));
operation->sha_ctx = sha256_ctx;
int mode;
operation->sha_ctx = sha256_ctx;
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_224
operation->sha_type = (alg == PSA_ALG_SHA_224) ? ESP_SHA_OPERATION_TYPE_SHA224 : ESP_SHA_OPERATION_TYPE_SHA256;
mode = (alg == PSA_ALG_SHA_224) ? SHA2_224 : SHA2_256;
@@ -160,7 +172,12 @@ psa_status_t esp_sha_hash_setup(esp_sha_hash_operation_t *operation, psa_algorit
operation->sha_type = ESP_SHA_OPERATION_TYPE_SHA256;
mode = SHA2_256;
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_224
return esp_sha256_starts(sha256_ctx, mode);
int ret = esp_sha256_starts(sha256_ctx, mode);
if (ret != PSA_SUCCESS) {
esp_sha_hash_abort(operation);
return ret;
}
return PSA_SUCCESS;
} else
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_256 || MBEDTLS_PSA_ACCEL_ALG_SHA_224
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
@@ -174,17 +191,25 @@ psa_status_t esp_sha_hash_setup(esp_sha_hash_operation_t *operation, psa_algorit
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memset(sha512_ctx, 0, sizeof(esp_sha512_context));
operation->sha_ctx = sha512_ctx;
int mode = SHA2_512;
operation->sha_ctx = sha512_ctx;
operation->sha_type = ESP_SHA_OPERATION_TYPE_SHA512;
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_384
operation->sha_type = (alg == PSA_ALG_SHA_384) ? ESP_SHA_OPERATION_TYPE_SHA384 : ESP_SHA_OPERATION_TYPE_SHA512;
mode = (alg == PSA_ALG_SHA_384) ? SHA2_384 : SHA2_512;
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_384
return esp_sha512_starts(sha512_ctx, mode);
int ret = esp_sha512_starts(sha512_ctx, mode);
if (ret != PSA_SUCCESS) {
esp_sha_hash_abort(operation);
return ret;
}
return PSA_SUCCESS;
}
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
return PSA_ERROR_NOT_SUPPORTED;
if (PSA_ALG_IS_HASH(alg)) {
return PSA_ERROR_NOT_SUPPORTED;
}
return PSA_ERROR_INVALID_ARGUMENT;
}
psa_status_t esp_sha_hash_update(
@@ -192,9 +217,18 @@ psa_status_t esp_sha_hash_update(
const uint8_t *input,
size_t input_length)
{
if (!operation || !operation->sha_ctx || !input) {
if (!operation) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (operation->sha_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
if (input == NULL && input_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (input_length == 0) {
return PSA_SUCCESS;
}
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
esp_sha1_context *ctx = (esp_sha1_context *)operation->sha_ctx;
@@ -213,7 +247,7 @@ psa_status_t esp_sha_hash_update(
return esp_sha512_driver_update(ctx, input, input_length);
}
#endif // (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
return PSA_ERROR_NOT_SUPPORTED;
return PSA_ERROR_BAD_STATE;
}
psa_status_t esp_sha_hash_finish(
@@ -226,135 +260,163 @@ psa_status_t esp_sha_hash_finish(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (operation->sha_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
/* Defense in depth: gate buffer sizing in the dispatcher so we don't rely
* solely on every per-algorithm sub-driver to enforce it. */
size_t expected_size = 0;
switch (operation->sha_type) {
case ESP_SHA_OPERATION_TYPE_SHA1: expected_size = PSA_HASH_LENGTH(PSA_ALG_SHA_1); break;
case ESP_SHA_OPERATION_TYPE_SHA224: expected_size = PSA_HASH_LENGTH(PSA_ALG_SHA_224); break;
case ESP_SHA_OPERATION_TYPE_SHA256: expected_size = PSA_HASH_LENGTH(PSA_ALG_SHA_256); break;
case ESP_SHA_OPERATION_TYPE_SHA384: expected_size = PSA_HASH_LENGTH(PSA_ALG_SHA_384); break;
case ESP_SHA_OPERATION_TYPE_SHA512: expected_size = PSA_HASH_LENGTH(PSA_ALG_SHA_512); break;
default: return PSA_ERROR_BAD_STATE;
}
if (hash_size < expected_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
esp_sha1_context *ctx = (esp_sha1_context *)operation->sha_ctx;
int ret = esp_sha1_driver_finish(ctx, hash, hash_size, hash_length);
mbedtls_platform_zeroize(ctx, sizeof(esp_sha1_context));
free(ctx); // Free the context after use
operation->sha_ctx = NULL;
return ret;
return esp_sha1_driver_finish((esp_sha1_context *)operation->sha_ctx,
hash, hash_size, hash_length);
} else
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA256 ||
operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
esp_sha256_context *ctx = (esp_sha256_context *)operation->sha_ctx;
int ret = esp_sha256_driver_finish(ctx, hash, hash_size, hash_length, operation->sha_type);
mbedtls_platform_zeroize(ctx, sizeof(esp_sha256_context));
free(ctx); // Free the context after use
operation->sha_ctx = NULL;
return ret;
return esp_sha256_driver_finish((esp_sha256_context *)operation->sha_ctx,
hash, hash_size, hash_length,
operation->sha_type);
} else
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
#if (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA384 ||
operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) {
esp_sha512_context *ctx = (esp_sha512_context *)operation->sha_ctx;
int ret = esp_sha512_driver_finish(ctx, hash, hash_size, hash_length, operation->sha_type);
mbedtls_platform_zeroize(ctx, sizeof(esp_sha512_context));
free(ctx); // Free the context after use
operation->sha_ctx = NULL;
return ret;
return esp_sha512_driver_finish((esp_sha512_context *)operation->sha_ctx,
hash, hash_size, hash_length,
operation->sha_type);
}
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
return PSA_ERROR_NOT_SUPPORTED;
return PSA_ERROR_BAD_STATE;
}
psa_status_t esp_sha_hash_abort(esp_sha_hash_operation_t *operation)
{
if (!operation) {
return PSA_ERROR_INVALID_ARGUMENT;
}
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
esp_sha1_context *ctx = (esp_sha1_context *)operation->sha_ctx;
if (ctx) {
esp_sha1_driver_abort(ctx);
}
} else
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA256 ||
operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
esp_sha256_context *ctx = (esp_sha256_context *)operation->sha_ctx;
if (ctx) {
esp_sha256_driver_abort(ctx);
}
} else
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
#if (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA384 ||
operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) {
esp_sha512_context *ctx = (esp_sha512_context *)operation->sha_ctx;
if (ctx) {
esp_sha512_driver_abort(ctx);
}
} else
#endif // (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
{
return PSA_ERROR_NOT_SUPPORTED;
}
if (operation->sha_ctx) {
free(operation->sha_ctx);
operation->sha_ctx = NULL;
return PSA_SUCCESS;
}
return PSA_SUCCESS;
if (operation->sha_ctx == NULL) {
return PSA_SUCCESS;
}
bool bad_state = false;
switch (operation->sha_type) {
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
case ESP_SHA_OPERATION_TYPE_SHA1:
(void)esp_sha1_driver_abort((esp_sha1_context *)operation->sha_ctx);
break;
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
case ESP_SHA_OPERATION_TYPE_SHA256:
case ESP_SHA_OPERATION_TYPE_SHA224:
(void)esp_sha256_driver_abort((esp_sha256_context *)operation->sha_ctx);
break;
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
#if (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
case ESP_SHA_OPERATION_TYPE_SHA384:
case ESP_SHA_OPERATION_TYPE_SHA512:
(void)esp_sha512_driver_abort((esp_sha512_context *)operation->sha_ctx);
break;
#endif // (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
default:
bad_state = true;
break;
}
free(operation->sha_ctx);
operation->sha_ctx = NULL;
return bad_state ? PSA_ERROR_BAD_STATE : PSA_SUCCESS;
}
psa_status_t esp_sha_hash_clone(
const esp_sha_hash_operation_t *source_operation,
esp_sha_hash_operation_t *target_operation)
{
target_operation->sha_type = source_operation->sha_type;
if (!source_operation || !target_operation) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (source_operation->sha_ctx == NULL) {
return PSA_ERROR_BAD_STATE;
}
if (target_operation->sha_ctx != NULL) {
return PSA_ERROR_BAD_STATE;
}
void *ctx = NULL;
size_t ctx_size = 0;
psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (target_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
esp_sha1_context *sha1_ctx = heap_caps_malloc(sizeof(esp_sha1_context), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
if (!sha1_ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memset(sha1_ctx, 0, sizeof(esp_sha1_context));
target_operation->sha_ctx = sha1_ctx;
if (!target_operation->sha_ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
esp_sha1_driver_clone(source_operation->sha_ctx, target_operation->sha_ctx);
if (source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
ctx_size = sizeof(esp_sha1_context);
} else
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
if (target_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA256 ||
target_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
esp_sha256_context *sha256_ctx = heap_caps_malloc(sizeof(esp_sha256_context), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
if (!sha256_ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memset(sha256_ctx, 0, sizeof(esp_sha256_context));
target_operation->sha_ctx = sha256_ctx;
if (!target_operation->sha_ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
esp_sha256_driver_clone(source_operation->sha_ctx, target_operation->sha_ctx);
if (source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA256 ||
source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
ctx_size = sizeof(esp_sha256_context);
} else
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
#if (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
if (target_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA384 ||
target_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) {
esp_sha512_context *sha512_ctx = heap_caps_malloc(sizeof(esp_sha512_context), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
if (!sha512_ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memset(sha512_ctx, 0, sizeof(esp_sha512_context));
target_operation->sha_ctx = sha512_ctx;
if (!target_operation->sha_ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
esp_sha512_driver_clone(source_operation->sha_ctx, target_operation->sha_ctx);
if (source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA384 ||
source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) {
ctx_size = sizeof(esp_sha512_context);
} else
#endif // (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
{
return PSA_ERROR_NOT_SUPPORTED;
}
ctx = heap_caps_malloc(ctx_size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
if (!ctx) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
memset(ctx, 0, ctx_size);
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
status = esp_sha1_driver_clone(source_operation->sha_ctx, ctx);
} else
#endif // MBEDTLS_PSA_ACCEL_ALG_SHA_1
#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
if (source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA256 ||
source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA224) {
status = esp_sha256_driver_clone(source_operation->sha_ctx, ctx);
} else
#endif // defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
#if (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
if (source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA384 ||
source_operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA512) {
status = esp_sha512_driver_clone(source_operation->sha_ctx, ctx);
} else
#endif // (defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) || defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))
{
status = PSA_ERROR_NOT_SUPPORTED;
}
if (status != PSA_SUCCESS) {
mbedtls_platform_zeroize(ctx, ctx_size);
free(ctx);
return status;
}
target_operation->sha_ctx = ctx;
target_operation->sha_type = source_operation->sha_type;
return PSA_SUCCESS;
}

View File

@@ -37,9 +37,11 @@ typedef struct {
* @brief Structure to store opaque HMAC operation context.
*/
typedef struct {
psa_algorithm_t alg; /**< MAC algorithm (PSA_ALG_HMAC(PSA_ALG_SHA_256)); 0 = fresh / aborted. */
const uint8_t *key_buffer; /**< Pointer to the per-source storage struct in key slot */
uint8_t hmac[ESP_HMAC_RESULT_SIZE]; /**< Buffer to store the HMAC result */
bool is_persistent; /**< Cached persistence flag for use in update */
bool computed; /**< True once update has produced a MAC into hmac[]; gates double-update. */
} esp_hmac_opaque_operation_t;
#endif /* ESP_HMAC_OPAQUE_DRIVER_ENABLED */

View File

@@ -10,7 +10,7 @@
#include "soc/soc_caps.h"
#include "psa/crypto_driver_common.h"
#include "psa_crypto_driver_esp_sha_contexts.h"
#include "esp_rom_md5.h"
#include "psa_crypto_driver_esp_md5_contexts.h"
#ifdef __cplusplus
extern "C" {
@@ -21,7 +21,7 @@ typedef struct {
psa_algorithm_t alg;
uint8_t *opad; // Dynamically allocated to save space
union {
md5_context_t md5_ctx;
esp_md5_hash_operation_t md5_ctx;
esp_sha_hash_operation_t esp_sha_ctx;
};
} esp_hmac_transparent_operation_t;

View File

@@ -8,7 +8,7 @@
#include "esp_types.h"
#include "psa/crypto.h"
#include "esp_rom_md5.h"
#include "psa_crypto_driver_esp_md5_contexts.h"
#ifdef __cplusplus
extern "C" {
@@ -27,25 +27,25 @@ psa_status_t esp_md5_hash_compute(psa_algorithm_t alg,
size_t hash_size,
size_t *hash_length);
psa_status_t esp_md5_hash_setup(md5_context_t *operation,
psa_status_t esp_md5_hash_setup(esp_md5_hash_operation_t *operation,
psa_algorithm_t alg);
psa_status_t esp_md5_hash_update(
md5_context_t *operation,
esp_md5_hash_operation_t *operation,
const uint8_t *input,
size_t input_length );
psa_status_t esp_md5_hash_finish(
md5_context_t *operation,
esp_md5_hash_operation_t *operation,
uint8_t *hash,
size_t hash_size,
size_t *hash_length);
psa_status_t esp_md5_hash_abort(md5_context_t *operation);
psa_status_t esp_md5_hash_abort(esp_md5_hash_operation_t *operation);
psa_status_t esp_md5_hash_clone(
const md5_context_t *source_operation,
md5_context_t *target_operation);
const esp_md5_hash_operation_t *source_operation,
esp_md5_hash_operation_t *target_operation);
#ifdef __cplusplus
}

View File

@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "esp_rom_md5.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ESP MD5 driver operation context
*
* Wraps the ROM-supplied md5_context_t with an explicit is_active flag so
* the driver can detect setup-twice / update-without-setup / use-after-abort
* without relying on internal field values of the ROM struct.
*/
typedef struct {
md5_context_t md5_ctx;
bool is_active;
} esp_md5_hash_operation_t;
#ifdef __cplusplus
}
#endif

View File

@@ -41,6 +41,14 @@ static const uint8_t expected_hmac_sha256[] = {
0x50, 0xd7, 0x15, 0x78, 0x82, 0x10, 0xbe, 0xc6,
};
/* HMAC-SHA256(key_256, "") — MAC of an empty (zero-length) message. */
static const uint8_t expected_hmac_sha256_empty[] = {
0x46, 0x24, 0x76, 0xa8, 0x97, 0xdd, 0xfd, 0xbd,
0x40, 0xd1, 0x42, 0x0e, 0x08, 0xa5, 0xbc, 0xfe,
0xeb, 0x25, 0xc3, 0xe2, 0xad, 0xe6, 0xa0, 0xa9,
0x08, 0x3b, 0x32, 0x7b, 0x9e, 0xf9, 0xfc, 0xa1,
};
// Helper function to set up key attributes for HMAC
static void setup_hmac_key_attributes(psa_key_attributes_t *attributes,
psa_algorithm_t alg,
@@ -160,6 +168,27 @@ TEST_CASE("PSA HMAC SHA-256 test", "[psa_hmac]")
psa_reset_key_attributes(&attributes);
}
TEST_CASE("PSA HMAC SHA-256 empty input 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);
/* A zero-length input must produce HMAC(key, ""), not an error. */
test_hmac_compute_and_verify(key_id, alg, test_data, 0,
expected_hmac_sha256_empty,
sizeof(expected_hmac_sha256_empty));
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
}
TEST_CASE("PSA HMAC SHA-256 multipart test", "[psa_hmac]")
{
psa_status_t status;
@@ -257,4 +286,44 @@ TEST_CASE("PSA HMAC opaque driver compute and verify", "[psa_hmac][efuse_hmac_ke
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
}
TEST_CASE("PSA HMAC opaque driver empty input compute and verify", "[psa_hmac][efuse_hmac_key]")
{
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);
esp_hmac_opaque_key_t opaque_key = {
.efuse_key_id = HMAC_EFUSE_KEY_ID,
};
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, PSA_KEY_LIFETIME_ESP_HMAC_VOLATILE);
status = psa_import_key(&attributes, (uint8_t *)&opaque_key, sizeof(opaque_key), &key_id);
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
/*
* Zero-length input: update() no-ops, so finish() must compute HMAC(key, "")
* rather than returning PSA_ERROR_BAD_STATE.
*/
uint8_t mac[32] = {0};
size_t mac_length = 0;
status = psa_mac_compute(key_id, alg, test_data, 0,
mac, sizeof(mac), &mac_length);
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(sizeof(expected_hmac_sha256_empty), mac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_hmac_sha256_empty, mac, mac_length);
status = psa_mac_verify(key_id, alg, test_data, 0,
expected_hmac_sha256_empty, sizeof(expected_hmac_sha256_empty));
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
}
#endif /* ESP_HMAC_OPAQUE_DRIVER_ENABLED && CONFIG_MBEDTLS_TEST_HMAC_OPAQUE_EFUSE_KEY */

View File

@@ -221,6 +221,10 @@ Using an eFuse-based HMAC key:
// failure calculating HMAC
}
.. note::
The ESP-HMAC opaque PSA driver is backed by the one-shot hardware HMAC peripheral, which computes the MAC over the whole message in a single operation and cannot save or restore intermediate state between calls. Multipart streaming is therefore not supported: supply the entire message in a single :cpp:func:`psa_mac_compute` call (as shown above) or in a single multipart update. A second non-empty update on the same operation returns ``PSA_ERROR_BAD_STATE``; the operation fails closed and never produces a MAC computed over only part of the message.
API Reference
-------------

View File

@@ -221,6 +221,10 @@ HMAC 的第三种应用场景是将其作为密钥,启用软禁用的 JTAG 接
// 计算 HMAC 失败
}
.. note::
ESP-HMAC 不透明 PSA 驱动基于单次硬件 HMAC 外设实现,该外设可以通过单次运算为完整消息计算消息认证码 (MAC),但无法在多次调用之间保存或恢复运算中间状态。因此,该驱动不支持多分段流式运算:须在单次 :cpp:func:`psa_mac_compute` 调用中传入完整消息(如上所示),或仅执行一次多分段更新操作。若对同一 MAC 运算操作发起第二次非空更新,会返回 ``PSA_ERROR_BAD_STATE`` 错误,且该操作会直接失败并关闭,不会基于部分消息生成对应的 MAC 结果。
API 参考
-------------