fix(mbedtls/port): add additional hardening for PSA drivers

This commit is contained in:
Ashish Sharma
2026-05-26 10:36:07 +08:00
parent b5d16d86dc
commit 33cb603e02
16 changed files with 437 additions and 288 deletions

View File

@@ -104,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;
}
@@ -274,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)) {
@@ -384,15 +405,15 @@ 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];
mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);
@@ -416,7 +437,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data
/* Gate *data_len on the bad flag so it does not leak padding validity. */
*data_len = mbedtls_ct_if(bad, 0, pad_idx);
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
*invalid_padding = bad;
}
psa_status_t esp_aes_cipher_finish(
@@ -428,7 +449,7 @@ psa_status_t esp_aes_cipher_finish(
int ret = -1;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
uint8_t temp_output_buffer[ESP_MBEDTLS_AES_MAX_BLOCK_LENGTH] = { 0 };
int invalid_padding = 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;
@@ -480,13 +501,8 @@ psa_status_t esp_aes_cipher_finish(
}
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 == MBEDTLS_ERR_CIPHER_INVALID_PADDING) {
invalid_padding = 1;
} else if (ret != 0) {
status = mbedtls_to_psa_error(ret);
goto exit;
}
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;
}
@@ -530,7 +546,7 @@ psa_status_t esp_aes_cipher_finish(
memcpy(output, temp_output_buffer, output_size);
}
status = mbedtls_ct_error_if_else_0(mbedtls_ct_bool(invalid_padding),
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,

View File

@@ -55,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;

View File

@@ -1102,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;
}

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"
@@ -159,13 +160,12 @@ psa_status_t esp_cmac_update(esp_cmac_operation_t *esp_cmac_ctx, const uint8_t *
if (data == NULL && data_length != 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
if (data_length == 0) {
return PSA_SUCCESS;
}
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;
@@ -355,6 +355,8 @@ exit:
mbedtls_platform_zeroize(K2, sizeof(K2));
mbedtls_platform_zeroize(M_last, sizeof(M_last));
(void)esp_cmac_abort(esp_cmac_ctx);
return status;
}

View File

@@ -276,6 +276,84 @@ psa_status_t esp_hmac_setup_opaque(
return PSA_SUCCESS;
}
#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)
{
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 *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 (status != PSA_SUCCESS) {
return status;
}
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 (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;
}
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) {
@@ -293,74 +371,16 @@ psa_status_t esp_hmac_update_opaque(esp_hmac_opaque_operation_t *esp_hmac_ctx, c
return PSA_ERROR_BAD_STATE;
}
hmac_key_id_t hmac_key_id = 0;
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
const esp_key_mgr_key_recovery_info_t *key_recovery_info = NULL;
#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;
}
}
esp_err_t hmac_ret = esp_hmac_calculate(hmac_key_id, data, data_length, esp_hmac_ctx->hmac);
#if SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD
if (key_recovery_info) {
esp_key_mgr_deactivate_key(key_recovery_info->key_type);
}
#endif /* SOC_KEY_MANAGER_SUPPORTED && !ESP_TEE_BUILD */
if (hmac_ret == ESP_OK) {
esp_hmac_ctx->computed = true;
/*
* 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;
}
mbedtls_platform_zeroize(esp_hmac_ctx->hmac, sizeof(esp_hmac_ctx->hmac));
if (hmac_ret == ESP_ERR_INVALID_ARG) {
return PSA_ERROR_INVALID_ARGUMENT;
} else if (hmac_ret == ESP_FAIL) {
return PSA_ERROR_HARDWARE_FAILURE;
}
return PSA_ERROR_CORRUPTION_DETECTED;
return esp_hmac_opaque_calculate(esp_hmac_ctx, data, data_length);
}
psa_status_t esp_hmac_finish_opaque(
@@ -373,7 +393,7 @@ psa_status_t esp_hmac_finish_opaque(
return PSA_ERROR_INVALID_ARGUMENT;
}
if (esp_hmac_ctx->alg == 0 || !esp_hmac_ctx->computed) {
if (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
@@ -381,6 +401,20 @@ psa_status_t esp_hmac_finish_opaque(
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);
@@ -444,6 +478,10 @@ psa_status_t esp_hmac_verify_finish_opaque(
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) {

View File

@@ -221,13 +221,13 @@ psa_status_t esp_hmac_update_transparent(esp_hmac_transparent_operation_t *esp_h
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 (esp_hmac_ctx->alg == 0) {
return PSA_ERROR_BAD_STATE;
}
#if defined(ESP_MD5_DRIVER_ENABLED)
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg);
@@ -271,6 +271,7 @@ 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. */
@@ -342,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;
}

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

View File

@@ -563,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;
@@ -577,8 +579,11 @@ psa_status_t esp_rsa_ds_opaque_sign_hash_complete(
}
*signature_length = expected_signature_size;
status = PSA_SUCCESS;
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(

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;
@@ -515,7 +520,6 @@ psa_status_t esp_rsa_ds_pad_oaep_unpad(unsigned char *input,
if (bad != MBEDTLS_CT_FALSE) {
*olen = 0;
mbedtls_platform_zeroize(input, ilen);
mbedtls_platform_zeroize(lhash, sizeof(lhash));
return PSA_ERROR_INVALID_ARGUMENT;
}

View File

@@ -78,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) \
@@ -111,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
@@ -147,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
@@ -174,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
@@ -201,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 )

View File

@@ -123,76 +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];
}
mbedtls_platform_zeroize(W, sizeof(W));
mbedtls_platform_zeroize(A, sizeof(A));
temp1 = temp2 = 0;
(void)temp1; (void)temp2;
/* 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)
{
@@ -325,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:

View File

@@ -146,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)))
@@ -163,55 +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(W, sizeof(W));
A = B = C = D = E = F = G = H = 0;
temp1 = temp2 = 0;
(void)A; (void)B; (void)C; (void)D; (void)E; (void)F; (void)G; (void)H;
(void)temp1; (void)temp2;
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 )
@@ -244,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)
{

View File

@@ -226,6 +226,9 @@ psa_status_t esp_sha_hash_update(
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;
@@ -276,11 +279,6 @@ psa_status_t esp_sha_hash_finish(
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*hash_length = expected_size;
if (hash_size != 0) {
memset(hash, '!', hash_size);
}
#ifdef MBEDTLS_PSA_ACCEL_ALG_SHA_1
if (operation->sha_type == ESP_SHA_OPERATION_TYPE_SHA1) {
return esp_sha1_driver_finish((esp_sha1_context *)operation->sha_ctx,

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
-------------