mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 10:47:19 +02:00
fix(mbedtls/gcm): Add support for software fallback for non-AES ciphers in a GCM operation
- Even if the config MBEDTLS_HARDWARE_AES is enabled, we now support fallback to software implementation of GCM operations when non-AES ciphers are used.
This commit is contained in:
@ -402,6 +402,29 @@ menu "mbedTLS"
|
|||||||
mbedTLS will still use the hardware accelerated AES block operation, but
|
mbedTLS will still use the hardware accelerated AES block operation, but
|
||||||
on a single block at a time.
|
on a single block at a time.
|
||||||
|
|
||||||
|
config MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER
|
||||||
|
bool "Enable support for non-AES ciphers in GCM operation"
|
||||||
|
depends on MBEDTLS_HARDWARE_AES
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable this config to support fallback to software definitions for a non-AES
|
||||||
|
cipher GCM operation as we support hardware acceleration only for AES cipher.
|
||||||
|
Some of the non-AES ciphers used in a GCM operation are DES, ARIA, CAMELLIA,
|
||||||
|
CHACHA20, BLOWFISH.
|
||||||
|
|
||||||
|
If this config is disabled, performing a non-AES cipher GCM operation with
|
||||||
|
the config MBEDTLS_HARDWARE_AES enabled will result in calculation of an
|
||||||
|
AES-GCM operation instead for the given input values and thus could lead
|
||||||
|
to failure in certificate validation which would ultimately lead to a SSL
|
||||||
|
handshake failure.
|
||||||
|
|
||||||
|
This config being by-default enabled leads to an increase in binary size
|
||||||
|
footprint of ~2.5KB.
|
||||||
|
In case you are sure that your use case (for example, client and server
|
||||||
|
configurations in case of a TLS handshake) would not involve any GCM
|
||||||
|
operations using a non-AES cipher, you can safely disable this config,
|
||||||
|
leading to reduction in binary size footprint.
|
||||||
|
|
||||||
config MBEDTLS_HARDWARE_MPI
|
config MBEDTLS_HARDWARE_MPI
|
||||||
bool "Enable hardware MPI (bignum) acceleration"
|
bool "Enable hardware MPI (bignum) acceleration"
|
||||||
default y
|
default y
|
||||||
|
Submodule components/mbedtls/mbedtls updated: 89cc7af4bb...09bba150d0
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileContributor: 2016-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
||||||
@ -251,6 +251,27 @@ int esp_aes_gcm_setkey( esp_gcm_context *ctx,
|
|||||||
const unsigned char *key,
|
const unsigned char *key,
|
||||||
unsigned int keybits )
|
unsigned int keybits )
|
||||||
{
|
{
|
||||||
|
/* Fallback to software implementation of GCM operation when a non-AES
|
||||||
|
* cipher is selected, as we support hardware acceleration only for a
|
||||||
|
* GCM operation using AES cipher.
|
||||||
|
*/
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
mbedtls_gcm_free_soft(ctx->ctx_soft);
|
||||||
|
free(ctx->ctx_soft);
|
||||||
|
ctx->ctx_soft = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cipher != MBEDTLS_CIPHER_ID_AES) {
|
||||||
|
ctx->ctx_soft = (mbedtls_gcm_context_soft*) malloc(sizeof(mbedtls_gcm_context_soft));
|
||||||
|
if (ctx->ctx_soft == NULL) {
|
||||||
|
return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
|
||||||
|
}
|
||||||
|
mbedtls_gcm_init_soft(ctx->ctx_soft);
|
||||||
|
return mbedtls_gcm_setkey_soft(ctx->ctx_soft, cipher, key, keybits);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !SOC_AES_SUPPORT_AES_192
|
#if !SOC_AES_SUPPORT_AES_192
|
||||||
if (keybits == 192) {
|
if (keybits == 192) {
|
||||||
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
|
||||||
@ -332,6 +353,14 @@ void esp_aes_gcm_free( esp_gcm_context *ctx)
|
|||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
mbedtls_gcm_free_soft(ctx->ctx_soft);
|
||||||
|
free(ctx->ctx_soft);
|
||||||
|
/* Note that the value of ctx->ctx_soft should be NULL'ed out
|
||||||
|
and here it is taken care by the bzero call below */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
bzero(ctx, sizeof(esp_gcm_context));
|
bzero(ctx, sizeof(esp_gcm_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +370,17 @@ int esp_aes_gcm_starts( esp_gcm_context *ctx,
|
|||||||
const unsigned char *iv,
|
const unsigned char *iv,
|
||||||
size_t iv_len )
|
size_t iv_len )
|
||||||
{
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
ESP_LOGE(TAG, "No AES context supplied");
|
||||||
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
return mbedtls_gcm_starts_soft(ctx->ctx_soft, mode, iv, iv_len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* IV is limited to 2^32 bits, so 2^29 bytes */
|
/* IV is limited to 2^32 bits, so 2^29 bytes */
|
||||||
/* IV is not allowed to be zero length */
|
/* IV is not allowed to be zero length */
|
||||||
if ( iv_len == 0 ||
|
if ( iv_len == 0 ||
|
||||||
@ -348,11 +388,6 @@ int esp_aes_gcm_starts( esp_gcm_context *ctx,
|
|||||||
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
|
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx) {
|
|
||||||
ESP_LOGE(TAG, "No AES context supplied");
|
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iv) {
|
if (!iv) {
|
||||||
ESP_LOGE(TAG, "No IV supplied");
|
ESP_LOGE(TAG, "No IV supplied");
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
@ -407,16 +442,22 @@ int esp_aes_gcm_update_ad( esp_gcm_context *ctx,
|
|||||||
const unsigned char *aad,
|
const unsigned char *aad,
|
||||||
size_t aad_len )
|
size_t aad_len )
|
||||||
{
|
{
|
||||||
/* AD are limited to 2^32 bits, so 2^29 bytes */
|
|
||||||
if ( ( (uint32_t) aad_len ) >> 29 != 0 ) {
|
|
||||||
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
ESP_LOGE(TAG, "No AES context supplied");
|
ESP_LOGE(TAG, "No AES context supplied");
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
return mbedtls_gcm_update_ad_soft(ctx->ctx_soft, aad, aad_len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* AD are limited to 2^32 bits, so 2^29 bytes */
|
||||||
|
if ( ( (uint32_t) aad_len ) >> 29 != 0 ) {
|
||||||
|
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
|
||||||
|
}
|
||||||
|
|
||||||
if ( (aad_len > 0) && !aad) {
|
if ( (aad_len > 0) && !aad) {
|
||||||
ESP_LOGE(TAG, "No aad supplied");
|
ESP_LOGE(TAG, "No aad supplied");
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
@ -442,6 +483,17 @@ int esp_aes_gcm_update( esp_gcm_context *ctx,
|
|||||||
unsigned char *output, size_t output_size,
|
unsigned char *output, size_t output_size,
|
||||||
size_t *output_length )
|
size_t *output_length )
|
||||||
{
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
ESP_LOGE(TAG, "No GCM context supplied");
|
||||||
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
return mbedtls_gcm_update_soft(ctx->ctx_soft, input, input_length, output, output_size, output_length);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t nc_off = 0;
|
size_t nc_off = 0;
|
||||||
uint8_t nonce_counter[AES_BLOCK_BYTES] = {0};
|
uint8_t nonce_counter[AES_BLOCK_BYTES] = {0};
|
||||||
uint8_t stream[AES_BLOCK_BYTES] = {0};
|
uint8_t stream[AES_BLOCK_BYTES] = {0};
|
||||||
@ -452,10 +504,6 @@ int esp_aes_gcm_update( esp_gcm_context *ctx,
|
|||||||
}
|
}
|
||||||
*output_length = input_length;
|
*output_length = input_length;
|
||||||
|
|
||||||
if (!ctx) {
|
|
||||||
ESP_LOGE(TAG, "No GCM context supplied");
|
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
|
||||||
}
|
|
||||||
if (!input) {
|
if (!input) {
|
||||||
ESP_LOGE(TAG, "No input supplied");
|
ESP_LOGE(TAG, "No input supplied");
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
@ -512,6 +560,11 @@ int esp_aes_gcm_finish( esp_gcm_context *ctx,
|
|||||||
size_t *output_length,
|
size_t *output_length,
|
||||||
unsigned char *tag, size_t tag_len )
|
unsigned char *tag, size_t tag_len )
|
||||||
{
|
{
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
return mbedtls_gcm_finish_soft(ctx->ctx_soft, output, output_size, output_length, tag, tag_len);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
size_t nc_off = 0;
|
size_t nc_off = 0;
|
||||||
uint8_t len_block[AES_BLOCK_BYTES] = {0};
|
uint8_t len_block[AES_BLOCK_BYTES] = {0};
|
||||||
uint8_t stream[AES_BLOCK_BYTES] = {0};
|
uint8_t stream[AES_BLOCK_BYTES] = {0};
|
||||||
@ -607,6 +660,16 @@ int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
|
|||||||
size_t tag_len,
|
size_t tag_len,
|
||||||
unsigned char *tag )
|
unsigned char *tag )
|
||||||
{
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
ESP_LOGE(TAG, "No AES context supplied");
|
||||||
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
return mbedtls_gcm_crypt_and_tag_soft(ctx->ctx_soft, mode, length, iv, iv_len, aad, aad_len, input, output, tag_len, tag);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if CONFIG_MBEDTLS_HARDWARE_GCM
|
#if CONFIG_MBEDTLS_HARDWARE_GCM
|
||||||
int ret;
|
int ret;
|
||||||
lldesc_t aad_desc[2] = {};
|
lldesc_t aad_desc[2] = {};
|
||||||
@ -635,11 +698,6 @@ int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
|
|||||||
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
|
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx) {
|
|
||||||
ESP_LOGE(TAG, "No AES context supplied");
|
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iv) {
|
if (!iv) {
|
||||||
ESP_LOGE(TAG, "No IV supplied");
|
ESP_LOGE(TAG, "No IV supplied");
|
||||||
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
return MBEDTLS_ERR_GCM_BAD_INPUT;
|
||||||
@ -727,6 +785,11 @@ int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
|
|||||||
const unsigned char *input,
|
const unsigned char *input,
|
||||||
unsigned char *output )
|
unsigned char *output )
|
||||||
{
|
{
|
||||||
|
#if defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
if (ctx->ctx_soft != NULL) {
|
||||||
|
return mbedtls_gcm_auth_decrypt_soft(ctx->ctx_soft, length, iv, iv_len, aad, aad_len, tag, tag_len, input, output);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
int ret;
|
int ret;
|
||||||
unsigned char check_tag[16];
|
unsigned char check_tag[16];
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -42,6 +42,8 @@ typedef struct {
|
|||||||
const unsigned char *aad; /*!< The additional data. */
|
const unsigned char *aad; /*!< The additional data. */
|
||||||
esp_aes_context aes_ctx;
|
esp_aes_context aes_ctx;
|
||||||
esp_aes_gcm_state gcm_state;
|
esp_aes_gcm_state gcm_state;
|
||||||
|
/* Software context needed for soft fallback for non-AES ciphers */
|
||||||
|
void *ctx_soft;
|
||||||
} esp_gcm_context;
|
} esp_gcm_context;
|
||||||
|
|
||||||
|
|
||||||
|
@ -155,6 +155,12 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_MBEDTLS_HARDWARE_AES
|
#ifdef CONFIG_MBEDTLS_HARDWARE_AES
|
||||||
#define MBEDTLS_GCM_ALT
|
#define MBEDTLS_GCM_ALT
|
||||||
|
#ifdef CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER
|
||||||
|
/* Prefer hardware and fallback to software */
|
||||||
|
#define MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK
|
||||||
|
#else
|
||||||
|
#undef MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* MBEDTLS_SHAxx_ALT to enable hardware SHA support
|
/* MBEDTLS_SHAxx_ALT to enable hardware SHA support
|
||||||
|
81
components/mbedtls/port/include/mbedtls/gcm.h
Normal file
81
components/mbedtls/port/include/mbedtls/gcm.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include_next "mbedtls/gcm.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_GCM_ALT) && defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK is defined, for non-AES GCM
|
||||||
|
* operations we need to fallback to the software function definitions of the
|
||||||
|
* mbedtls GCM layer.
|
||||||
|
* Thus in this case we need declarations for the software funtions.
|
||||||
|
* Please refer mbedtls/include/mbedtls/gcm.h for function documentations
|
||||||
|
*/
|
||||||
|
|
||||||
|
void mbedtls_gcm_init_soft(mbedtls_gcm_context_soft *ctx);
|
||||||
|
|
||||||
|
|
||||||
|
int mbedtls_gcm_setkey_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
mbedtls_cipher_id_t cipher,
|
||||||
|
const unsigned char *key,
|
||||||
|
unsigned int keybits);
|
||||||
|
|
||||||
|
int mbedtls_gcm_starts_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
int mode,
|
||||||
|
const unsigned char *iv, size_t iv_len);
|
||||||
|
|
||||||
|
int mbedtls_gcm_update_ad_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
const unsigned char *add, size_t add_len);
|
||||||
|
|
||||||
|
int mbedtls_gcm_update_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
const unsigned char *input, size_t input_length,
|
||||||
|
unsigned char *output, size_t output_size,
|
||||||
|
size_t *output_length);
|
||||||
|
|
||||||
|
int mbedtls_gcm_finish_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
unsigned char *output, size_t output_size,
|
||||||
|
size_t *output_length,
|
||||||
|
unsigned char *tag, size_t tag_len);
|
||||||
|
|
||||||
|
|
||||||
|
int mbedtls_gcm_crypt_and_tag_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
int mode,
|
||||||
|
size_t length,
|
||||||
|
const unsigned char *iv,
|
||||||
|
size_t iv_len,
|
||||||
|
const unsigned char *add,
|
||||||
|
size_t add_len,
|
||||||
|
const unsigned char *input,
|
||||||
|
unsigned char *output,
|
||||||
|
size_t tag_len,
|
||||||
|
unsigned char *tag);
|
||||||
|
|
||||||
|
|
||||||
|
int mbedtls_gcm_auth_decrypt_soft(mbedtls_gcm_context_soft *ctx,
|
||||||
|
size_t length,
|
||||||
|
const unsigned char *iv,
|
||||||
|
size_t iv_len,
|
||||||
|
const unsigned char *add,
|
||||||
|
size_t add_len,
|
||||||
|
const unsigned char *tag,
|
||||||
|
size_t tag_len,
|
||||||
|
const unsigned char *input,
|
||||||
|
unsigned char *output);
|
||||||
|
|
||||||
|
void mbedtls_gcm_free_soft(mbedtls_gcm_context_soft *ctx);
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_GCM_ALT && MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
Reference in New Issue
Block a user