Merge branch 'feat/support_aes_block_and_dma_modes_during_runtime' into 'master'

Support AES block and DMA modes during runtime

Closes IDFGH-15251 and IDF-2594

See merge request espressif/esp-idf!40917
This commit is contained in:
Harshal Patil
2025-09-23 19:46:49 +05:30
24 changed files with 989 additions and 1495 deletions

View File

@@ -6,4 +6,7 @@ set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(crypto_test)

View File

@@ -30,14 +30,13 @@ endif()
if(CONFIG_SOC_AES_SUPPORTED)
list(APPEND srcs "aes/test_aes.c"
"$ENV{IDF_PATH}/components/mbedtls/port/aes/esp_aes_common.c"
"aes/aes_block.c")
"$ENV{IDF_PATH}/components/mbedtls/port/aes/esp_aes.c")
list(APPEND priv_include_dirs "$ENV{IDF_PATH}/components/mbedtls/port/include"
"$ENV{IDF_PATH}/components/mbedtls/port/aes/include")
if(CONFIG_SOC_AES_SUPPORT_DMA)
list(APPEND priv_include_dirs "$ENV{IDF_PATH}/components/mbedtls/port/aes/dma/include")
list(APPEND srcs "$ENV{IDF_PATH}/components/mbedtls/port/aes/dma/esp_aes.c")
if(NOT CONFIG_SOC_AES_GDMA)
list(APPEND srcs "$ENV{IDF_PATH}/components/mbedtls/port/aes/dma/esp_aes_crypto_dma_impl.c")
else()

View File

