mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(mbedtls): Enable h/w accel for CMAC and HMAC operations
- Refactor ESP-MAC drivers
This commit is contained in:
@@ -188,10 +188,6 @@ set(mbedtls_targets mbedtls mbedx509 tfpsacrypto builtin)
|
||||
|
||||
target_include_directories(tfpsacrypto PUBLIC "port/include")
|
||||
|
||||
if(CONFIG_MBEDTLS_HARDWARE_SHA OR CONFIG_MBEDTLS_HARDWARE_AES)
|
||||
target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include")
|
||||
endif()
|
||||
|
||||
message(STATUS "Setting up mbedtls configuration")
|
||||
foreach(target ${mbedtls_targets})
|
||||
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")
|
||||
@@ -361,8 +357,9 @@ if(CONFIG_SOC_SHA_SUPPORTED)
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_sha/psa_crypto_driver_esp_sha.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_sha/${SHA_PERIPHERAL_TYPE}/psa_crypto_driver_esp_sha256.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_sha/${SHA_PERIPHERAL_TYPE}/psa_crypto_driver_esp_sha512.c"
|
||||
|
||||
"${COMPONENT_DIR}/port/sha/esp_sha.c")
|
||||
"${COMPONENT_DIR}/port/sha/esp_sha.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac.c"
|
||||
)
|
||||
endif()
|
||||
target_sources(tfpsacrypto PRIVATE
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_sha/${SHA_PERIPHERAL_TYPE}/psa_crypto_driver_esp_sha1.c"
|
||||
@@ -411,9 +408,10 @@ if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES)
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c"
|
||||
)
|
||||
if(CONFIG_MBEDTLS_HARDWARE_SHA)
|
||||
if(CONFIG_MBEDTLS_CMAC_C)
|
||||
target_compile_definitions(tfpsacrypto PRIVATE ESP_CMAC_DRIVER_ENABLED)
|
||||
target_sources(tfpsacrypto PRIVATE
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_cmac.c"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -28,6 +28,9 @@ set(GEN_FILES OFF CACHE BOOL "mbedtls: use pre-generated source files")
|
||||
# Needed to for include_next includes to work from within mbedtls
|
||||
include_directories("${COMPONENT_DIR}/port/include")
|
||||
|
||||
# Add PSA driver include directory globally for mbedtls targets
|
||||
include_directories("${COMPONENT_DIR}/port/psa_driver/include")
|
||||
|
||||
# Import mbedtls library targets
|
||||
add_subdirectory(mbedtls)
|
||||
|
||||
@@ -82,9 +85,10 @@ if(CONFIG_SOC_AES_SUPPORTED)
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_aes_gcm.c"
|
||||
)
|
||||
if(CONFIG_MBEDTLS_HARDWARE_SHA)
|
||||
if(CONFIG_MBEDTLS_CMAC_C)
|
||||
target_compile_definitions(tfpsacrypto PRIVATE ESP_CMAC_DRIVER_ENABLED)
|
||||
target_sources(tfpsacrypto PRIVATE
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_aes/psa_crypto_driver_esp_cmac.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_cmac.c"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -99,7 +103,9 @@ if(CONFIG_SOC_SHA_SUPPORTED)
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha256.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_sha/core/psa_crypto_driver_esp_sha512.c"
|
||||
"${COMPONENT_DIR}/port/sha/core/sha.c"
|
||||
"${COMPONENT_DIR}/port/sha/esp_sha.c")
|
||||
"${COMPONENT_DIR}/port/sha/esp_sha.c"
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_mac/psa_crypto_driver_esp_hmac.c"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_MBEDTLS_ROM_MD5)
|
||||
|
||||
Submodule components/mbedtls/mbedtls updated: 1d21564333...5baeb30f6f
@@ -15,7 +15,6 @@
|
||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
#include <string.h>
|
||||
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
|
||||
#include "aes/esp_aes.h"
|
||||
#include "aes/esp_aes_gcm.h"
|
||||
#include "esp_aes_internal.h"
|
||||
|
||||
@@ -14,7 +14,99 @@
|
||||
#include "constant_time_internal.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static psa_status_t esp_crypto_aes_ecb_update(
|
||||
static const char *TAG = "psa_crypto_driver_esp_aes";
|
||||
|
||||
static psa_status_t esp_aes_cipher_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg, psa_encrypt_or_decrypt_t mode)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
|
||||
if (!PSA_ALG_IS_CIPHER(alg)) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (alg) {
|
||||
case PSA_ALG_ECB_NO_PADDING:
|
||||
case PSA_ALG_CBC_NO_PADDING:
|
||||
case PSA_ALG_CBC_PKCS7:
|
||||
case PSA_ALG_CTR:
|
||||
case PSA_ALG_XTS:
|
||||
case PSA_ALG_CFB:
|
||||
case PSA_ALG_OFB:
|
||||
break;
|
||||
default:
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
esp_aes_context *ctx = (esp_aes_context *) malloc(sizeof(esp_aes_context));
|
||||
if (ctx == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
esp_aes_init(ctx);
|
||||
|
||||
status = mbedtls_to_psa_error(esp_aes_setkey(ctx, key_buffer, key_buffer_size * 8));
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
free(ctx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
esp_aes_driver_ctx->aes_alg = alg;
|
||||
esp_aes_driver_ctx->mode = mode;
|
||||
esp_aes_driver_ctx->esp_aes_ctx = (void *) ctx;
|
||||
esp_aes_driver_ctx->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 : PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES));
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_encrypt_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
return esp_aes_cipher_setup(esp_aes_driver_ctx, attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, PSA_CRYPTO_DRIVER_ENCRYPT);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_decrypt_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
return esp_aes_cipher_setup(esp_aes_driver_ctx, attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, PSA_CRYPTO_DRIVER_DECRYPT);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_set_iv(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *iv,
|
||||
size_t iv_length)
|
||||
{
|
||||
if (iv_length != PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, esp_aes_driver_ctx->aes_alg)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
memcpy(esp_aes_driver_ctx->iv, iv, iv_length);
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t esp_aes_ecb_update(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *input, size_t input_length,
|
||||
uint8_t *output, size_t *output_length)
|
||||
@@ -74,7 +166,7 @@ exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t esp_crypto_aes_cbc_update(
|
||||
static psa_status_t esp_aes_cbc_update(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *input, size_t input_length,
|
||||
uint8_t *output, size_t output_size,
|
||||
@@ -166,10 +258,12 @@ exit:
|
||||
return mbedtls_to_psa_error(ret);
|
||||
}
|
||||
|
||||
psa_status_t esp_crypto_aes_update(
|
||||
psa_status_t esp_aes_cipher_update(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *input, size_t input_length,
|
||||
uint8_t *output, size_t output_size,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
int ret = -1;
|
||||
@@ -187,7 +281,7 @@ psa_status_t esp_crypto_aes_update(
|
||||
}
|
||||
|
||||
if (output_size < expected_output_size) {
|
||||
ESP_LOGE("TAG", "Output buffer too small: have %zu, need %zu", output_size, expected_output_size);
|
||||
ESP_LOGE(TAG, "Output buffer too small: have %zu, need %zu", output_size, expected_output_size);
|
||||
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
@@ -199,7 +293,7 @@ psa_status_t esp_crypto_aes_update(
|
||||
else if (esp_aes_driver_ctx->aes_alg == PSA_ALG_ECB_NO_PADDING) {
|
||||
/* esp_aes_crypt_ecb will only process a single block at a time in
|
||||
* ECB mode. Abstract this away to match the PSA API behaviour. */
|
||||
ret = esp_crypto_aes_ecb_update(esp_aes_driver_ctx,
|
||||
ret = esp_aes_ecb_update(esp_aes_driver_ctx,
|
||||
input,
|
||||
input_length,
|
||||
output,
|
||||
@@ -249,7 +343,7 @@ psa_status_t esp_crypto_aes_update(
|
||||
#endif /* CONFIG_MBEDTLS_CIPHER_MODE_OFB */
|
||||
case PSA_ALG_CBC_NO_PADDING:
|
||||
case PSA_ALG_CBC_PKCS7:
|
||||
ret = esp_crypto_aes_cbc_update(esp_aes_driver_ctx,
|
||||
ret = esp_aes_cbc_update(esp_aes_driver_ctx,
|
||||
input,
|
||||
input_length,
|
||||
output,
|
||||
@@ -314,9 +408,10 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data
|
||||
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
|
||||
}
|
||||
|
||||
psa_status_t esp_crypto_aes_finish(
|
||||
psa_status_t esp_aes_cipher_finish(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
uint8_t *output, size_t output_size,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
int ret = -1;
|
||||
@@ -421,7 +516,8 @@ exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_ctx)
|
||||
psa_status_t esp_aes_cipher_abort(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx)
|
||||
{
|
||||
esp_aes_context *ctx = (esp_aes_context *) esp_aes_driver_ctx->esp_aes_ctx;
|
||||
if (ctx == NULL) {
|
||||
@@ -432,85 +528,6 @@ psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_ctx)
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t esp_crypto_aes_set_iv(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *iv, size_t iv_length)
|
||||
{
|
||||
if (iv_length != PSA_CIPHER_IV_LENGTH(PSA_KEY_TYPE_AES, esp_aes_driver_ctx->aes_alg)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
memcpy(esp_aes_driver_ctx->iv, iv, iv_length);
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static psa_status_t esp_crypto_aes_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg, psa_encrypt_or_decrypt_t mode)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
|
||||
if (!PSA_ALG_IS_CIPHER(alg)) {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_AES) {
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (alg) {
|
||||
case PSA_ALG_ECB_NO_PADDING:
|
||||
case PSA_ALG_CBC_NO_PADDING:
|
||||
case PSA_ALG_CBC_PKCS7:
|
||||
case PSA_ALG_CTR:
|
||||
case PSA_ALG_XTS:
|
||||
case PSA_ALG_CFB:
|
||||
case PSA_ALG_OFB:
|
||||
break;
|
||||
default:
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
esp_aes_context *ctx = (esp_aes_context *) malloc(sizeof(esp_aes_context));
|
||||
if (ctx == NULL) {
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
esp_aes_init(ctx);
|
||||
|
||||
status = mbedtls_to_psa_error(esp_aes_setkey(ctx, key_buffer, key_buffer_size * 8));
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
free(ctx);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
esp_aes_driver_ctx->aes_alg = alg;
|
||||
esp_aes_driver_ctx->mode = mode;
|
||||
esp_aes_driver_ctx->esp_aes_ctx = (void *) ctx;
|
||||
esp_aes_driver_ctx->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 : PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES));
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_encrypt_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
return esp_crypto_aes_setup(esp_aes_driver_ctx, attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, PSA_CRYPTO_DRIVER_ENCRYPT);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_encrypt(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
@@ -533,58 +550,42 @@ psa_status_t esp_aes_cipher_encrypt(
|
||||
key_buffer, key_buffer_size,
|
||||
alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to setup encryption: %ld", status);
|
||||
ESP_LOGE(TAG, "Failed to setup encryption: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (iv_length > 0) {
|
||||
status = esp_crypto_aes_set_iv(&esp_aes_driver_ctx, iv, iv_length);
|
||||
status = esp_aes_cipher_set_iv(&esp_aes_driver_ctx, iv, iv_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to set IV: %ld", status);
|
||||
ESP_LOGE(TAG, "Failed to set IV: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
status = esp_crypto_aes_update(&esp_aes_driver_ctx, input, input_length,
|
||||
status = esp_aes_cipher_update(&esp_aes_driver_ctx, input, input_length,
|
||||
output, output_size,
|
||||
&update_output_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to update: %ld", status);
|
||||
ESP_LOGE(TAG, "Failed to update: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_crypto_aes_finish(&esp_aes_driver_ctx,
|
||||
status = esp_aes_cipher_finish(&esp_aes_driver_ctx,
|
||||
mbedtls_buffer_offset(output, update_output_length),
|
||||
output_size - update_output_length, &finish_output_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to finish: %ld", status);
|
||||
ESP_LOGE(TAG, "Failed to finish: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*output_length = update_output_length + finish_output_length;
|
||||
|
||||
exit:
|
||||
if (status == PSA_SUCCESS) {
|
||||
status = esp_crypto_aes_abort(&esp_aes_driver_ctx);
|
||||
} else {
|
||||
ESP_LOGE("esp_aes_cipher_encrypt", "Failed to abort: %ld", status);
|
||||
esp_crypto_aes_abort(&esp_aes_driver_ctx);
|
||||
}
|
||||
esp_aes_cipher_abort(&esp_aes_driver_ctx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_decrypt_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
return esp_crypto_aes_setup(esp_aes_driver_ctx, attributes,
|
||||
key_buffer, key_buffer_size,
|
||||
alg, PSA_CRYPTO_DRIVER_DECRYPT);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_decrypt(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
@@ -601,85 +602,44 @@ psa_status_t esp_aes_cipher_decrypt(
|
||||
key, key_length,
|
||||
alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to setup decryption: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
uint8_t iv_length = PSA_CIPHER_IV_LENGTH(psa_get_key_type(attributes), alg);
|
||||
|
||||
if (iv_length > 0) {
|
||||
status = esp_crypto_aes_set_iv(&esp_aes_driver_ctx,
|
||||
status = esp_aes_cipher_set_iv(&esp_aes_driver_ctx,
|
||||
input, iv_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to set IV: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
status = esp_crypto_aes_update(&esp_aes_driver_ctx,
|
||||
status = esp_aes_cipher_update(&esp_aes_driver_ctx,
|
||||
mbedtls_buffer_offset_const(input, iv_length),
|
||||
input_length - iv_length,
|
||||
output, output_size, &olength);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to update: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
accumulated_length = olength;
|
||||
|
||||
status = esp_crypto_aes_finish(&esp_aes_driver_ctx,
|
||||
status = esp_aes_cipher_finish(&esp_aes_driver_ctx,
|
||||
mbedtls_buffer_offset(output, accumulated_length),
|
||||
output_size - accumulated_length, &olength);
|
||||
if (status != PSA_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Failed to finish: %ld", status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*output_length = accumulated_length + olength;
|
||||
|
||||
exit:
|
||||
if (status == PSA_SUCCESS) {
|
||||
status = esp_crypto_aes_abort(&esp_aes_driver_ctx);
|
||||
} else {
|
||||
esp_crypto_aes_abort(&esp_aes_driver_ctx);
|
||||
}
|
||||
esp_aes_cipher_abort(&esp_aes_driver_ctx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_set_iv(
|
||||
esp_aes_operation_t *operation,
|
||||
const uint8_t *iv,
|
||||
size_t iv_length)
|
||||
{
|
||||
return esp_crypto_aes_set_iv(operation, iv, iv_length);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_update(
|
||||
esp_aes_operation_t *operation,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
return esp_crypto_aes_update(operation, input, input_length,
|
||||
output, output_size, output_length);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_finish(
|
||||
esp_aes_operation_t *operation,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length)
|
||||
{
|
||||
return esp_crypto_aes_finish(operation, output, output_size, output_length);
|
||||
}
|
||||
|
||||
psa_status_t esp_aes_cipher_abort(
|
||||
esp_aes_operation_t *operation)
|
||||
{
|
||||
esp_aes_context *ctx = (esp_aes_context *) operation->esp_aes_ctx;
|
||||
if (ctx == NULL) {
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
esp_aes_free(ctx);
|
||||
free(ctx);
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1,623 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_esp_cmac.h"
|
||||
#include "psa_crypto_driver_esp_cmac_contexts.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
|
||||
#define MBEDTLS_CMAC_MAX_BLOCK_SIZE 16
|
||||
|
||||
#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
|
||||
#define MBEDTLS_IS_BIG_ENDIAN 1
|
||||
#else
|
||||
#define MBEDTLS_IS_BIG_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_BSWAP32 __builtin_bswap32
|
||||
|
||||
static inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
|
||||
{
|
||||
uint32_t r;
|
||||
#if defined(UINT_UNALIGNED)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
r = *p32;
|
||||
#elif defined(UINT_UNALIGNED_STRUCT)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
r = p32->x;
|
||||
#else
|
||||
memcpy(&r, p, sizeof(r));
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
|
||||
{
|
||||
#if defined(UINT_UNALIGNED)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
*p32 = x;
|
||||
#elif defined(UINT_UNALIGNED_STRUCT)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
p32->x = x;
|
||||
#else
|
||||
memcpy(p, &x, sizeof(x));
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MBEDTLS_GET_UINT32_BE(data, offset) \
|
||||
((MBEDTLS_IS_BIG_ENDIAN) \
|
||||
? mbedtls_get_unaligned_uint32((data) + (offset)) \
|
||||
: MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
|
||||
)
|
||||
|
||||
#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
|
||||
do { \
|
||||
mbedtls_put_unaligned_uint32((data) + (offset), \
|
||||
(MBEDTLS_IS_BIG_ENDIAN) \
|
||||
? (uint32_t) (n) \
|
||||
: MBEDTLS_BSWAP32((uint32_t) (n))); \
|
||||
} while (0)
|
||||
|
||||
psa_status_t esp_cmac_mac_abort(esp_cmac_operation_t *operation)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
status = psa_destroy_key(operation->key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = psa_cipher_abort(&operation->cipher_ctx);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(&operation->cipher_ctx, sizeof(psa_cipher_operation_t));
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t mac_init(
|
||||
esp_cmac_operation_t *operation,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
memset(operation, 0, sizeof(*operation));
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t esp_cmac_setup_internal(esp_cmac_operation_t *cmac,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size)
|
||||
{
|
||||
int status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
#if defined(PSA_WANT_KEY_TYPE_DES)
|
||||
/* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
|
||||
* to do CMAC with pure DES, so return NOT_SUPPORTED here. */
|
||||
if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&
|
||||
(psa_get_key_bits(attributes) == 64 ||
|
||||
psa_get_key_bits(attributes) == 128)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_type_t key_type = psa_get_key_type(attributes);
|
||||
size_t key_bits = psa_get_key_bits(attributes);
|
||||
psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
|
||||
|
||||
/* Set up key attributes for PSA import */
|
||||
psa_set_key_type(&key_attributes, key_type);
|
||||
psa_set_key_bits(&key_attributes, key_bits);
|
||||
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
|
||||
psa_set_key_algorithm(&key_attributes, alg);
|
||||
|
||||
/* Import key for cipher operations */
|
||||
status = psa_import_key(&key_attributes, key_buffer, key_buffer_size, &cmac->key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = psa_cipher_encrypt_setup(&cmac->cipher_ctx, cmac->key_id, alg);
|
||||
if (status != 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
cmac->unprocessed_len = 0;
|
||||
cmac->cipher_block_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
|
||||
|
||||
mbedtls_platform_zeroize(cmac->state, sizeof(cmac->state));
|
||||
mbedtls_platform_zeroize(cmac->unprocessed_block, sizeof(cmac->unprocessed_block));
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
static psa_status_t esp_cmac_mac_setup_cmac(esp_cmac_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
status = mac_init(operation, alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
status = esp_cmac_setup_internal(operation, attributes, key_buffer, key_buffer_size);
|
||||
|
||||
if (status != PSA_SUCCESS) {
|
||||
esp_cmac_mac_abort(operation);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_mac_setup(esp_cmac_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
|
||||
status = esp_cmac_mac_setup_cmac(operation, attributes, key_buffer, key_buffer_size, alg);
|
||||
operation->alg = alg;
|
||||
} else if (PSA_ALG_IS_HMAC(alg)) {
|
||||
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(alg);
|
||||
uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
||||
size_t i;
|
||||
size_t hash_size = PSA_HASH_LENGTH(hash_alg);
|
||||
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
|
||||
|
||||
/* Sanity checks on block_size, to guarantee that there won't be a buffer
|
||||
* overflow below. This should never trigger if the hash algorithm
|
||||
* is implemented correctly. */
|
||||
/* The size checks against the ipad and opad buffers cannot be written
|
||||
* `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
|
||||
* because that triggers -Wlogical-op on GCC 7.3. */
|
||||
if (block_size > sizeof(ipad)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
if (block_size > sizeof(operation->opad)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
if (block_size < hash_size) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (key_buffer_size > block_size) {
|
||||
status = esp_sha_hash_compute(hash_alg, key_buffer, key_buffer_size,
|
||||
ipad, sizeof(ipad), &key_buffer_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
/* After hashing, key_buffer_size is set to the hash size, which
|
||||
* should be <= block_size. Verify this for static analysis. */
|
||||
if (key_buffer_size > block_size) {
|
||||
return PSA_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
}
|
||||
/* A 0-length key is not commonly used in HMAC when used as a MAC,
|
||||
* but it is permitted. It is common when HMAC is used in HKDF, for
|
||||
* example. Don't call `memcpy` in the 0-length because `key` could be
|
||||
* an invalid pointer which would make the behavior undefined. */
|
||||
else if (key_buffer_size != 0) {
|
||||
/* Additional safety check: ensure key fits in ipad buffer */
|
||||
if (key_buffer_size > sizeof(ipad)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
memcpy(ipad, key_buffer, key_buffer_size);
|
||||
}
|
||||
|
||||
/* ipad contains the key followed by garbage. Xor and fill with 0x36
|
||||
* to create the ipad value. */
|
||||
for (i = 0; i < key_buffer_size; i++) {
|
||||
ipad[i] ^= 0x36;
|
||||
}
|
||||
/* Only fill remaining bytes if key_buffer_size < block_size.
|
||||
* When key_buffer_size == block_size, the entire buffer is already
|
||||
* processed, so no padding is needed. This check also prevents
|
||||
* out-of-bounds pointer arithmetic (ipad + key_buffer_size would be
|
||||
* out of bounds when key_buffer_size == block_size == sizeof(ipad)). */
|
||||
if (key_buffer_size < block_size) {
|
||||
/* At this point: key_buffer_size < block_size <= sizeof(ipad),
|
||||
* so ipad + key_buffer_size is guaranteed to be within bounds. */
|
||||
size_t fill_size = block_size - key_buffer_size;
|
||||
memset(ipad + key_buffer_size, 0x36, fill_size);
|
||||
}
|
||||
|
||||
/* Copy the key material from ipad to opad, flipping the requisite bits,
|
||||
* and filling the rest of opad with the requisite constant. */
|
||||
for (i = 0; i < key_buffer_size; i++) {
|
||||
operation->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
|
||||
}
|
||||
/* Only fill remaining bytes if key_buffer_size < block_size.
|
||||
* When key_buffer_size == block_size, the entire buffer is already
|
||||
* processed, so no padding is needed. This check also prevents
|
||||
* out-of-bounds pointer arithmetic (operation->opad + key_buffer_size
|
||||
* would be out of bounds when key_buffer_size == block_size == sizeof(operation->opad)). */
|
||||
if (key_buffer_size < block_size) {
|
||||
/* At this point: key_buffer_size < block_size <= sizeof(operation->opad),
|
||||
* so operation->opad + key_buffer_size is guaranteed to be within bounds. */
|
||||
size_t fill_size = block_size - key_buffer_size;
|
||||
memset(operation->opad + key_buffer_size, 0x5C, fill_size);
|
||||
}
|
||||
status = esp_sha_hash_setup(&operation->hmac_operation, hash_alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_update(&operation->hmac_operation, ipad, block_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
operation->alg = alg;
|
||||
} else {
|
||||
(void) attributes;
|
||||
(void) key_buffer;
|
||||
(void) key_buffer_size;
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void xor_no_simd(unsigned char *output, const unsigned char *input1, const unsigned char *input2, size_t length)
|
||||
{
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
output[i] = input1[i] ^ input2[i];
|
||||
}
|
||||
}
|
||||
|
||||
static psa_status_t esp_cmac_mac_update_internal(esp_cmac_operation_t *cmac, const uint8_t *data, size_t data_length)
|
||||
{
|
||||
unsigned char *state = cmac->state;
|
||||
int ret = 0;
|
||||
size_t n, j, olen, block_size;
|
||||
|
||||
if (cmac == NULL || data == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
block_size = cmac->cipher_block_length;
|
||||
|
||||
/* Is there data still to process from the last call, that's greater in
|
||||
* size than a block? */
|
||||
if (cmac->unprocessed_len > 0 && data_length > block_size - cmac->unprocessed_len) {
|
||||
memcpy(&cmac->unprocessed_block[cmac->unprocessed_len], data, block_size - cmac->unprocessed_len);
|
||||
xor_no_simd(state, cmac->unprocessed_block, state, block_size);
|
||||
|
||||
if ((ret = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data += block_size - cmac->unprocessed_len;
|
||||
data_length -= block_size - cmac->unprocessed_len;
|
||||
cmac->unprocessed_len = 0;
|
||||
}
|
||||
|
||||
/* n is the number of blocks including any final partial block */
|
||||
n = (data_length + block_size - 1) / block_size;
|
||||
/* Iterate across the input data in block sized chunks, excluding any
|
||||
* final partial or complete block */
|
||||
for (j = 1; j < n; j++) {
|
||||
xor_no_simd(state, data, state, block_size);
|
||||
if ((ret = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data_length -= block_size;
|
||||
data += block_size;
|
||||
}
|
||||
|
||||
/* If there is data left over that wasn't aligned to a block */
|
||||
if (data_length > 0) {
|
||||
memcpy(&cmac->unprocessed_block[cmac->unprocessed_len], data, data_length);
|
||||
cmac->unprocessed_len += data_length;
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_mac_update(esp_cmac_operation_t *cmac, const uint8_t *data, size_t data_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (PSA_ALG_FULL_LENGTH_MAC(cmac->alg) == PSA_ALG_CMAC) {
|
||||
status = esp_cmac_mac_update_internal(cmac, data, data_length);
|
||||
} else if (PSA_ALG_IS_HMAC(cmac->alg)) {
|
||||
status = esp_sha_hash_update(&cmac->hmac_operation, data, data_length);
|
||||
} else {
|
||||
(void) cmac;
|
||||
(void) data;
|
||||
(void) data_length;
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static inline unsigned mbedtls_ct_uint_if_else_0(uint32_t condition, unsigned if1)
|
||||
{
|
||||
return (unsigned) (condition & if1);
|
||||
}
|
||||
|
||||
static int cmac_multiply_by_u(unsigned char *output,
|
||||
const unsigned char *input,
|
||||
size_t blocksize)
|
||||
{
|
||||
const unsigned char R_128 = 0x87;
|
||||
unsigned char R_n;
|
||||
uint32_t overflow = 0x00;
|
||||
int i;
|
||||
|
||||
if (blocksize == PSA_AES_BLOCK_SIZE) {
|
||||
R_n = R_128;
|
||||
}
|
||||
#if defined(PSA_WANT_KEY_TYPE_DES)
|
||||
else if (blocksize == PSA_DES_BLOCK_SIZE) {
|
||||
const unsigned char R_64 = 0x1B;
|
||||
R_n = R_64;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
for (i = (int) blocksize - 4; i >= 0; i -= 4) {
|
||||
uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
|
||||
uint32_t new_overflow = i32 >> 31;
|
||||
i32 = (i32 << 1) | overflow;
|
||||
MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
|
||||
overflow = new_overflow;
|
||||
}
|
||||
|
||||
unsigned char msb = (input[0] >> 7) & 1;
|
||||
output[blocksize - 1] ^= (unsigned char)(msb * R_n);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmac_generate_subkeys(psa_cipher_operation_t *ctx, size_t block_size,
|
||||
unsigned char *K1, unsigned char *K2)
|
||||
{
|
||||
int ret = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char L[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
size_t olen;
|
||||
|
||||
mbedtls_platform_zeroize(L, sizeof(L));
|
||||
|
||||
/* Calculate Ek(0) */
|
||||
if ((ret = psa_cipher_update(ctx, L, block_size, L, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate K1 and K2
|
||||
*/
|
||||
if ((ret = cmac_multiply_by_u(K1, L, block_size)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((ret = cmac_multiply_by_u(K2, K1, block_size)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(L, sizeof(L));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],
|
||||
size_t padded_block_len,
|
||||
const unsigned char *last_block,
|
||||
size_t last_block_len)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < padded_block_len; j++) {
|
||||
if (j < last_block_len) {
|
||||
padded_block[j] = last_block[j];
|
||||
} else if (j == last_block_len) {
|
||||
padded_block[j] = 0x80;
|
||||
} else {
|
||||
padded_block[j] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static psa_status_t esp_cmac_mac_finish_internal(
|
||||
esp_cmac_operation_t *cmac,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t olen, block_size;
|
||||
|
||||
unsigned char *state, *last_block;
|
||||
unsigned char K1[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char K2[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char M_last[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
|
||||
if (cmac == NULL || mac == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
state = cmac->state;
|
||||
block_size = cmac->cipher_block_length;
|
||||
|
||||
mbedtls_platform_zeroize(K1, sizeof(K1));
|
||||
mbedtls_platform_zeroize(K2, sizeof(K2));
|
||||
cmac_generate_subkeys(&cmac->cipher_ctx, block_size, K1, K2);
|
||||
|
||||
last_block = cmac->unprocessed_block;
|
||||
|
||||
/* Calculate last block */
|
||||
if (cmac->unprocessed_len < block_size) {
|
||||
cmac_pad(M_last, block_size, last_block, cmac->unprocessed_len);
|
||||
xor_no_simd(M_last, M_last, K2, block_size);
|
||||
} else {
|
||||
/* Last block is complete block */
|
||||
xor_no_simd(M_last, last_block, K1, block_size);
|
||||
}
|
||||
|
||||
xor_no_simd(state, M_last, state, block_size);
|
||||
if ((status = psa_cipher_update(&cmac->cipher_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* CMAC output is always the cipher block size, regardless of requested mac_size */
|
||||
size_t output_length = (mac_size < block_size) ? mac_size : block_size;
|
||||
memcpy(mac, state, output_length);
|
||||
*mac_length = output_length;
|
||||
exit:
|
||||
mbedtls_platform_zeroize(K1, sizeof(K1));
|
||||
mbedtls_platform_zeroize(K2, sizeof(K2));
|
||||
|
||||
cmac->unprocessed_len = 0;
|
||||
mbedtls_platform_zeroize(cmac->unprocessed_block, sizeof(cmac->unprocessed_block));
|
||||
mbedtls_platform_zeroize(state, PSA_CMAC_MAX_BLOCK_SIZE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_mac_finish(
|
||||
esp_cmac_operation_t *cmac,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (PSA_ALG_FULL_LENGTH_MAC(cmac->alg) == PSA_ALG_CMAC) {
|
||||
status = esp_cmac_mac_finish_internal(cmac, mac, mac_size, mac_length);
|
||||
} else if (PSA_ALG_IS_HMAC(cmac->alg)) {
|
||||
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(cmac->alg);
|
||||
|
||||
uint8_t tmp[PSA_HASH_MAX_SIZE];
|
||||
size_t hash_size = 0;
|
||||
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
|
||||
|
||||
status = esp_sha_hash_finish(&cmac->hmac_operation, tmp, sizeof(tmp), &hash_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
/* From here on, tmp needs to be wiped. */
|
||||
|
||||
status = esp_sha_hash_setup(&cmac->hmac_operation, hash_alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_update(&cmac->hmac_operation, cmac->opad, block_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_update(&cmac->hmac_operation, tmp, hash_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_finish(&cmac->hmac_operation, tmp, sizeof(tmp), &hash_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(mac, tmp, mac_size);
|
||||
|
||||
*mac_length = mac_size;
|
||||
exit:
|
||||
mbedtls_platform_zeroize(tmp, hash_size);
|
||||
} else {
|
||||
(void) cmac;
|
||||
(void) mac;
|
||||
(void) mac_length;
|
||||
(void) mac_size;
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_mac_compute(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
esp_cmac_operation_t operation = {0};
|
||||
|
||||
memset(&operation, 0, sizeof(operation));
|
||||
|
||||
status = esp_cmac_mac_setup(&operation,
|
||||
attributes, key_buffer, key_buffer_size,
|
||||
alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (input_length > 0) {
|
||||
status = esp_cmac_mac_update(&operation, input, input_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
size_t actual_mac_length = 0;
|
||||
status = esp_cmac_mac_finish(&operation, mac, mac_size, &actual_mac_length);
|
||||
if (status == PSA_SUCCESS) {
|
||||
*mac_length = actual_mac_length;
|
||||
}
|
||||
|
||||
exit:
|
||||
esp_cmac_mac_abort(&operation);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_mac_verify_finish(
|
||||
esp_cmac_operation_t *operation,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length)
|
||||
{
|
||||
uint8_t actual_mac[PSA_MAC_MAX_SIZE];
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (operation == NULL || mac == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (mac_length > sizeof(actual_mac)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
size_t actual_mac_length = 0;
|
||||
|
||||
status = esp_cmac_mac_finish(operation, actual_mac, sizeof(actual_mac), &actual_mac_length);
|
||||
if (status == PSA_SUCCESS) {
|
||||
if (memcmp(actual_mac, mac, mac_length) == 0) {
|
||||
return PSA_SUCCESS;
|
||||
} else {
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_esp_cmac.h"
|
||||
#include "psa_crypto_driver_esp_cmac_contexts.h"
|
||||
#include "psa_crypto_driver_esp_aes.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
|
||||
#define MBEDTLS_CMAC_MAX_BLOCK_SIZE 16
|
||||
|
||||
#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
|
||||
#define MBEDTLS_IS_BIG_ENDIAN 1
|
||||
#else
|
||||
#define MBEDTLS_IS_BIG_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#define MBEDTLS_BSWAP32 __builtin_bswap32
|
||||
|
||||
static inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
|
||||
{
|
||||
uint32_t r;
|
||||
#if defined(UINT_UNALIGNED)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
r = *p32;
|
||||
#elif defined(UINT_UNALIGNED_STRUCT)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
r = p32->x;
|
||||
#else
|
||||
memcpy(&r, p, sizeof(r));
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
|
||||
{
|
||||
#if defined(UINT_UNALIGNED)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
*p32 = x;
|
||||
#elif defined(UINT_UNALIGNED_STRUCT)
|
||||
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
|
||||
p32->x = x;
|
||||
#else
|
||||
memcpy(p, &x, sizeof(x));
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MBEDTLS_GET_UINT32_BE(data, offset) \
|
||||
((MBEDTLS_IS_BIG_ENDIAN) \
|
||||
? mbedtls_get_unaligned_uint32((data) + (offset)) \
|
||||
: MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
|
||||
)
|
||||
|
||||
#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
|
||||
do { \
|
||||
mbedtls_put_unaligned_uint32((data) + (offset), \
|
||||
(MBEDTLS_IS_BIG_ENDIAN) \
|
||||
? (uint32_t) (n) \
|
||||
: MBEDTLS_BSWAP32((uint32_t) (n))); \
|
||||
} while (0)
|
||||
|
||||
psa_status_t esp_cmac_abort(esp_cmac_operation_t *esp_cmac_ctx)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
status = psa_destroy_key(esp_cmac_ctx->key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = esp_aes_cipher_abort(&esp_cmac_ctx->esp_aes_ctx);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(esp_cmac_ctx, sizeof(esp_cmac_operation_t));
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
memset(esp_cmac_ctx, 0, sizeof(*esp_cmac_ctx));
|
||||
|
||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_key_type_t key_type = psa_get_key_type(attributes);
|
||||
size_t key_bits = psa_get_key_bits(attributes);
|
||||
psa_algorithm_t cmac_aes_key_alg = PSA_ALG_ECB_NO_PADDING;
|
||||
/* Set up key attributes for PSA import */
|
||||
psa_set_key_type(&key_attributes, key_type);
|
||||
psa_set_key_bits(&key_attributes, key_bits);
|
||||
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT);
|
||||
psa_set_key_algorithm(&key_attributes, cmac_aes_key_alg);
|
||||
|
||||
/* Import key for cipher operations */
|
||||
status = psa_import_key(&key_attributes, key_buffer, key_buffer_size, &esp_cmac_ctx->key_id);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_aes_cipher_encrypt_setup(&esp_cmac_ctx->esp_aes_ctx, &key_attributes, key_buffer, key_buffer_size, cmac_aes_key_alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
psa_destroy_key(esp_cmac_ctx->key_id);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
psa_reset_key_attributes(&key_attributes);
|
||||
esp_cmac_ctx->alg = alg;
|
||||
esp_cmac_ctx->unprocessed_len = 0;
|
||||
esp_cmac_ctx->cipher_block_length = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
|
||||
mbedtls_platform_zeroize(esp_cmac_ctx->state, sizeof(esp_cmac_ctx->state));
|
||||
mbedtls_platform_zeroize(esp_cmac_ctx->unprocessed_block, sizeof(esp_cmac_ctx->unprocessed_block));
|
||||
|
||||
exit:
|
||||
psa_reset_key_attributes(&key_attributes);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void xor_no_simd(unsigned char *output, const unsigned char *input1, const unsigned char *input2, size_t length)
|
||||
{
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
output[i] = input1[i] ^ input2[i];
|
||||
}
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_update(esp_cmac_operation_t *esp_cmac_ctx, const uint8_t *data, size_t data_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
size_t n, j, olen, block_size;
|
||||
unsigned char *state;
|
||||
|
||||
if (esp_cmac_ctx == NULL || data == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
state = esp_cmac_ctx->state;
|
||||
block_size = esp_cmac_ctx->cipher_block_length;
|
||||
|
||||
/* Is there data still to process from the last call, that's greater in
|
||||
* size than a block? */
|
||||
if (esp_cmac_ctx->unprocessed_len > 0 && data_length > block_size - esp_cmac_ctx->unprocessed_len) {
|
||||
memcpy(&esp_cmac_ctx->unprocessed_block[esp_cmac_ctx->unprocessed_len], data, block_size - esp_cmac_ctx->unprocessed_len);
|
||||
xor_no_simd(state, esp_cmac_ctx->unprocessed_block, state, block_size);
|
||||
|
||||
if ((status = esp_aes_cipher_update(&esp_cmac_ctx->esp_aes_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data += block_size - esp_cmac_ctx->unprocessed_len;
|
||||
data_length -= block_size - esp_cmac_ctx->unprocessed_len;
|
||||
esp_cmac_ctx->unprocessed_len = 0;
|
||||
}
|
||||
|
||||
/* n is the number of blocks including any final partial block */
|
||||
n = (data_length + block_size - 1) / block_size;
|
||||
/* Iterate across the input data in block sized chunks, excluding any
|
||||
* final partial or complete block */
|
||||
for (j = 1; j < n; j++) {
|
||||
xor_no_simd(state, data, state, block_size);
|
||||
if ((status = esp_aes_cipher_update(&esp_cmac_ctx->esp_aes_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data_length -= block_size;
|
||||
data += block_size;
|
||||
}
|
||||
|
||||
/* If there is data left over that wasn't aligned to a block */
|
||||
if (data_length > 0) {
|
||||
memcpy(&esp_cmac_ctx->unprocessed_block[esp_cmac_ctx->unprocessed_len], data, data_length);
|
||||
esp_cmac_ctx->unprocessed_len += data_length;
|
||||
}
|
||||
|
||||
status = PSA_SUCCESS;
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t cmac_multiply_by_u(unsigned char *output,
|
||||
const unsigned char *input,
|
||||
size_t blocksize)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
const unsigned char R_128 = 0x87;
|
||||
unsigned char R_n;
|
||||
uint32_t overflow = 0x00;
|
||||
int i;
|
||||
|
||||
if (blocksize == PSA_AES_BLOCK_SIZE) {
|
||||
R_n = R_128;
|
||||
}
|
||||
#if defined(PSA_WANT_KEY_TYPE_DES)
|
||||
else if (blocksize == PSA_DES_BLOCK_SIZE) {
|
||||
const unsigned char R_64 = 0x1B;
|
||||
R_n = R_64;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = (int) blocksize - 4; i >= 0; i -= 4) {
|
||||
uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
|
||||
uint32_t new_overflow = i32 >> 31;
|
||||
i32 = (i32 << 1) | overflow;
|
||||
MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
|
||||
overflow = new_overflow;
|
||||
}
|
||||
|
||||
unsigned char msb = (input[0] >> 7) & 1;
|
||||
output[blocksize - 1] ^= (unsigned char)(msb * R_n);
|
||||
|
||||
status = PSA_SUCCESS;
|
||||
exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
static psa_status_t cmac_generate_subkeys(esp_aes_operation_t *esp_aes_driver_ctx, size_t block_size,
|
||||
uint8_t *K1, uint8_t *K2)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
uint8_t L[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
size_t olen;
|
||||
|
||||
mbedtls_platform_zeroize(L, sizeof(L));
|
||||
|
||||
/* Calculate Ek(0) */
|
||||
if ((status = esp_aes_cipher_update(esp_aes_driver_ctx, L, block_size, L, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate K1 and K2
|
||||
*/
|
||||
if ((status = cmac_multiply_by_u(K1, L, block_size)) != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((status = cmac_multiply_by_u(K2, K1, block_size)) != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(L, sizeof(L));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],
|
||||
size_t padded_block_len,
|
||||
const unsigned char *last_block,
|
||||
size_t last_block_len)
|
||||
{
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < padded_block_len; j++) {
|
||||
if (j < last_block_len) {
|
||||
padded_block[j] = last_block[j];
|
||||
} else if (j == last_block_len) {
|
||||
padded_block[j] = 0x80;
|
||||
} else {
|
||||
padded_block[j] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_finish(
|
||||
esp_cmac_operation_t *esp_cmac_ctx,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
size_t olen, block_size;
|
||||
|
||||
unsigned char *state, *last_block;
|
||||
unsigned char K1[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char K2[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char M_last[PSA_CMAC_MAX_BLOCK_SIZE];
|
||||
|
||||
if (esp_cmac_ctx == NULL || mac == NULL || mac_size == 0) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
state = esp_cmac_ctx->state;
|
||||
block_size = esp_cmac_ctx->cipher_block_length;
|
||||
|
||||
mbedtls_platform_zeroize(K1, sizeof(K1));
|
||||
mbedtls_platform_zeroize(K2, sizeof(K2));
|
||||
cmac_generate_subkeys(&esp_cmac_ctx->esp_aes_ctx, block_size, K1, K2);
|
||||
|
||||
last_block = esp_cmac_ctx->unprocessed_block;
|
||||
|
||||
/* Calculate last block */
|
||||
if (esp_cmac_ctx->unprocessed_len < block_size) {
|
||||
cmac_pad(M_last, block_size, last_block, esp_cmac_ctx->unprocessed_len);
|
||||
xor_no_simd(M_last, M_last, K2, block_size);
|
||||
} else {
|
||||
/* Last block is complete block */
|
||||
xor_no_simd(M_last, last_block, K1, block_size);
|
||||
}
|
||||
|
||||
xor_no_simd(state, M_last, state, block_size);
|
||||
if ((status = esp_aes_cipher_update(&esp_cmac_ctx->esp_aes_ctx, state, block_size, state, PSA_CMAC_MAX_BLOCK_SIZE, &olen)) != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* CMAC output is always the cipher block size, regardless of requested mac_size */
|
||||
size_t output_length = (mac_size < block_size) ? mac_size : block_size;
|
||||
memcpy(mac, state, output_length);
|
||||
*mac_length = output_length;
|
||||
exit:
|
||||
mbedtls_platform_zeroize(K1, sizeof(K1));
|
||||
mbedtls_platform_zeroize(K2, sizeof(K2));
|
||||
|
||||
esp_cmac_ctx->unprocessed_len = 0;
|
||||
mbedtls_platform_zeroize(esp_cmac_ctx->unprocessed_block, sizeof(esp_cmac_ctx->unprocessed_block));
|
||||
mbedtls_platform_zeroize(state, PSA_CMAC_MAX_BLOCK_SIZE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_compute(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
esp_cmac_operation_t esp_cmac_ctx = {0};
|
||||
|
||||
status = esp_cmac_setup(&esp_cmac_ctx,
|
||||
attributes, key_buffer, key_buffer_size,
|
||||
alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (input_length > 0) {
|
||||
status = esp_cmac_update(&esp_cmac_ctx, input, input_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
size_t actual_mac_length = 0;
|
||||
status = esp_cmac_finish(&esp_cmac_ctx, mac, mac_size, &actual_mac_length);
|
||||
if (status == PSA_SUCCESS) {
|
||||
*mac_length = actual_mac_length;
|
||||
}
|
||||
|
||||
exit:
|
||||
esp_cmac_abort(&esp_cmac_ctx);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
psa_status_t esp_cmac_verify_finish(
|
||||
esp_cmac_operation_t *esp_cmac_ctx,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length)
|
||||
{
|
||||
uint8_t actual_mac[PSA_MAC_MAX_SIZE];
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (esp_cmac_ctx == NULL || mac == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (mac_length > sizeof(actual_mac)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
size_t actual_mac_length = 0;
|
||||
|
||||
status = esp_cmac_finish(esp_cmac_ctx, actual_mac, sizeof(actual_mac), &actual_mac_length);
|
||||
if (status == PSA_SUCCESS) {
|
||||
if (memcmp(actual_mac, mac, mac_length) == 0) {
|
||||
return PSA_SUCCESS;
|
||||
} else {
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_esp_hmac.h"
|
||||
#include "psa_crypto_driver_esp_hmac_contexts.h"
|
||||
|
||||
|
||||
psa_status_t esp_hmac_abort(esp_hmac_operation_t *esp_hmac_ctx)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
status = esp_sha_hash_abort(&esp_hmac_ctx->esp_sha_ctx);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(esp_hmac_ctx, sizeof(esp_hmac_operation_t));
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(alg);
|
||||
uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
||||
size_t i;
|
||||
size_t hash_size = PSA_HASH_LENGTH(hash_alg);
|
||||
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
|
||||
|
||||
if (esp_hmac_ctx == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
memset(esp_hmac_ctx, 0, sizeof(esp_hmac_operation_t));
|
||||
|
||||
/* Sanity checks on block_size, to guarantee that there won't be a buffer
|
||||
* overflow below. This should never trigger if the hash algorithm
|
||||
* is implemented correctly. */
|
||||
/* The size check against the ipad buffer also covers opad since both
|
||||
* have the same size (PSA_HMAC_MAX_HASH_BLOCK_SIZE). */
|
||||
if ((block_size > sizeof(ipad)) || (block_size < hash_size)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (key_buffer_size > block_size) {
|
||||
status = esp_sha_hash_compute(hash_alg, key_buffer, key_buffer_size,
|
||||
ipad, sizeof(ipad), &key_buffer_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
/* After hashing, key_buffer_size is set to the hash size, which
|
||||
* should be <= block_size. Verify this for static analysis. */
|
||||
if (key_buffer_size > block_size) {
|
||||
return PSA_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
}
|
||||
/* A 0-length key is not commonly used in HMAC when used as a MAC,
|
||||
* but it is permitted. It is common when HMAC is used in HKDF, for
|
||||
* example. Don't call `memcpy` in the 0-length because `key` could be
|
||||
* an invalid pointer which would make the behavior undefined. */
|
||||
else if (key_buffer_size != 0) {
|
||||
/* Additional safety check: ensure key fits in ipad buffer */
|
||||
if (key_buffer_size > sizeof(ipad)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
memcpy(ipad, key_buffer, key_buffer_size);
|
||||
}
|
||||
|
||||
/* ipad contains the key followed by garbage. Xor and fill with 0x36
|
||||
* to create the ipad value. */
|
||||
for (i = 0; i < key_buffer_size; i++) {
|
||||
ipad[i] ^= 0x36;
|
||||
}
|
||||
|
||||
/* Only fill remaining bytes if key_buffer_size < block_size.
|
||||
* When key_buffer_size == block_size, the entire buffer is already
|
||||
* processed, so no padding is needed. This check also prevents
|
||||
* out-of-bounds pointer arithmetic (ipad + key_buffer_size would be
|
||||
* out of bounds when key_buffer_size == block_size == sizeof(ipad)). */
|
||||
if (key_buffer_size < block_size) {
|
||||
/* At this point: key_buffer_size < block_size <= sizeof(ipad),
|
||||
* so ipad + key_buffer_size is guaranteed to be within bounds. */
|
||||
size_t fill_size = block_size - key_buffer_size;
|
||||
memset(ipad + key_buffer_size, 0x36, fill_size);
|
||||
}
|
||||
|
||||
/* Copy the key material from ipad to opad, flipping the requisite bits,
|
||||
* and filling the rest of opad with the requisite constant. */
|
||||
for (i = 0; i < key_buffer_size; i++) {
|
||||
esp_hmac_ctx->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
|
||||
}
|
||||
/* Only fill remaining bytes if key_buffer_size < block_size.
|
||||
* When key_buffer_size == block_size, the entire buffer is already
|
||||
* processed, so no padding is needed. This check also prevents
|
||||
* out-of-bounds pointer arithmetic (esp_hmac_ctx->opad + key_buffer_size
|
||||
* would be out of bounds when key_buffer_size == block_size == sizeof(esp_hmac_ctx->opad)). */
|
||||
if (key_buffer_size < block_size) {
|
||||
/* At this point: key_buffer_size < block_size <= sizeof(esp_hmac_ctx->opad),
|
||||
* so esp_hmac_ctx->opad + key_buffer_size is guaranteed to be within bounds. */
|
||||
size_t fill_size = block_size - key_buffer_size;
|
||||
memset(esp_hmac_ctx->opad + key_buffer_size, 0x5C, fill_size);
|
||||
}
|
||||
|
||||
status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, ipad, block_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
esp_hmac_ctx->alg = alg;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_hmac_update(esp_hmac_operation_t *esp_hmac_ctx, const uint8_t *data, size_t data_length)
|
||||
{
|
||||
return esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, data, data_length);
|
||||
}
|
||||
|
||||
psa_status_t esp_hmac_finish(
|
||||
esp_hmac_operation_t *esp_hmac_ctx,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(esp_hmac_ctx->alg);
|
||||
|
||||
uint8_t tmp[PSA_HASH_MAX_SIZE];
|
||||
size_t hash_size = 0;
|
||||
size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
|
||||
|
||||
status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
/* From here on, tmp needs to be wiped. */
|
||||
|
||||
status = esp_sha_hash_setup(&esp_hmac_ctx->esp_sha_ctx, hash_alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, esp_hmac_ctx->opad, block_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_update(&esp_hmac_ctx->esp_sha_ctx, tmp, hash_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = esp_sha_hash_finish(&esp_hmac_ctx->esp_sha_ctx, tmp, sizeof(tmp), &hash_size);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(mac, tmp, mac_size);
|
||||
|
||||
*mac_length = mac_size;
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(tmp, hash_size);
|
||||
return status;
|
||||
}
|
||||
|
||||
psa_status_t esp_hmac_compute(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
esp_hmac_operation_t esp_hmac_ctx = {0};
|
||||
|
||||
status = esp_hmac_setup(&esp_hmac_ctx,
|
||||
attributes, key_buffer, key_buffer_size,
|
||||
alg);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (input_length > 0) {
|
||||
status = esp_hmac_update(&esp_hmac_ctx, input, input_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
size_t actual_mac_length = 0;
|
||||
status = esp_hmac_finish(&esp_hmac_ctx, mac, mac_size, &actual_mac_length);
|
||||
if (status == PSA_SUCCESS) {
|
||||
*mac_length = actual_mac_length;
|
||||
}
|
||||
|
||||
exit:
|
||||
esp_hmac_abort(&esp_hmac_ctx);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
psa_status_t esp_hmac_verify_finish(
|
||||
esp_hmac_operation_t *esp_hmac_ctx,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length)
|
||||
{
|
||||
uint8_t actual_mac[PSA_MAC_MAX_SIZE];
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
|
||||
if (esp_hmac_ctx == NULL || mac == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (mac_length > sizeof(actual_mac)) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
size_t actual_mac_length = 0;
|
||||
|
||||
status = esp_hmac_finish(esp_hmac_ctx, actual_mac, sizeof(actual_mac), &actual_mac_length);
|
||||
if (status == PSA_SUCCESS) {
|
||||
if (memcmp(actual_mac, mac, mac_length) == 0) {
|
||||
return PSA_SUCCESS;
|
||||
} else {
|
||||
return PSA_ERROR_INVALID_SIGNATURE;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -30,29 +30,6 @@ psa_status_t esp_aes_cipher_encrypt(
|
||||
size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t esp_crypto_aes_encrypt_setup(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer, size_t key_buffer_size,
|
||||
psa_algorithm_t alg);
|
||||
|
||||
psa_status_t esp_crypto_aes_set_iv(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *iv, size_t iv_length);
|
||||
|
||||
psa_status_t esp_crypto_aes_update(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *input, size_t input_length,
|
||||
uint8_t *output, size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t esp_crypto_aes_finish(
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
uint8_t *output, size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t esp_crypto_aes_abort(esp_aes_operation_t *esp_aes_driver_ctx);
|
||||
|
||||
psa_status_t esp_aes_cipher_decrypt(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key, size_t key_length,
|
||||
@@ -73,12 +50,12 @@ psa_status_t esp_aes_cipher_encrypt_setup(
|
||||
psa_algorithm_t alg);
|
||||
|
||||
psa_status_t esp_aes_cipher_set_iv(
|
||||
esp_aes_operation_t *operation,
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *iv,
|
||||
size_t iv_length);
|
||||
|
||||
psa_status_t esp_aes_cipher_update(
|
||||
esp_aes_operation_t *operation,
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *output,
|
||||
@@ -86,13 +63,13 @@ psa_status_t esp_aes_cipher_update(
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t esp_aes_cipher_finish(
|
||||
esp_aes_operation_t *operation,
|
||||
esp_aes_operation_t *esp_aes_driver_ctx,
|
||||
uint8_t *output,
|
||||
size_t output_size,
|
||||
size_t *output_length);
|
||||
|
||||
psa_status_t esp_aes_cipher_abort(
|
||||
esp_aes_operation_t *operation);
|
||||
esp_aes_operation_t *esp_aes_driver_ctx);
|
||||
#endif /* ESP_AES_DRIVER_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -9,46 +9,43 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(ESP_AES_DRIVER_ENABLED)
|
||||
#if defined(ESP_CMAC_DRIVER_ENABLED)
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_esp_cmac_contexts.h"
|
||||
|
||||
psa_status_t esp_cmac_compute(const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length);
|
||||
|
||||
psa_status_t esp_cmac_mac_compute(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length);
|
||||
psa_status_t esp_cmac_abort(esp_cmac_operation_t *esp_cmac_ctx);
|
||||
|
||||
psa_status_t esp_cmac_mac_abort(esp_cmac_operation_t *operation);
|
||||
psa_status_t esp_cmac_setup(esp_cmac_operation_t *esp_cmac_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg);
|
||||
|
||||
psa_status_t esp_cmac_mac_setup(esp_cmac_operation_t *operation,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg);
|
||||
psa_status_t esp_cmac_update(esp_cmac_operation_t *esp_cmac_ctx,
|
||||
const uint8_t *data,
|
||||
size_t data_length);
|
||||
|
||||
psa_status_t esp_cmac_mac_update(esp_cmac_operation_t *cmac,
|
||||
const uint8_t *data,
|
||||
size_t data_length);
|
||||
psa_status_t esp_cmac_finish(esp_cmac_operation_t *esp_cmac_ctx,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length);
|
||||
|
||||
psa_status_t esp_cmac_mac_finish(
|
||||
esp_cmac_operation_t *hmac,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length);
|
||||
psa_status_t esp_cmac_verify_finish(esp_cmac_operation_t *esp_cmac_ctx,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length);
|
||||
|
||||
psa_status_t esp_cmac_mac_verify_finish(
|
||||
esp_cmac_operation_t *operation,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length);
|
||||
#endif /* ESP_AES_DRIVER_ENABLED */
|
||||
#endif /* ESP_CMAC_DRIVER_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -10,21 +10,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(ESP_AES_DRIVER_ENABLED) || defined(PSA_CRYPTO_DRIVER_TEST)
|
||||
#if defined(ESP_CMAC_DRIVER_ENABLED)
|
||||
|
||||
#if defined(ESP_SHA_DRIVER_ENABLED)
|
||||
#include "psa_crypto_driver_esp_sha_contexts.h"
|
||||
#include "psa_crypto_driver_esp_sha.h"
|
||||
#endif /* ESP_SHA_DRIVER_ENABLED */
|
||||
#include "psa_crypto_driver_esp_aes_contexts.h"
|
||||
|
||||
#define PSA_AES_BLOCK_SIZE PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)
|
||||
#define PSA_DES_BLOCK_SIZE PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_DES)
|
||||
|
||||
#if defined(PSA_WANT_KEY_TYPE_AES)
|
||||
#define PSA_CMAC_MAX_BLOCK_SIZE PSA_AES_BLOCK_SIZE /**< The longest block used by CMAC is that of AES. */
|
||||
#else
|
||||
#define PSA_CMAC_MAX_BLOCK_SIZE PSA_DES_BLOCK_SIZE /**< The longest block used by CMAC is that of 3DES. */
|
||||
#endif
|
||||
#define PSA_CMAC_MAX_BLOCK_SIZE PSA_AES_BLOCK_SIZE
|
||||
|
||||
typedef struct {
|
||||
/** The CMAC key identifier for cipher operations */
|
||||
@@ -42,16 +33,12 @@ typedef struct {
|
||||
|
||||
uint8_t cipher_block_length;
|
||||
|
||||
struct psa_cipher_operation_s cipher_ctx;
|
||||
esp_aes_operation_t esp_aes_ctx;
|
||||
|
||||
psa_algorithm_t alg;
|
||||
#if defined(ESP_SHA_DRIVER_ENABLED)
|
||||
esp_sha_hash_operation_t hmac_operation;
|
||||
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
||||
#endif /* ESP_SHA_DRIVER_ENABLED */
|
||||
} esp_cmac_operation_t;
|
||||
|
||||
#endif /* ESP_AES_DRIVER_ENABLED */
|
||||
#endif /* ESP_CMAC_DRIVER_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(ESP_SHA_DRIVER_ENABLED)
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "psa_crypto_driver_esp_hmac_contexts.h"
|
||||
|
||||
psa_status_t esp_hmac_compute(const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length);
|
||||
|
||||
psa_status_t esp_hmac_abort(esp_hmac_operation_t *esp_hmac_ctx);
|
||||
|
||||
psa_status_t esp_hmac_setup(esp_hmac_operation_t *esp_hmac_ctx,
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg);
|
||||
|
||||
psa_status_t esp_hmac_update(esp_hmac_operation_t *esp_hmac_ctx,
|
||||
const uint8_t *data,
|
||||
size_t data_length);
|
||||
|
||||
psa_status_t esp_hmac_finish(esp_hmac_operation_t *esp_hmac_ctx,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length);
|
||||
|
||||
psa_status_t esp_hmac_verify_finish(esp_hmac_operation_t *esp_hmac_ctx,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length);
|
||||
|
||||
#endif /* ESP_SHA_DRIVER_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(ESP_SHA_DRIVER_ENABLED)
|
||||
|
||||
#include "psa_crypto_driver_esp_sha_contexts.h"
|
||||
#include "psa_crypto_driver_esp_sha.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
||||
psa_algorithm_t alg;
|
||||
esp_sha_hash_operation_t esp_sha_ctx;
|
||||
} esp_hmac_operation_t;
|
||||
|
||||
#endif /* ESP_SHA_DRIVER_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -8,7 +8,9 @@
|
||||
#include "psa/crypto.h"
|
||||
#include "unity.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_MBEDTLS_ARIA_C
|
||||
/*
|
||||
ARIA-256-ECB Encrypt - RFC 5794 test vector
|
||||
Key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
|
||||
@@ -90,3 +92,4 @@ TEST_CASE("PSA ARIA-256-ECB encrypt test vector", "[psa][psa_cipher][aria]")
|
||||
|
||||
psa_destroy_key(dec_key_id);
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_ARIA_C */
|
||||
|
||||
@@ -85,10 +85,9 @@ TEST_CASE("PSA CMAC AES-128 test", "[psa_cmac]")
|
||||
test_data, sizeof(test_data),
|
||||
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
|
||||
&cmac_length);
|
||||
ESP_LOGI("PSA CMAC AES-128", "Status: %ld", status);
|
||||
|
||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(16, cmac_length);
|
||||
ESP_LOG_BUFFER_HEXDUMP("CMAC AES-128", cmac, cmac_length, ESP_LOG_INFO);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
|
||||
|
||||
// Verify CMAC
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "unity.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER
|
||||
|
||||
static const uint8_t key_256[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
@@ -206,3 +209,4 @@ TEST_CASE("PSA ARIA-GCM one-shot", "[psa-gcm]")
|
||||
/* Destroy the key */
|
||||
psa_destroy_key(key_id);
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER */
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
#error "SHA256 is disabled in mbedtls config"
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_AES_C)
|
||||
#if (!defined(MBEDTLS_AES_C) && !defined(PSA_WANT_KEY_TYPE_AES))
|
||||
#error "AES support is disabled in mbedtls config"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -464,11 +464,7 @@ components/log/host_test/log_test/main/log_test.cpp
|
||||
components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py
|
||||
components/mbedtls/port/aes/esp_aes_xts.c
|
||||
components/mbedtls/port/include/aes/esp_aes.h
|
||||
components/mbedtls/port/include/aes_alt.h
|
||||
components/mbedtls/port/include/bignum_impl.h
|
||||
components/mbedtls/port/include/sha1_alt.h
|
||||
components/mbedtls/port/include/sha256_alt.h
|
||||
components/mbedtls/port/include/sha512_alt.h
|
||||
components/mbedtls/port/sha/parallel_engine/sha.c
|
||||
components/protocomm/include/transports/protocomm_console.h
|
||||
components/protocomm/include/transports/protocomm_httpd.h
|
||||
|
||||
Reference in New Issue
Block a user