@@ -1,111 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "esp_crypto_periph_clk.h"
#include "hal/aes_types.h"
#include "hal/aes_hal.h"
#include "hal/aes_ll.h"
#if SOC_AES_SUPPORTED
#include "aes_block.h"
void aes_crypt_cbc_block(int mode,
uint8_t key_bytes,
const uint8_t key[32],
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output)
{
uint32_t *output_words = (uint32_t *)output;
const uint32_t *input_words = (const uint32_t *)input;
uint32_t *iv_words = (uint32_t *)iv;
unsigned char temp[16];
esp_crypto_aes_enable_periph_clk(true);
/* Sets the key used for AES encryption/decryption */
aes_hal_setkey(key, key_bytes, mode);
if (mode == ESP_AES_DECRYPT) {
while ( length > 0 ) {
memcpy(temp, input_words, 16);
aes_hal_transform_block(input_words, output_words);
output_words[0] = output_words[0] ^ iv_words[0];
output_words[1] = output_words[1] ^ iv_words[1];
output_words[2] = output_words[2] ^ iv_words[2];
output_words[3] = output_words[3] ^ iv_words[3];
memcpy( iv_words, temp, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
} else { // ESP_AES_ENCRYPT
while ( length > 0 ) {
output_words[0] = input_words[0] ^ iv_words[0];
output_words[1] = input_words[1] ^ iv_words[1];
output_words[2] = input_words[2] ^ iv_words[2];
output_words[3] = input_words[3] ^ iv_words[3];
aes_hal_transform_block(output_words, output_words);
memcpy( iv_words, output_words, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
}
esp_crypto_aes_enable_periph_clk(false);
}
void aes_crypt_ctr_block(uint8_t key_bytes,
const uint8_t key[32],
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
int c, i;
size_t n = *nc_off;
esp_crypto_aes_enable_periph_clk(true);
/* Sets the key used for AES encryption/decryption */
aes_hal_setkey(key, key_bytes, ESP_AES_ENCRYPT);
while (length--) {
if ( n == 0 ) {
aes_hal_transform_block(nonce_counter, stream_block);
for ( i = 16; i > 0; i-- ) {
if ( ++nonce_counter[i - 1] != 0 ) {
break;
}
}
}
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
n = ( n + 1 ) & 0x0F;
}
*nc_off = n;
esp_crypto_aes_enable_periph_clk(false);
}
#endif

View File

@@ -1,29 +0,0 @@
/*
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdio.h>
#if SOC_AES_SUPPORTED
void aes_crypt_cbc_block(int mode,
uint8_t key_bytes,
const uint8_t key[32],
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output);
void aes_crypt_ctr_block(uint8_t key_bytes,
const uint8_t key[32],
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
@@ -15,15 +15,10 @@
#include "memory_checks.h"
#include "unity_fixture.h"
#include "esp_log.h"
#include "aes/esp_aes.h"
#include "aes/esp_aes_gcm.h"
#if SOC_AES_SUPPORTED
#include "aes_block.h"
#define AES_BUFFER_SIZE 1600
#define AES_LONG_BUFFER_SIZE 8000
#include "aes/esp_aes.h"
#include "aes/esp_aes_gcm.h"
TEST_GROUP(aes);
@@ -39,17 +34,16 @@ TEST_TEAR_DOWN(aes)
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
}
static void test_cbc_aes(bool is_dma, size_t buffer_size, const uint8_t expected_cipher_end[32])
static void test_cbc_aes(size_t buffer_size, const uint8_t expected_cipher_end[32])
{
esp_aes_context ctx;
unsigned int key_bits = 256;
uint8_t nonce[16];
esp_aes_init(&ctx);
esp_aes_setkey(&ctx, key_256, key_bits);
TEST_ASSERT_EQUAL(0, esp_aes_setkey(&ctx, key_256, KEY_BITS));
uint8_t *chipertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(chipertext);
uint8_t *ciphertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(ciphertext);
uint8_t *plaintext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(plaintext);
uint8_t *decryptedtext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -60,52 +54,34 @@ static void test_cbc_aes(bool is_dma, size_t buffer_size, const uint8_t expected
// Encrypt
memcpy(nonce, iv, 16);
#ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_cbc(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, chipertext);
}
else
#endif
{
aes_crypt_cbc_block(ESP_AES_ENCRYPT, key_bits / 8, key_256, buffer_size, nonce, plaintext, chipertext);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + buffer_size - 32, 32);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cbc(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, ciphertext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
#ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_cbc(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, chipertext, decryptedtext);
}
else
#endif
{
aes_crypt_cbc_block(ESP_AES_DECRYPT, key_bits / 8, key_256, buffer_size, nonce, chipertext, decryptedtext);
}
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cbc(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, ciphertext, decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx);
// Free dynamically allocated memory
heap_caps_free(chipertext);
heap_caps_free(ciphertext);
heap_caps_free(plaintext);
heap_caps_free(decryptedtext);
}
static void test_ctr_aes(bool is_dma, size_t buffer_size, const uint8_t expected_cipher_end[32])
static void test_ctr_aes(size_t buffer_size, const uint8_t expected_cipher_end[32])
{
esp_aes_context ctx;
unsigned int key_bits = 256;
uint8_t nonce[16];
uint8_t stream_block[16];
size_t nc_off = 0;
esp_aes_init(&ctx);
esp_aes_setkey(&ctx, key_256, key_bits);
TEST_ASSERT_EQUAL(0, esp_aes_setkey(&ctx, key_256, KEY_BITS));
uint8_t *chipertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(chipertext);
uint8_t *ciphertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(ciphertext);
uint8_t *plaintext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(plaintext);
uint8_t *decryptedtext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -116,53 +92,35 @@ static void test_ctr_aes(bool is_dma, size_t buffer_size, const uint8_t expected
// Encrypt
memcpy(nonce, iv, 16);
#ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, plaintext, chipertext);
}
else
#endif
{
aes_crypt_ctr_block(key_bits / 8, key_256, buffer_size, &nc_off, nonce, stream_block, plaintext, chipertext);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + buffer_size - 32, 32);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, plaintext, ciphertext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
nc_off = 0;
#ifdef SOC_AES_SUPPORT_DMA
if (is_dma) {
esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, chipertext, decryptedtext);
}
else
#endif
{
aes_crypt_ctr_block(key_bits / 8, key_256, buffer_size, &nc_off, nonce, stream_block, chipertext, decryptedtext);
}
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ctr(&ctx, buffer_size, &nc_off, nonce, stream_block, ciphertext, decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx);
// Free dynamically allocated memory
heap_caps_free(chipertext);
heap_caps_free(ciphertext);
heap_caps_free(plaintext);
heap_caps_free(decryptedtext);
}
#ifdef SOC_AES_SUPPORT_DMA
#if SOC_AES_SUPPORT_DMA
static void test_ofb_aes(size_t buffer_size, const uint8_t expected_cipher_end[32])
{
esp_aes_context ctx;
unsigned int key_bits = 256;
uint8_t nonce[16];
size_t nc_off = 0;
esp_aes_init(&ctx);
esp_aes_setkey(&ctx, key_256, key_bits);
TEST_ASSERT_EQUAL(0, esp_aes_setkey(&ctx, key_256, KEY_BITS));
uint8_t *chipertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(chipertext);
uint8_t *ciphertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(ciphertext);
uint8_t *plaintext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(plaintext);
uint8_t *decryptedtext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -173,19 +131,19 @@ static void test_ofb_aes(size_t buffer_size, const uint8_t expected_cipher_end[3
// Encrypt
memcpy(nonce, iv, 16);
esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + buffer_size - 32, 32);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, plaintext, ciphertext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
nc_off = 0;
esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_ofb(&ctx, buffer_size, &nc_off, nonce, ciphertext, decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx);
// Free dynamically allocated memory
heap_caps_free(chipertext);
heap_caps_free(ciphertext);
heap_caps_free(plaintext);
heap_caps_free(decryptedtext);
}
@@ -193,14 +151,13 @@ static void test_ofb_aes(size_t buffer_size, const uint8_t expected_cipher_end[3
static void test_cfb8_aes(size_t buffer_size, const uint8_t expected_cipher_end[32])
{
esp_aes_context ctx;
unsigned int key_bits = 256;
uint8_t nonce[16];
esp_aes_init(&ctx);
esp_aes_setkey(&ctx, key_256, key_bits);
TEST_ASSERT_EQUAL(0, esp_aes_setkey(&ctx, key_256, KEY_BITS));
uint8_t *chipertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(chipertext);
uint8_t *ciphertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(ciphertext);
uint8_t *plaintext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(plaintext);
uint8_t *decryptedtext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -211,18 +168,18 @@ static void test_cfb8_aes(size_t buffer_size, const uint8_t expected_cipher_end[
// Encrypt
memcpy(nonce, iv, 16);
esp_aes_crypt_cfb8(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + buffer_size - 32, 32);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb8(&ctx, ESP_AES_ENCRYPT, buffer_size, nonce, plaintext, ciphertext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
esp_aes_crypt_cfb8(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb8(&ctx, ESP_AES_DECRYPT, buffer_size, nonce, ciphertext, decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx);
// Free dynamically allocated memory
heap_caps_free(chipertext);
heap_caps_free(ciphertext);
heap_caps_free(plaintext);
heap_caps_free(decryptedtext);
}
@@ -230,15 +187,14 @@ static void test_cfb8_aes(size_t buffer_size, const uint8_t expected_cipher_end[
static void test_cfb128_aes(size_t buffer_size, const uint8_t expected_cipher_end[32])
{
esp_aes_context ctx;
unsigned int key_bits = 256;
uint8_t nonce[16];
size_t nc_off = 0;
esp_aes_init(&ctx);
esp_aes_setkey(&ctx, key_256, key_bits);
TEST_ASSERT_EQUAL(0, esp_aes_setkey(&ctx, key_256, KEY_BITS));
uint8_t *chipertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(chipertext);
uint8_t *ciphertext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(ciphertext);
uint8_t *plaintext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(plaintext);
uint8_t *decryptedtext = heap_caps_calloc(buffer_size, sizeof(uint8_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
@@ -249,25 +205,25 @@ static void test_cfb128_aes(size_t buffer_size, const uint8_t expected_cipher_en
// Encrypt
memcpy(nonce, iv, 16);
esp_aes_crypt_cfb128(&ctx, ESP_AES_ENCRYPT, buffer_size, &nc_off, nonce, plaintext, chipertext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, chipertext + buffer_size - 32, 32);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb128(&ctx, ESP_AES_ENCRYPT, buffer_size, &nc_off, nonce, plaintext, ciphertext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + buffer_size - 32, 32);
// Decrypt
nc_off = 0;
memcpy(nonce, iv, 16);
esp_aes_crypt_cfb128(&ctx, ESP_AES_DECRYPT, buffer_size, &nc_off, nonce, chipertext, decryptedtext);
TEST_ASSERT_EQUAL(0, esp_aes_crypt_cfb128(&ctx, ESP_AES_DECRYPT, buffer_size, &nc_off, nonce, ciphertext, decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, buffer_size);
esp_aes_free(&ctx);
// Free dynamically allocated memory
heap_caps_free(chipertext);
heap_caps_free(ciphertext);
heap_caps_free(plaintext);
heap_caps_free(decryptedtext);
}
#if SOC_GCM_SUPPORTED
#define CIPHER_ID_AES 2
static void test_gcm_aes(size_t length, const uint8_t expected_last_block[16], const uint8_t expected_tag[16])
{
uint8_t iv[16];
@@ -296,17 +252,17 @@ static void test_gcm_aes(size_t length, const uint8_t expected_last_block[16], c
memcpy(iv_buf, iv, iv_length);
esp_aes_gcm_init(&ctx);
TEST_ASSERT(esp_aes_gcm_setkey(&ctx, CIPHER_ID_AES, key, 8 * sizeof(key)) == 0);
TEST_ASSERT_EQUAL(0, esp_aes_gcm_setkey(&ctx, CIPHER_ID_AES, key, 8 * sizeof(key)));
/* Encrypt and authenticate */
TEST_ASSERT(esp_aes_gcm_crypt_and_tag(&ctx, ESP_AES_ENCRYPT, length, iv_buf, iv_length, add, add_length, plaintext, ciphertext, tag_len, tag_buf_encrypt) == 0);
TEST_ASSERT_EQUAL(0, esp_aes_gcm_crypt_and_tag(&ctx, ESP_AES_ENCRYPT, length, iv_buf, iv_length, add, add_length, plaintext, ciphertext, tag_len, tag_buf_encrypt));
size_t offset = length > 16 ? length - 16 : 0;
/* Sanity check: make sure the last ciphertext block matches what we expect to see. */
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, ciphertext + offset, MIN(16, length));
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf_encrypt, tag_len);
/* Decrypt and authenticate */
TEST_ASSERT(esp_aes_gcm_auth_decrypt(&ctx, length, iv_buf, iv_length, add, add_length, expected_tag, tag_len, ciphertext, decryptedtext) == 0);
TEST_ASSERT_EQUAL(0, esp_aes_gcm_auth_decrypt(&ctx, length, iv_buf, iv_length, add, add_length, expected_tag, tag_len, ciphertext, decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, length);
esp_aes_gcm_free(&ctx);
@@ -315,148 +271,75 @@ static void test_gcm_aes(size_t length, const uint8_t expected_last_block[16], c
heap_caps_free(ciphertext);
heap_caps_free(decryptedtext);
}
#endif /* SOC_GCM_SUPPORTED */
#endif /* SOC_AES_SUPPORT_DMA */
TEST(aes, cbc_aes_256_block_test)
{
const uint8_t expected_cipher_end[32] = {
0x3e, 0x68, 0x8a, 0x02, 0xe6, 0xf2, 0x6a, 0x9e,
0x9b, 0xb2, 0xc0, 0xc4, 0x63, 0x63, 0xd9, 0x25,
0x51, 0xdc, 0xc2, 0x71, 0x96, 0xb3, 0xe5, 0xcd,
0xbd, 0x0e, 0xf2, 0xef, 0xa9, 0xab, 0xab, 0x2d,
};
test_cbc_aes(0,AES_BUFFER_SIZE, expected_cipher_end);
test_cbc_aes(AES_BUFFER_SIZE_BLOCK_MODE, expected_cipher_end_block_cbc);
}
TEST(aes, ctr_aes_256_block_test)
{
const uint8_t expected_cipher_end[32] = {
0xed, 0xa4, 0xa4, 0xe0, 0xee, 0x1d, 0x73, 0x96,
0xd3, 0xde, 0xaa, 0xe0, 0xb7, 0x76, 0x7f, 0xcb,
0x0f, 0xe8, 0x64, 0xf0, 0xd3, 0xf1, 0xab, 0x14,
0x5a, 0x89, 0x47, 0xb4, 0x32, 0xed, 0x41, 0x9c,
};
test_ctr_aes(0, AES_BUFFER_SIZE, expected_cipher_end);
test_ctr_aes(AES_BUFFER_SIZE_BLOCK_MODE, expected_cipher_end_block_ctr);
}
#if SOC_AES_SUPPORT_DMA
TEST(aes, cbc_aes_256_dma_test)
{
const uint8_t expected_cipher_end[32] = {
0x3e, 0x68, 0x8a, 0x02, 0xe6, 0xf2, 0x6a, 0x9e,
0x9b, 0xb2, 0xc0, 0xc4, 0x63, 0x63, 0xd9, 0x25,
0x51, 0xdc, 0xc2, 0x71, 0x96, 0xb3, 0xe5, 0xcd,
0xbd, 0x0e, 0xf2, 0xef, 0xa9, 0xab, 0xab, 0x2d,
};
test_cbc_aes(1, AES_BUFFER_SIZE, expected_cipher_end);
test_cbc_aes(AES_BUFFER_SIZE_DMA_MODE, expected_cipher_end_dma_cbc);
}
TEST(aes, ctr_aes_256_dma_test)
{
const uint8_t expected_cipher_end[32] = {
0xed, 0xa4, 0xa4, 0xe0, 0xee, 0x1d, 0x73, 0x96,
0xd3, 0xde, 0xaa, 0xe0, 0xb7, 0x76, 0x7f, 0xcb,
0x0f, 0xe8, 0x64, 0xf0, 0xd3, 0xf1, 0xab, 0x14,
0x5a, 0x89, 0x47, 0xb4, 0x32, 0xed, 0x41, 0x9c,
};
test_ctr_aes(1, AES_BUFFER_SIZE, expected_cipher_end);
test_ctr_aes(AES_BUFFER_SIZE_DMA_MODE, expected_cipher_end_dma_ctr);
}
TEST(aes, ofb_aes_256_dma_test)
{
const uint8_t expected_cipher_end[] = {
0x9e, 0x12, 0x10, 0xf0, 0x3f, 0xbf, 0xf8, 0x34,
0x08, 0x86, 0x7c, 0x02, 0x6b, 0x8a, 0x76, 0xa6,
0x25, 0x9f, 0x34, 0x61, 0x8b, 0x89, 0x60, 0x16,
0xe6, 0xa0, 0xa5, 0xb6, 0x5b, 0x0a, 0xeb, 0x1f,
};
test_ofb_aes(AES_BUFFER_SIZE, expected_cipher_end);
test_ofb_aes(AES_BUFFER_SIZE_DMA_MODE, expected_cipher_end_dma_ofb);
}
TEST(aes, cfb8_aes_256_dma_test)
{
const uint8_t expected_cipher_end[] = {
0x76, 0x95, 0x22, 0x72, 0x3f, 0x44, 0x2d, 0x32,
0x3e, 0x85, 0xb8, 0xe8, 0xf7, 0x38, 0x04, 0xd6,
0x4a, 0xc5, 0xdb, 0x2c, 0x46, 0x5f, 0x5b, 0xa2,
0x24, 0x4a, 0x35, 0xcb, 0xe5, 0x94, 0x71, 0x21,
};
test_cfb8_aes(AES_BUFFER_SIZE, expected_cipher_end);
test_cfb8_aes(AES_BUFFER_SIZE_DMA_MODE, expected_cipher_end_dma_cfb8);
}
TEST(aes, cfb128_aes_256_dma_test)
{
const uint8_t expected_cipher_end[] = {
0xd0, 0x9b, 0x2e, 0x25, 0xd5, 0xeb, 0x08, 0xbd,
0xd8, 0x7e, 0x64, 0xde, 0x35, 0x2b, 0xb1, 0x53,
0xf8, 0x3a, 0xf7, 0xa8, 0x1e, 0x96, 0xaa, 0xce,
0xa4, 0xf2, 0x8a, 0x2d, 0x01, 0xd5, 0x62, 0xa0,
};
test_cfb128_aes(AES_BUFFER_SIZE, expected_cipher_end);
test_cfb128_aes(AES_BUFFER_SIZE_DMA_MODE, expected_cipher_end_dma_cfb128);
}
#if CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT
TEST(aes, cbc_aes_256_long_dma_test)
{
const uint8_t expected_cipher_end[32] = {
0xd1, 0x32, 0x62, 0x9d, 0x2f, 0x0e, 0x1d, 0x27,
0x0e, 0x2b, 0x53, 0x0b, 0x81, 0x53, 0x92, 0x69,
0x8a, 0x9c, 0x25, 0xb1, 0x77, 0x2b, 0xe4, 0x80,
0x3a, 0xee, 0xdc, 0xbb, 0x80, 0xd6, 0x1a, 0x42,
};
test_cbc_aes(1, AES_LONG_BUFFER_SIZE, expected_cipher_end);
test_cbc_aes(AES_BUFFER_SIZE_DMA_MODE_WITH_INTERRUPT, expected_cipher_end_dma_cbc_with_interrupt);
}
TEST(aes, ctr_aes_256_long_dma_test)
{
const uint8_t expected_cipher_end[32] = {
0x30, 0x8e, 0x3b, 0x27, 0x54, 0x85, 0x58, 0x20,
0x1a, 0xa6, 0xca, 0x81, 0x12, 0x23, 0x7f, 0x01,
0xba, 0x27, 0x72, 0x44, 0xa9, 0x00, 0x42, 0x8a,
0x4e, 0xda, 0x26, 0xf9, 0xd9, 0x0b, 0xb1, 0xa5,
};
test_ctr_aes(1, AES_LONG_BUFFER_SIZE, expected_cipher_end);
test_ctr_aes(AES_BUFFER_SIZE_DMA_MODE_WITH_INTERRUPT, expected_cipher_end_dma_ctr_with_interrupt);
}
TEST(aes, ofb_aes_256_long_dma_test)
{
const uint8_t expected_cipher_end[] = {
0xdc, 0xd1, 0x8a, 0x5c, 0x38, 0xb4, 0xce, 0xdf,
0x21, 0xa0, 0xa4, 0x0b, 0x87, 0xbb, 0xdf, 0xf5,
0x42, 0xc6, 0xe2, 0x1f, 0x9f, 0x93, 0x3b, 0xa4,
0xdd, 0xb0, 0xce, 0xf0, 0x98, 0x47, 0x23, 0x20,
};
test_ofb_aes(AES_LONG_BUFFER_SIZE, expected_cipher_end);
test_ofb_aes(AES_BUFFER_SIZE_DMA_MODE_WITH_INTERRUPT, expected_cipher_end_dma_ofb_with_interrupt);
}
TEST(aes, cfb8_aes_256_long_dma_test)
{
const uint8_t expected_cipher_end[] = {
0x9a, 0x2a, 0xaf, 0xec, 0xd1, 0xf3, 0xd2, 0xe2,
0xf5, 0x62, 0x16, 0x5c, 0x42, 0x8f, 0xc1, 0xa3,
0x34, 0x05, 0x9b, 0xa5, 0x44, 0x02, 0xff, 0xf4,
0x6b, 0xca, 0x3c, 0xac, 0xff, 0x6e, 0xb6, 0x7a,
};
test_cfb8_aes(AES_LONG_BUFFER_SIZE, expected_cipher_end);
test_cfb8_aes(AES_BUFFER_SIZE_DMA_MODE_WITH_INTERRUPT, expected_cipher_end_dma_cfb8_with_interrupt);
}
TEST(aes, cfb128_aes_256_long_dma_test)
{
const uint8_t expected_cipher_end[] = {
0x6c, 0x63, 0xa9, 0x19, 0x12, 0x89, 0x57, 0xeb,
0xbe, 0x73, 0x17, 0x62, 0xc6, 0xfc, 0xf0, 0x43,
0x6d, 0x49, 0x6b, 0xc6, 0x35, 0xf8, 0xc1, 0x48,
0xe2, 0xb7, 0xb1, 0x6f, 0x26, 0x9f, 0x04, 0x8b,
};
test_cfb128_aes(AES_LONG_BUFFER_SIZE, expected_cipher_end);
test_cfb128_aes(AES_BUFFER_SIZE_DMA_MODE_WITH_INTERRUPT, expected_cipher_end_dma_cfb128_with_interrupt);
}
#endif
#if SOC_GCM_SUPPORTED
TEST(aes, gcm_aes_dma_test)
{
size_t length = 16;
@@ -487,6 +370,7 @@ TEST(aes, gcm_aes_long_dma_test)
test_gcm_aes(length, expected_last_block, expected_tag);
}
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
#endif /* SOC_GCM_SUPPORTED */
#endif /* SOC_AES_SUPPORT_DMA */
TEST_GROUP_RUNNER(aes)
@@ -506,10 +390,12 @@ TEST_GROUP_RUNNER(aes)
RUN_TEST_CASE(aes, cfb8_aes_256_long_dma_test);
RUN_TEST_CASE(aes, cfb128_aes_256_long_dma_test);
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
#if SOC_GCM_SUPPORTED
RUN_TEST_CASE(aes, gcm_aes_dma_test);
#if CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT
RUN_TEST_CASE(aes, gcm_aes_long_dma_test);
#endif /* CONFIG_CRYPTO_TESTAPP_USE_AES_INTERRUPT */
#endif /* SOC_GCM_SUPPORTED */
#endif /* SOC_AES_SUPPORT_DMA */
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -25,4 +25,98 @@ static const uint8_t iv[] = {
0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
};
#define AES_BUFFER_SIZE_BLOCK_MODE 128 /* Shorter data length to test the block mode */
const uint8_t expected_cipher_end_block_cbc[32] = {
0x89, 0xc1, 0x6b, 0x75, 0x19, 0x03, 0x0f, 0x1d,
0xdb, 0xfb, 0xb9, 0x90, 0x02, 0x30, 0x34, 0x3c,
0xf0, 0x12, 0xa1, 0xa3, 0x87, 0x0f, 0x61, 0x32,
0x58, 0xdd, 0x20, 0xbe, 0xff, 0x30, 0x58, 0x38,
};
const uint8_t expected_cipher_end_block_ctr[32] = {
0xd4, 0xf8, 0x63, 0xd3, 0x1f, 0xfa, 0xfa, 0xf5,
0x42, 0x7e, 0x3e, 0xad, 0x63, 0x99, 0x69, 0x3d,
0x91, 0x40, 0xfa, 0xa8, 0x74, 0x89, 0xae, 0xbe,
0xee, 0x5c, 0xea, 0x45, 0xef, 0x77, 0x2b, 0x83,
};
#define AES_BUFFER_SIZE_DMA_MODE 1600 /* Longer data length to test the DMA mode */
/* Expected cipher text's last 32 bytes for 1600 bytes data length */
const uint8_t expected_cipher_end_dma_cbc[32] = {
0x3e, 0x68, 0x8a, 0x02, 0xe6, 0xf2, 0x6a, 0x9e,
0x9b, 0xb2, 0xc0, 0xc4, 0x63, 0x63, 0xd9, 0x25,
0x51, 0xdc, 0xc2, 0x71, 0x96, 0xb3, 0xe5, 0xcd,
0xbd, 0x0e, 0xf2, 0xef, 0xa9, 0xab, 0xab, 0x2d,
};
const uint8_t expected_cipher_end_dma_ctr[32] = {
0xed, 0xa4, 0xa4, 0xe0, 0xee, 0x1d, 0x73, 0x96,
0xd3, 0xde, 0xaa, 0xe0, 0xb7, 0x76, 0x7f, 0xcb,
0x0f, 0xe8, 0x64, 0xf0, 0xd3, 0xf1, 0xab, 0x14,
0x5a, 0x89, 0x47, 0xb4, 0x32, 0xed, 0x41, 0x9c,
};
const uint8_t expected_cipher_end_dma_ofb[32] = {
0x9e, 0x12, 0x10, 0xf0, 0x3f, 0xbf, 0xf8, 0x34,
0x08, 0x86, 0x7c, 0x02, 0x6b, 0x8a, 0x76, 0xa6,
0x25, 0x9f, 0x34, 0x61, 0x8b, 0x89, 0x60, 0x16,
0xe6, 0xa0, 0xa5, 0xb6, 0x5b, 0x0a, 0xeb, 0x1f,
};
const uint8_t expected_cipher_end_dma_cfb8[32] = {
0x76, 0x95, 0x22, 0x72, 0x3f, 0x44, 0x2d, 0x32,
0x3e, 0x85, 0xb8, 0xe8, 0xf7, 0x38, 0x04, 0xd6,
0x4a, 0xc5, 0xdb, 0x2c, 0x46, 0x5f, 0x5b, 0xa2,
0x24, 0x4a, 0x35, 0xcb, 0xe5, 0x94, 0x71, 0x21,
};
const uint8_t expected_cipher_end_dma_cfb128[32] = {
0xd0, 0x9b, 0x2e, 0x25, 0xd5, 0xeb, 0x08, 0xbd,
0xd8, 0x7e, 0x64, 0xde, 0x35, 0x2b, 0xb1, 0x53,
0xf8, 0x3a, 0xf7, 0xa8, 0x1e, 0x96, 0xaa, 0xce,
0xa4, 0xf2, 0x8a, 0x2d, 0x01, 0xd5, 0x62, 0xa0,
};
#define AES_BUFFER_SIZE_DMA_MODE_WITH_INTERRUPT 8000
const uint8_t expected_cipher_end_dma_cbc_with_interrupt[32] = {
0xd1, 0x32, 0x62, 0x9d, 0x2f, 0x0e, 0x1d, 0x27,
0x0e, 0x2b, 0x53, 0x0b, 0x81, 0x53, 0x92, 0x69,
0x8a, 0x9c, 0x25, 0xb1, 0x77, 0x2b, 0xe4, 0x80,
0x3a, 0xee, 0xdc, 0xbb, 0x80, 0xd6, 0x1a, 0x42,
};
const uint8_t expected_cipher_end_dma_ctr_with_interrupt[32] = {
0x30, 0x8e, 0x3b, 0x27, 0x54, 0x85, 0x58, 0x20,
0x1a, 0xa6, 0xca, 0x81, 0x12, 0x23, 0x7f, 0x01,
0xba, 0x27, 0x72, 0x44, 0xa9, 0x00, 0x42, 0x8a,
0x4e, 0xda, 0x26, 0xf9, 0xd9, 0x0b, 0xb1, 0xa5,
};
const uint8_t expected_cipher_end_dma_ofb_with_interrupt[32] = {
0xdc, 0xd1, 0x8a, 0x5c, 0x38, 0xb4, 0xce, 0xdf,
0x21, 0xa0, 0xa4, 0x0b, 0x87, 0xbb, 0xdf, 0xf5,
0x42, 0xc6, 0xe2, 0x1f, 0x9f, 0x93, 0x3b, 0xa4,
0xdd, 0xb0, 0xce, 0xf0, 0x98, 0x47, 0x23, 0x20,
};
const uint8_t expected_cipher_end_dma_cfb8_with_interrupt[32] = {
0x9a, 0x2a, 0xaf, 0xec, 0xd1, 0xf3, 0xd2, 0xe2,
0xf5, 0x62, 0x16, 0x5c, 0x42, 0x8f, 0xc1, 0xa3,
0x34, 0x05, 0x9b, 0xa5, 0x44, 0x02, 0xff, 0xf4,
0x6b, 0xca, 0x3c, 0xac, 0xff, 0x6e, 0xb6, 0x7a,
};
const uint8_t expected_cipher_end_dma_cfb128_with_interrupt[32] = {
0x6c, 0x63, 0xa9, 0x19, 0x12, 0x89, 0x57, 0xeb,
0xbe, 0x73, 0x17, 0x62, 0xc6, 0xfc, 0xf0, 0x43,
0x6d, 0x49, 0x6b, 0xc6, 0x35, 0xf8, 0xc1, 0x48,
0xe2, 0xb7, 0xb1, 0x6f, 0x26, 0x9f, 0x04, 0x8b,
};
#define KEY_BITS 256
#endif /* SOC_AES_SUPPORTED */

View File

@@ -6,3 +6,6 @@ CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x8000
# Enable block and DMA modes for AES
CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM=y

View File

@@ -210,14 +210,6 @@ if(CONFIG_SOC_SHA_SUPPORTED)
endif()
endif()
if(CONFIG_SOC_AES_SUPPORTED)
if(CONFIG_SOC_AES_SUPPORT_DMA)
set(AES_PERIPHERAL_TYPE "dma")
else()
set(AES_PERIPHERAL_TYPE "block")
endif()
endif()
if(SHA_PERIPHERAL_TYPE STREQUAL "core")
target_include_directories(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/sha/core/include")
@@ -229,7 +221,7 @@ if(SHA_PERIPHERAL_TYPE STREQUAL "core")
target_sources(mbedcrypto PRIVATE "${SHA_CORE_SRCS}")
endif()
if(AES_PERIPHERAL_TYPE STREQUAL "dma")
if(CONFIG_SOC_AES_SUPPORT_DMA)
if(NOT CONFIG_SOC_AES_GDMA)
set(AES_DMA_SRCS "${COMPONENT_DIR}/port/aes/dma/esp_aes_crypto_dma_impl.c")
else()
@@ -242,7 +234,7 @@ if(AES_PERIPHERAL_TYPE STREQUAL "dma")
target_sources(mbedcrypto PRIVATE "${AES_DMA_SRCS}")
endif()
if((SHA_PERIPHERAL_TYPE STREQUAL "core" AND CONFIG_SOC_SHA_SUPPORT_DMA) OR AES_PERIPHERAL_TYPE STREQUAL "dma")
if((SHA_PERIPHERAL_TYPE STREQUAL "core" AND CONFIG_SOC_SHA_SUPPORT_DMA) OR CONFIG_SOC_AES_SUPPORT_DMA)
target_link_libraries(mbedcrypto PRIVATE idf::esp_mm)
if(CONFIG_SOC_SHA_GDMA OR CONFIG_SOC_AES_GDMA)
if(CONFIG_SOC_AXI_DMA_EXT_MEM_ENC_ALIGNMENT)
@@ -263,7 +255,7 @@ if(CONFIG_SOC_AES_SUPPORTED)
target_include_directories(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/include")
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_xts.c"
"${COMPONENT_DIR}/port/aes/esp_aes_common.c"
"${COMPONENT_DIR}/port/aes/${AES_PERIPHERAL_TYPE}/esp_aes.c"
"${COMPONENT_DIR}/port/aes/esp_aes.c"
)
endif()

View File

@@ -1071,42 +1071,6 @@ menu "mbedTLS"
This reduces code size, but disables support for 192-bit and
256-bit AES keys.
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC
bool "Enable AES hardware's pseudo round function"
default n
depends on SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION
help
Enables the pseudo round function of the AES peripheral.
Enabling this would impact the performance of the AES operations.
For more info regarding the performance impact, please checkout
the pseudo round function section of the security guide.
choice MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH
prompt "Strength of the pseudo rounds function"
depends on MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC
default MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW
help
The strength of the pseudo rounds functions can be configured to low, medium and high.
You can configure the strength of the pseudo rounds functions according to your use cases,
for example, increasing the strength would provide higher security but would slow down the
hardware AES encryption/decryption operations.
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW
bool "Low"
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM
bool "Medium"
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_HIGH
bool "High"
endchoice
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH
int
default 1 if MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW
default 2 if MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM
default 3 if MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_HIGH
config MBEDTLS_CMAC_C
bool "Enable CMAC mode for block ciphers"
default y
@@ -1647,6 +1611,57 @@ menu "mbedTLS"
priority level and any level from 1 to 3 can be selected (based on the availability).
Note: Higher value indicates high interrupt priority.
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC
bool "Enable AES hardware's pseudo round function"
default n
depends on SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION && MBEDTLS_HARDWARE_AES
help
Enables the pseudo round function of the AES peripheral.
Enabling this would impact the performance of the AES operations.
For more info regarding the performance impact, please checkout
the pseudo round function section of the security guide.
choice MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH
prompt "Strength of the pseudo rounds function"
depends on MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC
default MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW
help
The strength of the pseudo rounds functions can be configured to low, medium and high.
You can configure the strength of the pseudo rounds functions according to your use cases,
for example, increasing the strength would provide higher security but would slow down the
hardware AES encryption/decryption operations.
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW
bool "Low"
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM
bool "Medium"
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_HIGH
bool "High"
endchoice
config MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH
int
default 1 if MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW
default 2 if MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM
default 3 if MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_HIGH
config MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
bool "Enable performance optimisation for the small data length hardware AES operations"
depends on MBEDTLS_HARDWARE_AES && SOC_AES_SUPPORT_DMA
default y
help
This option enables dynamically switching between the hardware
AES peripheral's block and DMA modes based on the length of the input data,
thus, significantly speeding up the AES operations with shorter data lengths.
For example, NVS encryption/decryption operations, TLS communication, etc.
with smaller data lengths.
It is enabled by default due to the significant performance impact but note that
it also increases the binary size by ~1.2 KB as it pulls in the peripheral's block
mode code as well.
config MBEDTLS_PK_RSA_ALT_SUPPORT
bool "Enable RSA alt support"
default y

View File

@@ -48,7 +48,7 @@ target_include_directories(mbedcrypto PRIVATE ${crypto_port_inc_dirs})
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/esp_tee/esp_tee_crypto_shared_gdma.c")
# AES implementation
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/dma/esp_aes.c"
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes.c"
"${COMPONENT_DIR}/port/aes/dma/esp_aes_dma_core.c")
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_common.c"

View File

@@ -1,579 +0,0 @@
/**
* \brief AES block cipher, ESP block hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include <string.h>
#include "mbedtls/aes.h"
#include "mbedtls/platform_util.h"
#include "esp_log.h"
#include "aes/esp_aes.h"
#include "soc/hwcrypto_periph.h"
#include "soc/soc_caps.h"
#include <sys/lock.h>
#include "hal/aes_hal.h"
#include "hal/aes_ll.h"
#include "esp_aes_internal.h"
#include <freertos/FreeRTOS.h>
#include <stdio.h>
#include "esp_private/esp_crypto_lock_internal.h"
static const char *TAG = "esp-aes";
/* AES uses a spinlock mux not a lock as the underlying block operation
only takes 208 cycles (to write key & compute block), +600 cycles
for DPORT protection but +3400 cycles again if you use a full sized lock.
For CBC, CFB, etc. this may mean that interrupts are disabled for a longer
period of time for bigger lengths. However at the moment this has to happen
anyway due to DPORT protection...
*/
static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
void esp_aes_acquire_hardware( void )
{
portENTER_CRITICAL(&aes_spinlock);
/* Enable AES hardware */
AES_RCC_ATOMIC() {
aes_ll_enable_bus_clock(true);
aes_ll_reset_register();
}
}
void esp_aes_release_hardware( void )
{
/* Disable AES hardware */
AES_RCC_ATOMIC() {
aes_ll_enable_bus_clock(false);
}
portEXIT_CRITICAL(&aes_spinlock);
}
/* Run a single 16 byte block of AES, using the hardware engine.
*
* Call only while holding esp_aes_acquire_hardware().
*
* The function esp_aes_block zeroises the output buffer in the case of following conditions:
* 1. If key is not written in the hardware
* 2. If the fault injection check failed
*/
static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
{
uint32_t i0, i1, i2, i3;
const uint32_t *input_words = (uint32_t *)input;
uint32_t *output_words = (uint32_t *)output;
/* If no key is written to hardware yet, either the user hasn't called
mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
know which mode to use - or a fault skipped the
key write to hardware. Treat this as a fatal error and zero the output block.
*/
if (ctx->key_in_hardware != ctx->key_bytes) {
mbedtls_platform_zeroize(output, 16);
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
i0 = input_words[0];
i1 = input_words[1];
i2 = input_words[2];
i3 = input_words[3];
#ifdef CONFIG_MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC
esp_aes_enable_pseudo_rounds(CONFIG_MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH);
#endif /* CONFIG_MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC */
aes_hal_transform_block(input, output);
/* Physical security check: Verify the AES accelerator actually ran, and wasn't
skipped due to external fault injection while starting the peripheral.
Note that i0,i1,i2,i3 are copied from input buffer in case input==output.
Bypassing this check requires at least one additional fault.
*/
if (i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
// calling zeroing functions to narrow the
// window for a double-fault of the abort step, here
memset(output, 0, 16);
mbedtls_platform_zeroize(output, 16);
abort();
}
return 0;
}
static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
const unsigned char *output )
{
if (!ctx) {
ESP_LOGD(TAG, "No AES context supplied");
return -1;
}
if (!input) {
ESP_LOGD(TAG, "No input supplied");
return -1;
}
if (!output) {
ESP_LOGD(TAG, "No output supplied");
return -1;
}
return 0;
}
/*
* AES-ECB block encryption
*/
int esp_internal_aes_encrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware();
return r;
}
/*
* AES-ECB block decryption
*/
int esp_internal_aes_decrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware();
return r;
}
/*
* AES-ECB block encryption/decryption
*/
int esp_aes_crypt_ecb(esp_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware();
return r;
}
/*
* AES-CBC buffer encryption/decryption
*/
int esp_aes_crypt_cbc(esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGD(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
uint32_t *output_words = (uint32_t *)output;
const uint32_t *input_words = (const uint32_t *)input;
uint32_t *iv_words = (uint32_t *)iv;
unsigned char temp[16];
if ( length % 16 ) {
return ( ERR_ESP_AES_INVALID_INPUT_LENGTH );
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
if ( mode == ESP_AES_DECRYPT ) {
while ( length > 0 ) {
memcpy(temp, input_words, 16);
ret = esp_aes_block(ctx, input_words, output_words);
if (ret != 0) {
goto cleanup;
}
output_words[0] = output_words[0] ^ iv_words[0];
output_words[1] = output_words[1] ^ iv_words[1];
output_words[2] = output_words[2] ^ iv_words[2];
output_words[3] = output_words[3] ^ iv_words[3];
memcpy( iv_words, temp, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
} else { // ESP_AES_ENCRYPT
while ( length > 0 ) {
output_words[0] = input_words[0] ^ iv_words[0];
output_words[1] = input_words[1] ^ iv_words[1];
output_words[2] = input_words[2] ^ iv_words[2];
output_words[3] = input_words[3] ^ iv_words[3];
ret = esp_aes_block(ctx, output_words, output_words);
if (ret != 0) {
goto cleanup;
}
memcpy( iv_words, output_words, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
}
ret = 0;
cleanup:
esp_aes_release_hardware();
return ret;
}
/*
* AES-CFB128 buffer encryption/decryption
*/
int esp_aes_crypt_cfb128(esp_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv_off) {
ESP_LOGE(TAG, "No IV offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
int c;
size_t n = *iv_off;
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
if ( mode == ESP_AES_DECRYPT ) {
while ( length-- ) {
if ( n == 0 ) {
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
goto cleanup;
}
}
c = *input++;
*output++ = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
n = ( n + 1 ) & 0x0F;
}
} else {
while ( length-- ) {
if ( n == 0 ) {
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
goto cleanup;
}
}
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
n = ( n + 1 ) & 0x0F;
}
}
*iv_off = n;
ret = 0;
cleanup:
esp_aes_release_hardware();
return ret;
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int esp_aes_crypt_cfb8(esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = -1;
unsigned char c;
unsigned char ov[17];
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
while ( length-- ) {
memcpy( ov, iv, 16 );
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
goto cleanup;
}
if ( mode == ESP_AES_DECRYPT ) {
ov[16] = *input;
}
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
if ( mode == ESP_AES_ENCRYPT ) {
ov[16] = c;
}
memcpy( iv, ov + 1, 16 );
}
ret = 0;
cleanup:
esp_aes_release_hardware();
return ret;
}
/*
* AES-CTR buffer encryption/decryption
*/
int esp_aes_crypt_ctr(esp_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
int c, i, ret = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!stream_block) {
ESP_LOGE(TAG, "No stream supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!nonce_counter) {
ESP_LOGE(TAG, "No nonce supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!nc_off) {
ESP_LOGE(TAG, "No nonce offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
size_t n = *nc_off;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
while ( length-- ) {
if ( n == 0 ) {
ret = esp_aes_block(ctx, nonce_counter, stream_block);
if (ret != 0) {
goto cleanup;
}
for ( i = 16; i > 0; i-- ) {
if ( ++nonce_counter[i - 1] != 0 ) {
break;
}
}
}
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
n = ( n + 1 ) & 0x0F;
}
*nc_off = n;
ret = 0;
cleanup:
esp_aes_release_hardware();
return ret;
}
/*
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
*/
int esp_aes_crypt_ofb(esp_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int ret = -1;
size_t n;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv_off) {
ESP_LOGE(TAG, "No IV offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *iv_off;
if (n > 15) {
return (MBEDTLS_ERR_AES_BAD_INPUT_DATA);
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
while (length--) {
if ( n == 0 ) {
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
goto cleanup;
}
}
*output++ = *input++ ^ iv[n];
n = ( n + 1 ) & 0x0F;
}
*iv_off = n;
ret = 0;
cleanup:
esp_aes_release_hardware();
return ( ret );
}

View File

@@ -1,521 +0,0 @@
/**
* \brief AES block cipher, ESP DMA hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include <string.h>
#include "mbedtls/aes.h"
#include "esp_log.h"
#include "esp_crypto_lock.h"
#include "hal/aes_hal.h"
#include "esp_aes_internal.h"
#include "esp_crypto_periph_clk.h"
#if SOC_AES_GDMA
#define AES_LOCK() esp_crypto_sha_aes_lock_acquire()
#define AES_RELEASE() esp_crypto_sha_aes_lock_release()
#elif SOC_AES_CRYPTO_DMA
#define AES_LOCK() esp_crypto_dma_lock_acquire()
#define AES_RELEASE() esp_crypto_dma_lock_release()
#include "hal/crypto_dma_ll.h"
#endif
static const char *TAG = "esp-aes";
void esp_aes_acquire_hardware( void )
{
/* Released by esp_aes_release_hardware()*/
AES_LOCK();
esp_crypto_aes_enable_periph_clk(true);
}
/* Function to disable AES and Crypto DMA clocks and release locks */
void esp_aes_release_hardware( void )
{
esp_crypto_aes_enable_periph_clk(false);
AES_RELEASE();
}
static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
unsigned char *output )
{
if (!ctx) {
ESP_LOGE(TAG, "No AES context supplied");
return -1;
}
if (!input) {
ESP_LOGE(TAG, "No input supplied");
return -1;
}
if (!output) {
ESP_LOGE(TAG, "No output supplied");
return -1;
}
return 0;
}
/*
* AES-ECB single block encryption
*/
int esp_internal_aes_encrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
esp_aes_release_hardware();
return r;
}
/*
* AES-ECB single block decryption
*/
int esp_internal_aes_decrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
esp_aes_release_hardware();
return r;
}
/*
* AES-ECB block encryption/decryption
*/
int esp_aes_crypt_ecb(esp_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
esp_aes_release_hardware();
return r;
}
/*
* AES-CBC buffer encryption/decryption
*/
int esp_aes_crypt_cbc(esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int r = -1;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
/* For CBC input length should be multiple of
* AES BLOCK BYTES
* */
if ( (length % AES_BLOCK_BYTES) || (length == 0) ) {
return ERR_ESP_AES_INVALID_INPUT_LENGTH;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC);
aes_hal_set_iv(iv);
r = esp_aes_process_dma(ctx, input, output, length, NULL);
if (r != 0) {
goto cleanup;
}
aes_hal_read_iv(iv);
cleanup:
esp_aes_release_hardware();
return r;
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int esp_aes_crypt_cfb8(esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
int r = -1;
unsigned char c;
unsigned char ov[17];
size_t block_bytes = length - (length % AES_BLOCK_BYTES);
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
/* The DMA engine will only output correct IV if it runs
full blocks of input in CFB8 mode
*/
esp_aes_acquire_hardware();
if (block_bytes > 0) {
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8);
aes_hal_set_iv(iv);
r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
if (r != 0) {
goto cleanup;
}
aes_hal_read_iv(iv);
length -= block_bytes;
input += block_bytes;
output += block_bytes;
}
// Process remaining bytes block-at-a-time in ECB mode
if (length > 0) {
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, MBEDTLS_AES_ENCRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
while ( length-- ) {
memcpy( ov, iv, 16 );
r = esp_aes_process_dma(ctx, iv, iv, AES_BLOCK_BYTES, NULL);
if (r != 0) {
goto cleanup;
}
if ( mode == MBEDTLS_AES_DECRYPT ) {
ov[16] = *input;
}
c = *output++ = ( iv[0] ^ *input++ );
if ( mode == MBEDTLS_AES_ENCRYPT ) {
ov[16] = c;
}
memcpy( iv, ov + 1, 16 );
}
}
r = 0;
cleanup:
esp_aes_release_hardware();
return r;
}
/*
* AES-CFB128 buffer encryption/decryption
*/
int esp_aes_crypt_cfb128(esp_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
uint8_t c;
size_t stream_bytes = 0;
size_t n;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv_off) {
ESP_LOGE(TAG, "No IV offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
n = *iv_off;
/* First process the *iv_off bytes
* which are pending from the previous call to this API
*/
while (n > 0 && length > 0) {
if (mode == MBEDTLS_AES_ENCRYPT) {
iv[n] = *output++ = *input++ ^ iv[n];
} else {
c = *input++;
*output++ = c ^ iv[n];
iv[n] = c;
}
n = (n + 1) % AES_BLOCK_BYTES;
length--;
}
if (length > 0) {
stream_bytes = length % AES_BLOCK_BYTES;
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128);
aes_hal_set_iv(iv);
int r = esp_aes_process_dma(ctx, input, output, length, iv);
if (r != 0) {
esp_aes_release_hardware();
return r;
}
if (stream_bytes == 0) {
// if we didn't need the partial 'stream block' then the new IV is in the IV register
aes_hal_read_iv(iv);
} else {
// if we did process a final partial block the new IV is already processed via DMA (and has some bytes of output in it),
// In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next
// block uses ciphertext as its IV input)
//
// Note: It may be more efficient to not process the partial block via DMA in this case.
if (mode == MBEDTLS_AES_DECRYPT) {
memcpy(iv, input + length - stream_bytes, stream_bytes);
}
}
esp_aes_release_hardware();
}
*iv_off = n + stream_bytes;
return 0;
}
/*
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
*/
int esp_aes_crypt_ofb(esp_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
size_t n;
size_t stream_bytes = 0;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!iv_off) {
ESP_LOGE(TAG, "No IV offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *iv_off;
/* If there is an offset then use the output of the previous AES block
(the updated IV) to calculate the new output */
while (n > 0 && length > 0) {
*output++ = (*input++ ^ iv[n]);
n = (n + 1) & 0xF;
length--;
}
if (length > 0) {
stream_bytes = (length % AES_BLOCK_BYTES);
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB);
aes_hal_set_iv(iv);
int r = esp_aes_process_dma(ctx, input, output, length, iv);
if (r != 0) {
esp_aes_release_hardware();
return r;
}
aes_hal_read_iv(iv);
esp_aes_release_hardware();
}
*iv_off = n + stream_bytes;
return 0;
}
#ifdef CONFIG_MBEDTLS_CIPHER_MODE_CTR
/*
* AES-CTR buffer encryption/decryption
*/
int esp_aes_crypt_ctr(esp_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
size_t n;
if (esp_aes_validate_input(ctx, input, output)) {
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!stream_block) {
ESP_LOGE(TAG, "No stream supplied");
return -1;
}
if (!nonce_counter) {
ESP_LOGE(TAG, "No nonce supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!nc_off) {
ESP_LOGE(TAG, "No nonce offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *nc_off;
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
/* Process any unprocessed bytes left in stream block from
last operation */
while (n > 0 && length > 0) {
*output++ = (unsigned char)(*input++ ^ stream_block[n]);
n = (n + 1) & 0xF;
length--;
}
if (length > 0) {
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR);
aes_hal_set_iv(nonce_counter);
int r = esp_aes_process_dma(ctx, input, output, length, stream_block);
if (r != 0) {
esp_aes_release_hardware();
return r;
}
aes_hal_read_iv(nonce_counter);
esp_aes_release_hardware();
}
*nc_off = n + (length % AES_BLOCK_BYTES);
return 0;
}
#endif /* CONFIG_MBEDTLS_CIPHER_MODE_CTR */

View File

@@ -15,6 +15,7 @@
extern "C" {
#endif
#if SOC_AES_SUPPORT_DMA
/**
* @brief Start the DMA engine
*
@@ -41,6 +42,7 @@ bool esp_aes_dma_done(const crypto_dma_desc_t *output);
*/
void esp_aes_intr_alloc(void);
#endif /* SOC_AES_SUPPORT_DMA */
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,749 @@
/*
* \brief AES block and DMA hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* SPDX-FileCopyrightText: The Mbed TLS Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2025 Espressif Systems (Shanghai) CO LTD
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
#include <string.h>
#include "mbedtls/aes.h"
#include "esp_log.h"
#include "esp_crypto_lock.h"
#include "hal/aes_hal.h"
#include "esp_aes_internal.h"
#include "esp_crypto_periph_clk.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if SOC_AES_GDMA
#define AES_LOCK() esp_crypto_sha_aes_lock_acquire()
#define AES_RELEASE() esp_crypto_sha_aes_lock_release()
#elif SOC_AES_CRYPTO_DMA
#define AES_LOCK() esp_crypto_dma_lock_acquire()
#define AES_RELEASE() esp_crypto_dma_lock_release()
#include "hal/crypto_dma_ll.h"
#endif
static const char *TAG = "esp-aes";
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
#if CONFIG_IDF_TARGET_ESP32P4
#define AES_DMA_MODE_THRESHOLD 512
#else
#define AES_DMA_MODE_THRESHOLD 128
#endif
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
#if !SOC_AES_SUPPORT_DMA
#include <freertos/FreeRTOS.h>
/* AES uses a spinlock mux not a lock as the underlying block operation
only takes 208 cycles (to write key & compute block), +600 cycles
for DPORT protection but +3400 cycles again if you use a full sized lock.
For CBC, CFB, etc. this may mean that interrupts are disabled for a longer
period of time for bigger lengths. However at the moment this has to happen
anyway due to DPORT protection...
*/
static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
#endif
void esp_aes_acquire_hardware( void )
{
/* Released by esp_aes_release_hardware()*/
#if SOC_AES_SUPPORT_DMA
AES_LOCK();
#else
portENTER_CRITICAL(&aes_spinlock);
#endif
esp_crypto_aes_enable_periph_clk(true);
}
/* Function to disable AES and Crypto DMA clocks and release locks */
void esp_aes_release_hardware( void )
{
esp_crypto_aes_enable_periph_clk(false);
#if SOC_AES_SUPPORT_DMA
AES_RELEASE();
#else
portEXIT_CRITICAL(&aes_spinlock);
#endif
}
static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
unsigned char *output, unsigned char *iv, bool validate_iv)
{
if (!ctx) {
ESP_LOGE(TAG, "No AES context supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!input) {
ESP_LOGE(TAG, "No input supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!output) {
ESP_LOGE(TAG, "No output supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!valid_key_length(ctx)) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
if (validate_iv && !iv) {
ESP_LOGE(TAG, "No IV supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
return 0;
}
#if !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
/* Run a single 16 byte block of AES, using the hardware engine.
*
* Call only while holding esp_aes_acquire_hardware().
*
* The function esp_aes_block zeroises the output buffer in the case of following conditions:
* 1. If key is not written in the hardware
* 2. If the fault injection check failed
*/
static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
{
uint32_t i0, i1, i2, i3;
const uint32_t *input_words = (uint32_t *)input;
uint32_t *output_words = (uint32_t *)output;
/* If no key is written to hardware yet, either the user hasn't called
mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't
know which mode to use - or a fault skipped the
key write to hardware. Treat this as a fatal error and zero the output block.
*/
if (ctx->key_in_hardware != ctx->key_bytes) {
mbedtls_platform_zeroize(output, 16);
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
i0 = input_words[0];
i1 = input_words[1];
i2 = input_words[2];
i3 = input_words[3];
#ifdef CONFIG_MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC
esp_aes_enable_pseudo_rounds(CONFIG_MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH);
#endif /* CONFIG_MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC */
aes_hal_transform_block(input, output);
/* Physical security check: Verify the AES accelerator actually ran, and wasn't
skipped due to external fault injection while starting the peripheral.
Note that i0,i1,i2,i3 are copied from input buffer in case input==output.
Bypassing this check requires at least one additional fault.
*/
if (i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
// calling zeroing functions to narrow the
// window for a double-fault of the abort step, here
memset(output, 0, 16);
mbedtls_platform_zeroize(output, 16);
abort();
}
return 0;
}
#endif /* !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
/*
* AES-ECB single block encryption
*/
int esp_internal_aes_encrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
return esp_aes_crypt_ecb(ctx, ESP_AES_ENCRYPT, input, output);
}
/*
* AES-ECB single block decryption
*/
int esp_internal_aes_decrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
return esp_aes_crypt_ecb(ctx, ESP_AES_DECRYPT, input, output);
}
/*
* AES-ECB block encryption/decryption
*/
int esp_aes_crypt_ecb(esp_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
// Use helper for validation
int ret = esp_aes_validate_input(ctx, input, output, NULL, false);
if (ret != 0) {
return ret;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
#if SOC_AES_SUPPORT_DMA && !CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
ret = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
#else
ret = esp_aes_block(ctx, input, output);
#endif
esp_aes_release_hardware();
return ret;
}
/*
* AES-CBC buffer encryption/decryption
*/
int esp_aes_crypt_cbc(esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
// Use helpers for validation
int ret = esp_aes_validate_input(ctx, input, output, iv, true);
if (ret != 0) {
return ret;
}
/* For CBC input length should be multiple of AES BLOCK BYTES */
if ( (length % AES_BLOCK_BYTES) || (length == 0) ) {
return ERR_ESP_AES_INVALID_INPUT_LENGTH;
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
#if SOC_AES_SUPPORT_DMA
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
if (length > AES_DMA_MODE_THRESHOLD) {
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC);
aes_hal_set_iv(iv);
ret = esp_aes_process_dma(ctx, input, output, length, NULL);
if (ret != 0) {
goto cleanup;
}
aes_hal_read_iv(iv);
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
} else
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
#endif /* SOC_AES_SUPPORT_DMA */
#if !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
{
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
uint32_t *output_words = (uint32_t *)output;
const uint32_t *input_words = (const uint32_t *)input;
uint32_t *iv_words = (uint32_t *)iv;
unsigned char temp[16];
if (mode == ESP_AES_DECRYPT) {
while (length > 0) {
memcpy(temp, input_words, 16);
ret = esp_aes_block(ctx, input_words, output_words);
if (ret != 0) {
goto cleanup;
}
output_words[0] = output_words[0] ^ iv_words[0];
output_words[1] = output_words[1] ^ iv_words[1];
output_words[2] = output_words[2] ^ iv_words[2];
output_words[3] = output_words[3] ^ iv_words[3];
memcpy( iv_words, temp, 16 );
input_words += 4;
output_words += 4;
length -= 16;
}
} else { // ESP_AES_ENCRYPT
while (length > 0) {
output_words[0] = input_words[0] ^ iv_words[0];
output_words[1] = input_words[1] ^ iv_words[1];
output_words[2] = input_words[2] ^ iv_words[2];
output_words[3] = input_words[3] ^ iv_words[3];
ret = esp_aes_block(ctx, output_words, output_words);
if (ret != 0) {
goto cleanup;
}
memcpy(iv_words, output_words, 16);
input_words += 4;
output_words += 4;
length -= 16;
}
}
ret = 0;
}
#endif /* !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
cleanup:
esp_aes_release_hardware();
return ret;
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int esp_aes_crypt_cfb8(esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
unsigned char c;
unsigned char ov[17];
// Use helpers for validation
int ret = esp_aes_validate_input(ctx, input, output, iv, true);
if (ret != 0) {
return ret;
}
esp_aes_acquire_hardware();
#if SOC_AES_SUPPORT_DMA
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
if (length > AES_DMA_MODE_THRESHOLD) {
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
size_t block_bytes = length - (length % AES_BLOCK_BYTES);
/* The DMA engine will only output correct IV if it runs
full blocks of input in CFB8 mode
*/
if (block_bytes > 0) {
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8);
aes_hal_set_iv(iv);
ret = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
if (ret != 0) {
goto cleanup;
}
aes_hal_read_iv(iv);
length -= block_bytes;
input += block_bytes;
output += block_bytes;
}
// Process remaining bytes block-at-a-time in ECB mode
if (length > 0) {
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
while ( length-- ) {
memcpy( ov, iv, 16 );
ret = esp_aes_process_dma(ctx, iv, iv, AES_BLOCK_BYTES, NULL);
if (ret != 0) {
goto cleanup;
}
if ( mode == ESP_AES_DECRYPT ) {
ov[16] = *input;
}
c = *output++ = ( iv[0] ^ *input++ );
if ( mode == ESP_AES_ENCRYPT ) {
ov[16] = c;
}
memcpy( iv, ov + 1, 16 );
}
}
ret = 0;
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
} else
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
#endif /* SOC_AES_SUPPORT_DMA */
#if !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
{
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
while (length--) {
memcpy( ov, iv, 16 );
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
goto cleanup;
}
if (mode == ESP_AES_DECRYPT) {
ov[16] = *input;
}
c = *output++ = (unsigned char)(iv[0] ^ *input++);
if (mode == ESP_AES_ENCRYPT) {
ov[16] = c;
}
memcpy( iv, ov + 1, 16 );
}
ret = 0;
}
#endif /* !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
cleanup:
esp_aes_release_hardware();
return ret;
}
/*
* AES-CFB128 buffer encryption/decryption
*/
int esp_aes_crypt_cfb128(esp_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
uint8_t c;
size_t n;
// Use helpers for validation
int ret = esp_aes_validate_input(ctx, input, output, iv, true);
if (ret != 0) {
return ret;
}
if (!iv_off) {
ESP_LOGE(TAG, "No IV offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *iv_off;
#if SOC_AES_SUPPORT_DMA
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
if (length > AES_DMA_MODE_THRESHOLD) {
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
size_t stream_bytes = 0;
/* First process the *iv_off bytes
* which are pending from the previous call to this API
*/
while (n > 0 && length > 0) {
if (mode == ESP_AES_ENCRYPT) {
iv[n] = *output++ = *input++ ^ iv[n];
} else {
c = *input++;
*output++ = c ^ iv[n];
iv[n] = c;
}
n = (n + 1) % AES_BLOCK_BYTES;
length--;
}
if (length > 0) {
stream_bytes = length % AES_BLOCK_BYTES;
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128);
aes_hal_set_iv(iv);
ret = esp_aes_process_dma(ctx, input, output, length, iv);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
if (stream_bytes == 0) {
// if we didn't need the partial 'stream block' then the new IV is in the IV register
aes_hal_read_iv(iv);
} else {
// if we did process a final partial block the new IV is already processed via DMA (and has some bytes of output in it),
// In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next
// block uses ciphertext as its IV input)
//
// Note: It may be more efficient to not process the partial block via DMA in this case.
if (mode == ESP_AES_DECRYPT) {
memcpy(iv, input + length - stream_bytes, stream_bytes);
}
}
esp_aes_release_hardware();
}
*iv_off = n + stream_bytes;
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
} else
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
#endif /* SOC_AES_SUPPORT_DMA */
#if !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
{
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
if (mode == ESP_AES_DECRYPT) {
while (length--) {
if (n == 0) {
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
}
c = *input++;
*output++ = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c;
n = (n + 1) & 0x0F;
}
} else {
while (length--) {
if ( n == 0 ) {
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
}
iv[n] = *output++ = (unsigned char)(iv[n] ^ *input++);
n = ( n + 1 ) & 0x0F;
}
}
esp_aes_release_hardware();
*iv_off = n;
}
#endif /* !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
return 0;
}
/*
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
*/
int esp_aes_crypt_ofb(esp_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
size_t n;
// Use helpers for validation
int ret = esp_aes_validate_input(ctx, input, output, iv, true);
if (ret != 0) {
return ret;
}
if (!iv_off) {
ESP_LOGE(TAG, "No IV offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *iv_off;
#if SOC_AES_SUPPORT_DMA
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
if (length > AES_DMA_MODE_THRESHOLD) {
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
size_t stream_bytes = 0;
/* If there is an offset then use the output of the previous AES block
(the updated IV) to calculate the new output */
while (n > 0 && length > 0) {
*output++ = (*input++ ^ iv[n]);
n = (n + 1) & 0xF;
length--;
}
if (length > 0) {
stream_bytes = (length % AES_BLOCK_BYTES);
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB);
aes_hal_set_iv(iv);
ret = esp_aes_process_dma(ctx, input, output, length, iv);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
aes_hal_read_iv(iv);
esp_aes_release_hardware();
}
*iv_off = n + stream_bytes;
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
} else
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
#endif /* SOC_AES_SUPPORT_DMA */
#if !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
{
// TODO: Check if this is necessary as the DMA version does not have this check
if (n > 15) {
return (MBEDTLS_ERR_AES_BAD_INPUT_DATA);
}
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
while (length--) {
if (n == 0) {
ret = esp_aes_block(ctx, iv, iv);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
}
*output++ = *input++ ^ iv[n];
n = (n + 1) & 0x0F;
}
esp_aes_release_hardware();
*iv_off = n;
}
#endif /* !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
return 0;
}
/*
* AES-CTR buffer encryption/decryption
*/
int esp_aes_crypt_ctr(esp_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
size_t n;
// Use helper for validation
int ret = esp_aes_validate_input(ctx, input, output, NULL, false);
if (ret != 0) {
return ret;
}
if (!stream_block) {
ESP_LOGE(TAG, "No stream supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!nonce_counter) {
ESP_LOGE(TAG, "No nonce supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
if (!nc_off) {
ESP_LOGE(TAG, "No nonce offset supplied");
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
}
n = *nc_off;
#if SOC_AES_SUPPORT_DMA
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
if (length > AES_DMA_MODE_THRESHOLD) {
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
/* Process any unprocessed bytes left in stream block from
last operation */
while (n > 0 && length > 0) {
*output++ = (unsigned char)(*input++ ^ stream_block[n]);
n = (n + 1) & 0xF;
length--;
}
if (length > 0) {
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR);
aes_hal_set_iv(nonce_counter);
ret = esp_aes_process_dma(ctx, input, output, length, stream_block);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
aes_hal_read_iv(nonce_counter);
esp_aes_release_hardware();
}
*nc_off = n + (length % AES_BLOCK_BYTES);
#if CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
} else
#endif /* CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
#endif /* SOC_AES_SUPPORT_DMA */
#if !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM
{
esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
int c, i;
while (length--) {
if (n == 0) {
ret = esp_aes_block(ctx, nonce_counter, stream_block);
if (ret != 0) {
esp_aes_release_hardware();
return ret;
}
for (i = 16; i > 0; i--) {
if (++nonce_counter[i - 1] != 0) {
break;
}
}
}
c = *input++;
*output++ = (unsigned char)(c ^ stream_block[n]);
n = (n + 1) & 0x0F;
}
esp_aes_release_hardware();
*nc_off = n;
}
#endif /* !SOC_AES_SUPPORT_DMA || CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM */
return 0;
}

View File

@@ -345,7 +345,6 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16
/** XTS-AES buffer encryption/decryption */
int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output );
#ifdef __cplusplus
}
#endif

View File

@@ -10,12 +10,13 @@
#include "esp_private/gdma.h"
#include "esp_err.h"
#include "soc/lldesc.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if (SOC_AES_GDMA) || (SOC_SHA_GDMA)
/**
* @brief Start a GDMA transfer on the shared crypto DMA channel
* Supports AXI-DMA and AHB-DMA.
@@ -52,6 +53,7 @@ bool esp_crypto_shared_gdma_done(void);
* and need the DMA channel for other peripherals. An example would be doing some processing after disconnecting WiFi
*/
void esp_crypto_shared_gdma_free(void);
#endif /* (SOC_AES_GDMA) || (SOC_SHA_GDMA) */
#ifdef __cplusplus
}

View File

@@ -34,6 +34,7 @@
#include "esp_sha_internal.h"
#include "sha/sha_core.h"
#include "esp_compiler.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize(void *v, size_t n)
@@ -119,7 +120,8 @@ int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char
esp_internal_sha_update_state(ctx);
#if SOC_SHA_SUPPORT_DMA
if (sha_operation_mode(64) == SHA_DMA_MODE) {
// Unlikely to use DMA because data size is 64 bytes which is smaller than the DMA threshold
if (unlikely(sha_operation_mode(64) == SHA_DMA_MODE)) {
int ret = esp_sha_dma(SHA1, data, 64, NULL, 0, ctx->first_block);
if (ret != 0) {
esp_sha_release_hardware();

View File

@@ -34,6 +34,7 @@
#include "esp_sha_internal.h"
#include "sha/sha_core.h"
#include "esp_compiler.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize(void *v, size_t n)
@@ -132,7 +133,8 @@ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned
esp_internal_sha_update_state(ctx);
#if SOC_SHA_SUPPORT_DMA
if (sha_operation_mode(64) == SHA_DMA_MODE) {
// Unlikely to use DMA because data size is 64 bytes which is smaller than the DMA threshold
if (unlikely(sha_operation_mode(64) == SHA_DMA_MODE)) {
int ret = esp_sha_dma(ctx->mode, data, 64, NULL, 0, ctx->first_block);
if (ret != 0) {
esp_sha_release_hardware();

View File

@@ -40,6 +40,7 @@
#include "esp_sha_internal.h"
#include "sha/sha_core.h"
#include "esp_compiler.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize(void *v, size_t n)
@@ -169,7 +170,8 @@ int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx, const unsigned
}
#if SOC_SHA_SUPPORT_DMA
if (sha_operation_mode(128) == SHA_DMA_MODE) {
// Likely to use DMA because data size is 128 bytes which is larger or equal to the DMA threshold
if (likely(sha_operation_mode(128) == SHA_DMA_MODE)) {
ret = esp_sha_dma(ctx->mode, data, 128, NULL, 0, ctx->first_block);
if (ret != 0) {
esp_sha_release_hardware();

View File

@@ -139,22 +139,6 @@ config SOC_XTAL_CLOCK_PATH_DEPENDS_ON_TOP_DOMAIN
bool
default y
config SOC_AES_SUPPORT_DMA
bool
default y
config SOC_AES_GDMA
bool
default y
config SOC_AES_SUPPORT_AES_128
bool
default y
config SOC_AES_SUPPORT_AES_256
bool
default y
config SOC_ADC_PERIPH_NUM
int
default 1

View File

@@ -93,13 +93,13 @@
#define SOC_XTAL_CLOCK_PATH_DEPENDS_ON_TOP_DOMAIN 1
/*-------------------------- AES CAPS -----------------------------------------*/
#define SOC_AES_SUPPORT_DMA (1)
// #define SOC_AES_SUPPORT_DMA (1)
/* Has a centralized DMA, which is shared with all peripherals */
#define SOC_AES_GDMA (1)
// #define SOC_AES_GDMA (1)
#define SOC_AES_SUPPORT_AES_128 (1)
#define SOC_AES_SUPPORT_AES_256 (1)
// #define SOC_AES_SUPPORT_AES_128 (1)
// #define SOC_AES_SUPPORT_AES_256 (1)
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/

View File

@@ -223,6 +223,7 @@ These include:
- Consider disabling some cipher suites listed in the ``TLS Key Exchange Methods`` sub-menu (i.e., :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`).
- Consider disabling :ref:`CONFIG_MBEDTLS_ERROR_STRINGS` if the application is already pulling in mbedTLS error strings through using :cpp:func:`mbedtls_strerror`.
:esp32h2: - For {IDF_TARGET_NAME} v1.2 and above, consider disabling :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM` and :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM` as the software countermeasures for the ECDSA sign operation are not required.
:SOC_AES_SUPPORT_DMA: - Consider disabling :ref:CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM if the application does not involve or require performance optimization for operations that involve small data lengths, such as NVS encryption/decryption or TLS communication when performed on small data segments.
The help text for each option has some more information for reference.

View File

@@ -223,6 +223,7 @@ MbedTLS 功能
- 可以考虑禁用在 ``TLS Key Exchange Methods`` 子菜单中列出的一些密码套件(例如 :ref:`CONFIG_MBEDTLS_KEY_EXCHANGE_RSA`),以减小代码大小。
- 如果应用程序已经通过使用 :cpp:func:`mbedtls_strerror` 拉取 mbedTLS 错误字符串,则可以考虑禁用 :ref:`CONFIG_MBEDTLS_ERROR_STRINGS`
:esp32h2: - 对于 {IDF_TARGET_NAME} v1.2 及以上版本,可以考虑禁用 :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM` 和 :ref:`CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM`,因为无需再使用 ECDSA 签名的软件防护措施。
:SOC_AES_SUPPORT_DMA: - 如果应用程序不涉及或不需要针对小数据长度操作进行性能优化,例如在处理小数据段时进行的 NVS 加密/解密操作、TLS 通信等,可以考虑禁用 :ref:`CONFIG_MBEDTLS_AES_HW_SMALL_DATA_LEN_OPTIM`。
每个选项的帮助文本中都有更多信息可供参考。

View File

@@ -470,8 +470,6 @@ components/lwip/apps/ping/ping.c
components/lwip/include/apps/esp_ping.h
components/lwip/include/apps/ping/ping.h
components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/test_gen_crt_bundle.py
components/mbedtls/port/aes/block/esp_aes.c
components/mbedtls/port/aes/dma/esp_aes.c
components/mbedtls/port/aes/esp_aes_xts.c
components/mbedtls/port/include/aes/esp_aes.h
components/mbedtls/port/include/aes_alt.h