Merge branch 'feature/aes_hal' into 'master'

AES: refactor and add HAL layer

See merge request espressif/esp-idf!10979
This commit is contained in:
Angus Gratton 2020-12-11 15:39:49 +08:00
commit 8929a9cdb1
42 changed files with 3202 additions and 3297 deletions

View File

@ -17,7 +17,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "mbedtls/sha256.h" #include "mbedtls/sha256.h"
#include "sha/sha_parallel_engine.h" #include "sha/sha_parallel_engine.h"
#include "esp32/aes.h" #include "aes/esp_aes.h"
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
static const char *TAG = "test"; static const char *TAG = "test";

View File

@ -2,7 +2,7 @@
ROM functions for hardware AES support. ROM functions for hardware AES support.
It is not recommended to use these functions directly, It is not recommended to use these functions directly,
use the wrapper functions in esp32/aes.h instead. use the wrapper functions in aes/esp_aes.h instead.
*/ */
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD

View File

@ -28,6 +28,7 @@ if(NOT BOOTLOADER_BUILD)
"soc_hal.c" "soc_hal.c"
"interrupt_controller_hal.c" "interrupt_controller_hal.c"
"sha_hal.c" "sha_hal.c"
"aes_hal.c"
"twai_hal.c" "twai_hal.c"
"twai_hal_iram.c" "twai_hal_iram.c"
"${target}/interrupt_descriptor_table.c") "${target}/interrupt_descriptor_table.c")

227
components/hal/aes_hal.c Normal file
View File

@ -0,0 +1,227 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// 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 HAL layer for AES
#include "hal/aes_hal.h"
#include "hal/aes_ll.h"
#include <stdlib.h>
#include <string.h>
#include "soc/soc_caps.h"
#if SOC_AES_CRYPTO_DMA
#include "soc/crypto_dma_reg.h"
#include "hal/crypto_dma_ll.h"
#elif SOC_AES_GENERAL_DMA
#include "hal/gdma_ll.h"
#endif
uint8_t aes_hal_setkey(const uint8_t *key, size_t key_bytes, int mode)
{
aes_ll_set_mode(mode, key_bytes);
uint8_t key_bytes_in_hardware = aes_ll_write_key(key, key_bytes / 4);
/* Used for fault injection check: all words of key data should have been written to hardware */
return key_bytes_in_hardware;
}
/**
* @brief Busy wait until the AES accelerator is idle
*
*/
static inline void aes_hal_wait_idle(void)
{
while (aes_ll_get_state() != ESP_AES_STATE_IDLE) {
}
}
void aes_hal_transform_block(const void *input_block, void *output_block)
{
aes_ll_write_block(input_block);
aes_ll_start_transform();
aes_hal_wait_idle();
aes_ll_read_block(output_block);
}
#if SOC_AES_SUPPORT_DMA
#if SOC_AES_GENERAL_DMA
/**
* @brief Initialize the DMA
*
* @param input AES input descriptor (outlink)
* @param output AES output descriptor (inlink)
*/
static inline void aes_hal_dma_init(const lldesc_t *input, const lldesc_t *output)
{
/* Update driver when centralized DMA interface implemented, IDF-2192 */
gdma_ll_tx_enable_descriptor_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
gdma_ll_tx_enable_data_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
gdma_ll_rx_enable_descriptor_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
gdma_ll_rx_enable_data_burst(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, false);
gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_LL_PERIPH_ID_AES);
gdma_ll_rx_connect_to_periph(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_LL_PERIPH_ID_AES);
/* An L2 FIFO bigger than 40 bytes is need when accessing external ram */
gdma_ll_tx_extend_fifo_size_to(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, 40);
gdma_ll_rx_extend_l2_fifo_size_to(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, 40);
gdma_ll_tx_set_block_size_psram(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_OUT_EXT_MEM_BK_SIZE_16B);
gdma_ll_rx_set_block_size_psram(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, GDMA_OUT_EXT_MEM_BK_SIZE_16B);
/* Set descriptors */
gdma_ll_tx_set_desc_addr(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, (uint32_t)input);
gdma_ll_rx_set_desc_addr(&GDMA, SOC_GDMA_AES_DMA_CHANNEL, (uint32_t)output);
gdma_ll_rx_reset_channel(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
gdma_ll_tx_reset_channel(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
/* Start transfer */
gdma_ll_tx_start(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
gdma_ll_rx_start(&GDMA, SOC_GDMA_AES_DMA_CHANNEL);
}
static inline bool aes_hal_dma_done(const lldesc_t *output)
{
return (gdma_ll_rx_is_fsm_idle(&GDMA, SOC_GDMA_AES_DMA_CHANNEL) && (output->owner == 0));
}
#endif //SOC_AES_GENERAL_DMA
#if SOC_AES_CRYPTO_DMA
/**
* @brief Initialize the DMA
*
* @param input AES input descriptor (outlink)
* @param output AES output descriptor (inlink)
*/
static inline void aes_hal_dma_init(const lldesc_t *input, const lldesc_t *output)
{
crypto_dma_ll_reset();
crypto_dma_ll_set_mode(CRYPTO_DMA_AES);
/* Set descriptors, input to AES comes from outlink DMA and viceversa */
crypto_dma_ll_outlink_set((uint32_t)input);
crypto_dma_ll_inlink_set((uint32_t)output);
/* Start transfer */
crypto_dma_ll_outlink_start();
crypto_dma_ll_inlink_start();
}
static inline bool aes_hal_dma_done(lldesc_t *output)
{
return (crypto_dma_ll_inlink_is_eof() && (output->owner == 0));
}
#endif //SOC_AES_CRYPTO_DMA
void aes_hal_transform_dma_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks)
{
aes_ll_dma_enable(true);
aes_hal_dma_init(input, output);
/* Write the number of blocks */
aes_ll_set_num_blocks(num_blocks);
/* Start encrypting/decrypting */
aes_ll_start_transform();
}
void aes_hal_transform_dma_finish(void)
{
aes_ll_dma_exit();
aes_ll_dma_enable(false);
}
void aes_hal_mode_init(esp_aes_mode_t mode)
{
/* Set the algorith mode CBC, CFB ... */
aes_ll_set_block_mode(mode);
/* Presently hard-coding the INC function to 32 bit */
if (mode == ESP_AES_BLOCK_MODE_CTR) {
aes_ll_set_inc();
}
}
void aes_hal_set_iv(const uint8_t *iv)
{
aes_ll_set_iv(iv);
}
void aes_hal_read_iv(uint8_t *iv)
{
aes_ll_read_iv(iv);
}
static inline void aes_hal_wait_done(void)
{
while (aes_ll_get_state() != ESP_AES_STATE_DONE) {}
}
void aes_hal_wait_dma_done(lldesc_t *output)
{
/* Checking this if interrupt is used also, to avoid
issues with AES fault injection
*/
aes_hal_wait_done();
/* Wait for DMA write operation to complete */
while (1) {
if ( aes_hal_dma_done(output) ) {
break;
}
}
}
#endif //SOC_AES_SUPPORT_DMA
#if SOC_AES_SUPPORT_GCM
void aes_hal_gcm_calc_hash(uint8_t *gcm_hash)
{
aes_ll_dma_enable(true);
aes_ll_start_transform();
aes_hal_wait_idle();
aes_ll_gcm_read_hash(gcm_hash);
}
void aes_hal_transform_dma_gcm_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks)
{
aes_hal_dma_init(input, output);
/* Write the number of blocks */
aes_ll_set_num_blocks(num_blocks);
/* Start encrypting/decrypting */
aes_ll_cont_transform();
}
void aes_hal_gcm_init(size_t aad_num_blocks, size_t num_valid_bit)
{
aes_ll_gcm_set_aad_num_blocks(aad_num_blocks);
aes_ll_gcm_set_num_valid_bit(num_valid_bit);
}
void aes_hal_gcm_read_tag(uint8_t *tag, size_t tag_len)
{
uint8_t tag_res[TAG_BYTES];
aes_ll_gcm_read_tag(tag_res);
memcpy(tag, tag_res, tag_len);
}
#endif //SOC_AES_SUPPORT_GCM

View File

@ -0,0 +1,137 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// 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.
#pragma once
#include "soc/hwcrypto_reg.h"
#include "soc/dport_access.h"
#include "hal/aes_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief State of AES accelerator, busy or idle
*
*/
typedef enum {
ESP_AES_STATE_BUSY = 0, /* Transform in progress */
ESP_AES_STATE_IDLE, /* AES accelerator is idle */
} esp_aes_state_t;
/**
* @brief Write the encryption/decryption key to hardware
*
* @param key Key to be written to the AES hardware
* @param key_word_len Number of words in the key
*
* @return Number of bytes written to hardware, used for fault injection check,
* if a write was skipped then this sum is likely to be wrong
*/
static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
{
/* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
volatile uint8_t key_bytes_in_hardware = 0;
uint32_t *key_words = (uint32_t *)key;
for (int i = 0; i < key_word_len; i++) {
DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
key_bytes_in_hardware += 4;
}
return key_bytes_in_hardware;
}
/**
* @brief Sets the mode
*
* @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
* @param key_bytes Number of bytes in the key
*/
static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
/* See TRM for the mapping between keylength and mode bit */
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
}
/**
* @brief Writes message block to AES hardware
*
* @param input Block to be written
*/
static inline void aes_ll_write_block(const uint8_t *input)
{
const uint32_t *input_words = (const uint32_t *)input;
uint32_t i0;
uint32_t i1;
uint32_t i2;
uint32_t i3;
/* Storing i0,i1,i2,i3 in registers not an array
helps a lot with optimisations at -Os level */
i0 = input_words[0];
DPORT_REG_WRITE(AES_TEXT_BASE, i0);
i1 = input_words[1];
DPORT_REG_WRITE(AES_TEXT_BASE + 4, i1);
i2 = input_words[2];
DPORT_REG_WRITE(AES_TEXT_BASE + 8, i2);
i3 = input_words[3];
DPORT_REG_WRITE(AES_TEXT_BASE + 12, i3);
}
/**
* @brief Read the AES block
*
* @note If a transform was ran then this is the output
*
* @param output the output of the transform, length = AES_BLOCK_BYTES
*/
static inline void aes_ll_read_block(void *output)
{
uint32_t *output_words = (uint32_t *)output;
esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, AES_BLOCK_WORDS);
}
/**
* @brief Starts block transform
*
*/
static inline void aes_ll_start_transform(void)
{
DPORT_REG_WRITE(AES_START_REG, 1);
}
/**
* @brief Read state of AES accelerator
*
* @return esp_aes_state_t
*/
static inline esp_aes_state_t aes_ll_get_state(void)
{
return DPORT_REG_READ(AES_IDLE_REG);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,235 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// 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.
#pragma once
#include <stdbool.h>
#include "soc/hwcrypto_reg.h"
#include "hal/aes_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief State of AES accelerator, busy, idle or done
*
*/
typedef enum {
ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */
ESP_AES_STATE_BUSY, /* Transform in progress */
ESP_AES_STATE_DONE, /* Transform completed */
} esp_aes_state_t;
/**
* @brief Write the encryption/decryption key to hardware
*
* @param key Key to be written to the AES hardware
* @param key_word_len Number of words in the key
*
* @return volatile number of bytes written to hardware, used for fault injection check
*/
static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
{
/* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
volatile uint8_t key_in_hardware = 0;
uint32_t *key_words = (uint32_t *)key;
for (int i = 0; i < key_word_len; i++) {
REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
key_in_hardware += 4;
}
return key_in_hardware;
}
/**
* @brief Sets the mode
*
* @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
* @param key_bytes Number of bytes in the key
*/
static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
/* See TRM for the mapping between keylength and mode bit */
REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
}
/**
* @brief Writes message block to AES hardware
*
* @param input Block to be written
*/
static inline void aes_ll_write_block(const void *input)
{
const uint32_t *input_words = (const uint32_t *)input;
uint32_t i0, i1, i2, i3;
/* Storing i0,i1,i2,i3 in registers, not in an array
helps a lot with optimisations at -Os level */
i0 = input_words[0];
REG_WRITE(AES_TEXT_IN_BASE, i0);
i1 = input_words[1];
REG_WRITE(AES_TEXT_IN_BASE + 4, i1);
i2 = input_words[2];
REG_WRITE(AES_TEXT_IN_BASE + 8, i2);
i3 = input_words[3];
REG_WRITE(AES_TEXT_IN_BASE + 12, i3);
}
/**
* @brief Read the AES block
*
* @param output the output of the transform, length = AES_BLOCK_BYTES
*/
static inline void aes_ll_read_block(void *output)
{
uint32_t *output_words = (uint32_t *)output;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Starts block transform
*
*/
static inline void aes_ll_start_transform(void)
{
REG_WRITE(AES_TRIGGER_REG, 1);
}
/**
* @brief Read state of AES accelerator
*
* @return esp_aes_state_t
*/
static inline esp_aes_state_t aes_ll_get_state(void)
{
return REG_READ(AES_STATE_REG);
}
/**
* @brief Set mode of operation
*
* @note Only used for DMA transforms
*
* @param mode
*/
static inline void aes_ll_set_block_mode(esp_aes_mode_t mode)
{
REG_WRITE(AES_BLOCK_MODE_REG, mode);
}
/**
* @brief Set AES-CTR counter to INC32
*
* @note Only affects AES-CTR mode
*
*/
static inline void aes_ll_set_inc(void)
{
REG_WRITE(AES_INC_SEL_REG, 0);
}
/**
* @brief Release the DMA
*
*/
static inline void aes_ll_dma_exit(void)
{
REG_WRITE(AES_DMA_EXIT_REG, 0);
}
/**
* @brief Sets the number of blocks to be transformed
*
* @note Only used for DMA transforms
*
* @param num_blocks Number of blocks to transform
*/
static inline void aes_ll_set_num_blocks(size_t num_blocks)
{
REG_WRITE(AES_BLOCK_NUM_REG, num_blocks);
}
/*
* Write IV to hardware iv registers
*/
static inline void aes_ll_set_iv(const uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
for (int i = 0; i < IV_WORDS; i++ ) {
REG_WRITE(&reg_addr_buf[i], iv_words[i]);
}
}
/*
* Read IV from hardware iv registers
*/
static inline void aes_ll_read_iv(uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < IV_WORDS; i++) {
iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Enable or disable DMA mode
*
* @param enable true to enable, false to disable.
*/
static inline void aes_ll_dma_enable(bool enable)
{
REG_WRITE(AES_DMA_ENABLE_REG, enable);
}
/**
* @brief Enable or disable transform completed interrupt
*
* @param enable true to enable, false to disable.
*/
static inline void aes_ll_interrupt_enable(bool enable)
{
REG_WRITE(AES_INT_ENA_REG, enable);
}
/**
* @brief Clears the interrupt
*
*/
static inline void aes_ll_interrupt_clear(void)
{
REG_WRITE(AES_INT_CLR_REG, 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,317 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// 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.
#pragma once
#include <stdbool.h>
#include "soc/hwcrypto_reg.h"
#include "hal/aes_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief State of AES accelerator, busy, idle or done
*
*/
typedef enum {
ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */
ESP_AES_STATE_BUSY, /* Transform in progress */
ESP_AES_STATE_DONE, /* Transform completed */
} esp_aes_state_t;
/**
* @brief Write the encryption/decryption key to hardware
*
* @param key Key to be written to the AES hardware
* @param key_word_len Number of words in the key
*
* @return Number of bytes written to hardware, used for fault injection check
*/
static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
{
/* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
volatile uint8_t key_in_hardware = 0;
uint32_t *key_words = (uint32_t *)key;
for (int i = 0; i < key_word_len; i++) {
REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
key_in_hardware += 4;
}
return key_in_hardware;
}
/**
* @brief Sets the mode
*
* @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
* @param key_bytes Number of bytes in the key
*/
static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
/* See TRM for the mapping between keylength and mode bit */
REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
}
/**
* @brief Writes message block to AES hardware
*
* @param input Block to be written
*/
static inline void aes_ll_write_block(const void *input)
{
const uint32_t *input_words = (const uint32_t *)input;
uint32_t i0, i1, i2, i3;
/* Storing i0,i1,i2,i3 in registers not an array
helps a lot with optimisations at -Os level */
i0 = input_words[0];
REG_WRITE(AES_TEXT_IN_BASE, i0);
i1 = input_words[1];
REG_WRITE(AES_TEXT_IN_BASE + 4, i1);
i2 = input_words[2];
REG_WRITE(AES_TEXT_IN_BASE + 8, i2);
i3 = input_words[3];
REG_WRITE(AES_TEXT_IN_BASE + 12, i3);
}
/**
* @brief Read the AES block
*
* @param output the output of the transform, length = AES_BLOCK_BYTES
*/
static inline void aes_ll_read_block(void *output)
{
uint32_t *output_words = (uint32_t *)output;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Starts block transform
*
*/
static inline void aes_ll_start_transform(void)
{
REG_WRITE(AES_TRIGGER_REG, 1);
}
/**
* @brief Continue a previous started transform
*
* @note Only used when doing GCM
*/
static inline void aes_ll_cont_transform(void)
{
REG_WRITE(AES_CONTINUE_REG, 1);
}
/**
* @brief Read state of AES accelerator
*
* @return esp_aes_state_t
*/
static inline esp_aes_state_t aes_ll_get_state(void)
{
return REG_READ(AES_STATE_REG);
}
/**
* @brief Set mode of operation
*
* @note Only used for DMA transforms
*
* @param mode
*/
static inline void aes_ll_set_block_mode(esp_aes_mode_t mode)
{
REG_WRITE(AES_BLOCK_MODE_REG, mode);
}
/**
* @brief Set AES-CTR counter to INC32
*
* @note Only affects AES-CTR mode
*
*/
static inline void aes_ll_set_inc(void)
{
REG_WRITE(AES_INC_SEL_REG, 0);
}
/**
* @brief Release the DMA
*
*/
static inline void aes_ll_dma_exit(void)
{
REG_WRITE(AES_DMA_EXIT_REG, 0);
}
/**
* @brief Sets the number of blocks to be transformed
*
* @note Only used for DMA transforms
*
* @param num_blocks Number of blocks to transform
*/
static inline void aes_ll_set_num_blocks(size_t num_blocks)
{
REG_WRITE(AES_BLOCK_NUM_REG, num_blocks);
}
/*
* Write IV to hardware iv registers
*/
static inline void aes_ll_set_iv(const uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
for (int i = 0; i < IV_WORDS; i++ ) {
REG_WRITE(&reg_addr_buf[i], iv_words[i]);
}
}
/*
* Read IV from hardware iv registers
*/
static inline void aes_ll_read_iv(uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < IV_WORDS; i++) {
iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Enable or disable DMA mode
*
* @param enable true to enable, false to disable.
*/
static inline void aes_ll_dma_enable(bool enable)
{
REG_WRITE(AES_DMA_ENABLE_REG, enable);
}
/**
* @brief Enable or disable transform completed interrupt
*
* @param enable true to enable, false to disable.
*/
static inline void aes_ll_interrupt_enable(bool enable)
{
REG_WRITE(AES_INT_ENA_REG, enable);
}
/**
* @brief Clears the interrupt
*
*/
static inline void aes_ll_interrupt_clear(void)
{
REG_WRITE(AES_INT_CLR_REG, 1);
}
/**
* @brief Reads the AES-GCM hash sub-key H
*
* @param gcm_hash hash value
*/
static inline void aes_ll_gcm_read_hash(uint8_t *gcm_hash)
{
uint32_t *hash_words = (uint32_t *)gcm_hash;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
hash_words[i] = REG_READ(AES_H_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Sets the number of Additional Authenticated Data (AAD) blocks
*
* @note Only affects AES-GCM
*
* @param aad_num_blocks the number of Additional Authenticated Data (AAD) blocks
*/
static inline void aes_ll_gcm_set_aad_num_blocks(size_t aad_num_blocks)
{
REG_WRITE(AES_AAD_BLOCK_NUM_REG, aad_num_blocks);
}
/**
* @brief Sets the J0 value, for more information see the GCM subchapter in the TRM
*
* @note Only affects AES-GCM
*
* @param j0 J0 value
*/
static inline void aes_ll_gcm_set_j0(const uint8_t *j0)
{
uint32_t *j0_words = (uint32_t *)j0;
uint32_t *reg_addr_buf = (uint32_t *)(AES_J_BASE);
for (int i = 0; i < AES_BLOCK_WORDS; i++ ) {
REG_WRITE(&reg_addr_buf[i], j0_words[i]);
}
}
/**
* @brief Sets the number of effective bits of incomplete blocks in plaintext/cipertext.
*
* @note Only affects AES-GCM
*
* @param num_valid_bits the number of effective bits of incomplete blocks in plaintext/cipertext.
*/
static inline void aes_ll_gcm_set_num_valid_bit(size_t num_valid_bits)
{
REG_WRITE(AES_BIT_VALID_NUM_REG, num_valid_bits);
}
/**
* @brief Read the tag after a AES-GCM transform
*
* @param tag Pointer to where to store the result with length TAG_WORDS
*/
static inline void aes_ll_gcm_read_tag(uint8_t *tag)
{
uint32_t *tag_words = (uint32_t *)tag;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < TAG_WORDS; i++) {
tag_words[i] = REG_READ(AES_T_BASE + (i * REG_WIDTH));
}
}
#ifdef __cplusplus
}
#endif

View File

@ -19,29 +19,28 @@
******************************************************************************/ ******************************************************************************/
#pragma once #pragma once
#include "soc/hwcrypto_reg.h"
#include "soc/dport_reg.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#include "soc/hwcrypto_reg.h"
#include "soc/dport_reg.h"
typedef enum { typedef enum {
CRYPTO_DMA_AES= 0, CRYPTO_DMA_AES= 0,
CRYPTO_DMA_SHA, CRYPTO_DMA_SHA,
} crypto_dma_mode_t; } crypto_dma_mode_t;
/** /**
* @brief Resets set the outlink * @brief Resets the DMA
* *
*/ */
static inline void crypto_dma_ll_outlink_reset(void) static inline void crypto_dma_ll_reset(void)
{ {
SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST); SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST); CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
} }
/** /**
* @brief Selects the crypto DMA mode * @brief Selects the crypto DMA mode
* *
@ -63,6 +62,17 @@ static inline void crypto_dma_ll_outlink_set(uint32_t outlink_addr)
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, outlink_addr & OUT_LINK_REG_OUTLINK_ADDR); SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, outlink_addr & OUT_LINK_REG_OUTLINK_ADDR);
} }
/**
* @brief Sets up the inlink for a transfer
*
* @param inlink_addr Address of the inlink buffer
*/
static inline void crypto_dma_ll_inlink_set(uint32_t inlink_addr)
{
CLEAR_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_ADDR);
SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, inlink_addr & IN_LINK_REG_INLINK_ADDR);
}
/** /**
* @brief Starts the outlink * @brief Starts the outlink
* *
@ -72,6 +82,20 @@ static inline void crypto_dma_ll_outlink_start(void)
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START); SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START);
} }
/**
* @brief Starts the inlink
*
*/
static inline void crypto_dma_ll_inlink_start(void)
{
SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_START);
}
static inline bool crypto_dma_ll_inlink_is_eof(void)
{
return ((REG_READ(CRYPTO_DMA_INT_RAW_REG) & INT_RAW_IN_SUC_EOF) == INT_RAW_IN_SUC_EOF);
}
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,235 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// 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.
#pragma once
#include <stdbool.h>
#include "soc/hwcrypto_reg.h"
#include "hal/aes_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief State of AES accelerator, busy, idle or done
*
*/
typedef enum {
ESP_AES_STATE_IDLE = 0, /* AES accelerator is idle */
ESP_AES_STATE_BUSY, /* Transform in progress */
ESP_AES_STATE_DONE, /* Transform completed */
} esp_aes_state_t;
/**
* @brief Write the encryption/decryption key to hardware
*
* @param key Key to be written to the AES hardware
* @param key_word_len Number of words in the key
*
* @return volatile number of bytes written to hardware, used for fault injection check
*/
static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len)
{
/* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
volatile uint8_t key_in_hardware = 0;
uint32_t *key_words = (uint32_t *)key;
for (int i = 0; i < key_word_len; i++) {
REG_WRITE(AES_KEY_BASE + i * 4, *(key_words + i));
key_in_hardware += 4;
}
return key_in_hardware;
}
/**
* @brief Sets the mode
*
* @param mode ESP_AES_ENCRYPT = 1, or ESP_AES_DECRYPT = 0
* @param key_bytes Number of bytes in the key
*/
static inline void aes_ll_set_mode(int mode, uint8_t key_bytes)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
/* See TRM for the mapping between keylength and mode bit */
REG_WRITE(AES_MODE_REG, mode_reg_base + ((key_bytes / 8) - 2));
}
/**
* @brief Writes message block to AES hardware
*
* @param input Block to be written
*/
static inline void aes_ll_write_block(const void *input)
{
const uint32_t *input_words = (const uint32_t *)input;
uint32_t i0, i1, i2, i3;
/* Storing i0,i1,i2,i3 in registers not an array
helps a lot with optimisations at -Os level */
i0 = input_words[0];
REG_WRITE(AES_TEXT_IN_BASE, i0);
i1 = input_words[1];
REG_WRITE(AES_TEXT_IN_BASE + 4, i1);
i2 = input_words[2];
REG_WRITE(AES_TEXT_IN_BASE + 8, i2);
i3 = input_words[3];
REG_WRITE(AES_TEXT_IN_BASE + 12, i3);
}
/**
* @brief Read the AES block
*
* @param output the output of the transform, length = AES_BLOCK_BYTES
*/
static inline void aes_ll_read_block(void *output)
{
uint32_t *output_words = (uint32_t *)output;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
output_words[i] = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Starts block transform
*
*/
static inline void aes_ll_start_transform(void)
{
REG_WRITE(AES_TRIGGER_REG, 1);
}
/**
* @brief Read state of AES accelerator
*
* @return esp_aes_state_t
*/
static inline esp_aes_state_t aes_ll_get_state(void)
{
return REG_READ(AES_STATE_REG);
}
/**
* @brief Set mode of operation
*
* @note Only used for DMA transforms
*
* @param mode
*/
static inline void aes_ll_set_block_mode(esp_aes_mode_t mode)
{
REG_WRITE(AES_BLOCK_MODE_REG, mode);
}
/**
* @brief Set AES-CTR counter to INC32
*
* @note Only affects AES-CTR mode
*
*/
static inline void aes_ll_set_inc(void)
{
REG_WRITE(AES_INC_SEL_REG, 0);
}
/**
* @brief Release the DMA
*
*/
static inline void aes_ll_dma_exit(void)
{
REG_WRITE(AES_DMA_EXIT_REG, 0);
}
/**
* @brief Sets the number of blocks to be transformed
*
* @note Only used for DMA transforms
*
* @param num_blocks Number of blocks to transform
*/
static inline void aes_ll_set_num_blocks(size_t num_blocks)
{
REG_WRITE(AES_BLOCK_NUM_REG, num_blocks);
}
/*
* Write IV to hardware iv registers
*/
static inline void aes_ll_set_iv(const uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
for (int i = 0; i < IV_WORDS; i++ ) {
REG_WRITE(&reg_addr_buf[i], iv_words[i]);
}
}
/*
* Read IV from hardware iv registers
*/
static inline void aes_ll_read_iv(uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < IV_WORDS; i++) {
iv_words[i] = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
}
}
/**
* @brief Enable or disable DMA mode
*
* @param enable true to enable, false to disable.
*/
static inline void aes_ll_dma_enable(bool enable)
{
REG_WRITE(AES_DMA_ENABLE_REG, enable);
}
/**
* @brief Enable or disable transform completed interrupt
*
* @param enable true to enable, false to disable.
*/
static inline void aes_ll_interrupt_enable(bool enable)
{
REG_WRITE(AES_INT_ENA_REG, enable);
}
/**
* @brief Clears the interrupt
*
*/
static inline void aes_ll_interrupt_clear(void)
{
REG_WRITE(AES_INT_CLR_REG, 1);
}
#ifdef __cplusplus
}
#endif

View File

@ -52,6 +52,19 @@ extern "C" {
#define GDMA_LL_TRIG_SRC_SHA (7) #define GDMA_LL_TRIG_SRC_SHA (7)
#define GDMA_LL_TRIG_SRC_ADC_DAC (8) #define GDMA_LL_TRIG_SRC_ADC_DAC (8)
typedef enum {
GDMA_LL_PERIPH_ID_SPI2 = 0,
GDMA_LL_PERIPH_ID_SPI3,
GDMA_LL_PERIPH_ID_UART,
GDMA_LL_PERIPH_ID_I2S0,
GDMA_LL_PERIPH_ID_I2S1,
GDMA_LL_PERIPH_ID_LCD_CAM,
GDMA_LL_PERIPH_ID_AES,
GDMA_LL_PERIPH_ID_SHA,
GDMA_LL_PERIPH_ID_ADC_DAC,
} gdma_ll_periph_id_t;
///////////////////////////////////// Common ///////////////////////////////////////// ///////////////////////////////////// Common /////////////////////////////////////////
/** /**
* @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default * @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default
@ -287,7 +300,7 @@ static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, ui
/** /**
* @brief Connect DMA RX channel to a given peripheral * @brief Connect DMA RX channel to a given peripheral
*/ */
static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id) static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_ll_periph_id_t periph_id)
{ {
dev->peri_sel[channel].peri_in_sel = periph_id; dev->peri_sel[channel].peri_in_sel = periph_id;
} }
@ -482,7 +495,7 @@ static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, ui
/** /**
* @brief Connect DMA TX channel to a given peripheral * @brief Connect DMA TX channel to a given peripheral
*/ */
static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id) static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, gdma_ll_periph_id_t periph_id)
{ {
dev->peri_sel[channel].peri_out_sel = periph_id; dev->peri_sel[channel].peri_out_sel = periph_id;
} }

View File

@ -0,0 +1,162 @@
// Copyright 2020 Espressif Systems (shanghai) PTE LTD
//
// 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.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#include <stddef.h>
#include <stdbool.h>
#include "soc/lldesc.h"
#include "soc/soc_caps.h"
#include "hal/aes_types.h"
#include "hal/aes_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Sets the key used for AES encryption/decryption
*
* @param key pointer to the key
* @param key_bytes number of bytes in key
* @param mode key mode, 0 : decrypt, 1: encrypt
*
* @return uint8_t number of key bytes written to hardware, used for fault injection check
*/
uint8_t aes_hal_setkey(const uint8_t *key, size_t key_bytes, int mode);
/**
* @brief encrypts/decrypts a single block
*
* @param input_block input block, size of AES_BLOCK_BYTES
* @param output_block output block, size of AES_BLOCK_BYTES
*/
void aes_hal_transform_block(const void *input_block, void *output_block);
#if SOC_AES_SUPPORT_DMA
/**
* @brief Inits the AES mode of operation
*
* @param mode mode of operation, e.g. CTR or CBC
*/
void aes_hal_mode_init(esp_aes_mode_t mode);
/**
* @brief Sets the initialization vector for the transform
*
* @note The same IV must never be reused with the same key
*
* @param iv the initialization vector, length = IV_BYTES (16 bytes)
*/
void aes_hal_set_iv(const uint8_t *iv);
/**
* @brief Reads the initialization vector
*
* @param iv initialization vector read from HW, length = IV_BYTES (16 bytes)
*/
void aes_hal_read_iv(uint8_t *iv);
/**
* @brief Busy waits until the DMA operation is done (descriptor owner is CPU)
*
* @param output pointer to inlink descriptor
*/
void aes_hal_wait_dma_done(lldesc_t *output);
/**
* @brief Starts an already configured AES DMA transform
*
* @param input outlink descriptor for data to be written to the peripheral
* @param output inlink descriptor for data to be read from the peripheral
* @param num_blocks Number of blocks to transform
*/
void aes_hal_transform_dma_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks);
/**
* @brief Finish up a AES DMA conversion, release DMA
*
*/
void aes_hal_transform_dma_finish(void);
/**
* @brief Enable or disable transform completed interrupt
*
* @param enable true to enable, false to disable.
*/
#define aes_hal_interrupt_enable(enable) aes_ll_interrupt_enable(enable)
/**
* @brief Clears the interrupt
*
*/
#define aes_hal_interrupt_clear() aes_ll_interrupt_clear()
#if SOC_AES_SUPPORT_GCM
/**
* @brief Calculates the Hash sub-key H0 needed to start AES-GCM
*
* @param gcm_hash the Hash sub-key H0 output
*/
void aes_hal_gcm_calc_hash(uint8_t *gcm_hash);
/**
* @brief Initializes the AES hardware for AES-GCM
*
* @param aad_num_blocks the number of Additional Authenticated Data (AAD) blocks
* @param num_valid_bit the number of effective bits of incomplete blocks in plaintext/cipertext
*/
void aes_hal_gcm_init(size_t aad_num_blocks, size_t num_valid_bit);
/**
* @brief Starts a AES-GCM transform
*
* @param input outlink descriptor for data to be written to the peripheral
* @param output inlink descriptor for data to be read from the perihperal
* @param num_blocks Number of blocks to transform
*/
void aes_hal_transform_dma_gcm_start(const lldesc_t *input, const lldesc_t *output, size_t num_blocks);
/**
* @brief Sets the J0 value, for more information see the GCM subchapter in the TRM
*
* @note Only affects AES-GCM
*
* @param j0 J0 value
*/
#define aes_hal_gcm_set_j0(j0) aes_ll_gcm_set_j0(j0)
/**
* @brief Read the tag after a AES-GCM transform
*
* @param tag Pointer to where to store the result
* @param tag_length number of bytes to read into tag
*/
void aes_hal_gcm_read_tag(uint8_t *tag, size_t tag_len);
#endif //SOC_AES_SUPPORT_GCM
#endif //SOC_AES_SUPPORT_DMA
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,48 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
//
// 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.
#pragma once
/* padlock.c and aesni.c rely on these values! */
#define ESP_AES_ENCRYPT 1
#define ESP_AES_DECRYPT 0
/* DMA AES working modes*/
typedef enum {
ESP_AES_BLOCK_MODE_ECB = 0,
ESP_AES_BLOCK_MODE_CBC,
ESP_AES_BLOCK_MODE_OFB,
ESP_AES_BLOCK_MODE_CTR,
ESP_AES_BLOCK_MODE_CFB8,
ESP_AES_BLOCK_MODE_CFB128,
ESP_AES_BLOCK_MODE_GCM,
ESP_AES_BLOCK_MODE_MAX,
} esp_aes_mode_t;
/* Number of bytes in an AES block */
#define AES_BLOCK_BYTES (16)
/* Number of words in an AES block */
#define AES_BLOCK_WORDS (4)
/* Number of bytes in an IV */
#define IV_BYTES (16)
/* Number of words in an IV */
#define IV_WORDS (4)
/* Number of bytes in a GCM tag block */
#define TAG_BYTES (16)
/* Number of words in a GCM tag block */
#define TAG_WORDS (4)
#define AES_128_KEY_BYTES (128/8)
#define AES_192_KEY_BYTES (192/8)
#define AES_256_KEY_BYTES (256/8)

View File

@ -26,7 +26,6 @@
#include "hal/crypto_dma_ll.h" #include "hal/crypto_dma_ll.h"
#elif SOC_SHA_GENERAL_DMA #elif SOC_SHA_GENERAL_DMA
#include "hal/gdma_ll.h" #include "hal/gdma_ll.h"
#define DMA_PERIPH_SHA 7
#endif #endif
#define SHA1_STATE_LEN_WORDS (160 / 32) #define SHA1_STATE_LEN_WORDS (160 / 32)
@ -99,7 +98,7 @@ static inline void sha_hal_dma_init(lldesc_t *input)
gdma_ll_tx_enable_data_burst(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, false); gdma_ll_tx_enable_data_burst(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, false);
gdma_ll_tx_enable_auto_write_back(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, false); gdma_ll_tx_enable_auto_write_back(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, false);
gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, DMA_PERIPH_SHA); gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, GDMA_LL_PERIPH_ID_SHA);
#if SOC_GDMA_SUPPORT_EXTMEM #if SOC_GDMA_SUPPORT_EXTMEM
/* Atleast 40 bytes when accessing external RAM */ /* Atleast 40 bytes when accessing external RAM */
@ -124,7 +123,7 @@ static inline void sha_hal_dma_init(lldesc_t *input)
static inline void sha_hal_dma_init(lldesc_t *input) static inline void sha_hal_dma_init(lldesc_t *input)
{ {
crypto_dma_ll_set_mode(CRYPTO_DMA_SHA); crypto_dma_ll_set_mode(CRYPTO_DMA_SHA);
crypto_dma_ll_outlink_reset(); crypto_dma_ll_reset();
crypto_dma_ll_outlink_set((uint32_t)input); crypto_dma_ll_outlink_set((uint32_t)input);
crypto_dma_ll_outlink_start(); crypto_dma_ll_outlink_start();

View File

@ -2,7 +2,6 @@
// AES-CBC hardware throughput (accounts for worst-case performance with PSRAM workaround) // AES-CBC hardware throughput (accounts for worst-case performance with PSRAM workaround)
#define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 8.2 #define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 8.2
#define IDF_PERFORMANCE_MIN_AES_GCM_THROUGHPUT_MBSEC 0.5
// SHA256 hardware throughput at 240MHz, threshold set lower than worst case // SHA256 hardware throughput at 240MHz, threshold set lower than worst case
#define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 8.0 #define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 8.0

View File

@ -1,7 +1,8 @@
#pragma once #pragma once
#define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 43.0 #define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 43.0
#define IDF_PERFORMANCE_MIN_AES_GCM_THROUGHPUT_MBSEC 2.1 #define IDF_PERFORMANCE_MIN_AES_GCM_CRYPT_TAG_THROUGHPUT_MBSEC 30.0
#define IDF_PERFORMANCE_MIN_AES_GCM_UPDATE_THROUGHPUT_MBSEC 2.1
// SHA256 hardware throughput at 240MHz, threshold set lower than worst case // SHA256 hardware throughput at 240MHz, threshold set lower than worst case
#define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 90.0 #define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 90.0

View File

@ -84,16 +84,19 @@ target_sources(mbedtls PRIVATE ${mbedtls_target_sources})
# Choose perihperal type # Choose perihperal type
if(CONFIG_IDF_TARGET_ESP32) if(CONFIG_IDF_TARGET_ESP32)
set(SHA_PERIPHERAL_TYPE "parallel_engine") set(SHA_PERIPHERAL_TYPE "parallel_engine")
set(AES_PERIPHERAL_TYPE "block")
else() else()
set(SHA_PERIPHERAL_TYPE "dma") set(SHA_PERIPHERAL_TYPE "dma")
set(AES_PERIPHERAL_TYPE "dma")
endif() endif()
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c" target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c"
"${COMPONENT_DIR}/port/esp_mem.c" "${COMPONENT_DIR}/port/esp_mem.c"
"${COMPONENT_DIR}/port/esp_timing.c" "${COMPONENT_DIR}/port/esp_timing.c"
"${COMPONENT_DIR}/port/sha/esp_sha.c" "${COMPONENT_DIR}/port/sha/esp_sha.c"
"${COMPONENT_DIR}/port/esp_aes_xts.c" "${COMPONENT_DIR}/port/aes/esp_aes_xts.c"
"${COMPONENT_DIR}/port/${idf_target}/aes.c" "${COMPONENT_DIR}/port/aes/esp_aes_common.c"
"${COMPONENT_DIR}/port/aes/${AES_PERIPHERAL_TYPE}/esp_aes.c"
"${COMPONENT_DIR}/port/sha/${SHA_PERIPHERAL_TYPE}/sha.c" "${COMPONENT_DIR}/port/sha/${SHA_PERIPHERAL_TYPE}/sha.c"
) )
@ -121,6 +124,9 @@ if(CONFIG_MBEDTLS_HARDWARE_SHA)
) )
endif() endif()
if(CONFIG_MBEDTLS_HARDWARE_GCM)
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c")
endif()
foreach(target ${mbedtls_targets}) foreach(target ${mbedtls_targets})
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h") target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")

View File

@ -5,7 +5,7 @@
COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include esp_crt_bundle/include COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include esp_crt_bundle/include
COMPONENT_SRCDIRS := mbedtls/library port port/$(IDF_TARGET) port/sha port/sha/parallel_engine esp_crt_bundle COMPONENT_SRCDIRS := mbedtls/library port port/$(IDF_TARGET) port/sha port/sha/parallel_engine port/aes port/aes/block esp_crt_bundle
COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o

View File

@ -1,5 +1,5 @@
/** /**
* \brief AES block cipher, ESP32 hardware accelerated version * \brief AES block cipher, ESP block hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version. * Based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@ -28,9 +28,11 @@
#include <string.h> #include <string.h>
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include "esp32/aes.h" #include "aes/esp_aes.h"
#include "soc/hwcrypto_periph.h" #include "soc/hwcrypto_periph.h"
#include <sys/lock.h> #include <sys/lock.h>
#include "hal/aes_hal.h"
#include "aes/esp_aes_internal.h"
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
@ -49,10 +51,6 @@
*/ */
static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED; static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
static inline bool valid_key_length(const esp_aes_context *ctx)
{
return ctx->key_bytes == 128/8 || ctx->key_bytes == 192/8 || ctx->key_bytes == 256/8;
}
void esp_aes_acquire_hardware( void ) void esp_aes_acquire_hardware( void )
{ {
@ -70,64 +68,7 @@ void esp_aes_release_hardware( void )
portEXIT_CRITICAL(&aes_spinlock); portEXIT_CRITICAL(&aes_spinlock);
} }
void esp_aes_init( esp_aes_context *ctx )
{
bzero( ctx, sizeof( esp_aes_context ) );
}
void esp_aes_free( esp_aes_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_aes_context ) );
}
/*
* AES key schedule (same for encryption or decryption, as hardware handles schedule)
*
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
if (keybits != 128 && keybits != 192 && keybits != 256) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
ctx->key_bytes = keybits / 8;
memcpy(ctx->key, key, ctx->key_bytes);
ctx->key_in_hardware = 0;
return 0;
}
/*
* Helper function to copy key from esp_aes_context buffer
* to hardware key registers.
*
* Call only while holding esp_aes_acquire_hardware().
*/
static void esp_aes_setkey_hardware(esp_aes_context *ctx, int mode)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
ctx->key_in_hardware = 0;
for (int i = 0; i < ctx->key_bytes/4; ++i) {
DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
ctx->key_in_hardware += 4;
}
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
/* Fault injection check: all words of key data should have been written to hardware */
if (ctx->key_in_hardware < 16
|| ctx->key_in_hardware != ctx->key_bytes) {
abort();
}
}
/* Run a single 16 byte block of AES, using the hardware engine. /* Run a single 16 byte block of AES, using the hardware engine.
* *
@ -135,8 +76,8 @@ static void esp_aes_setkey_hardware(esp_aes_context *ctx, int mode)
*/ */
static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output) static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
{ {
const uint32_t *input_words = (const uint32_t *)input;
uint32_t i0, i1, i2, i3; uint32_t i0, i1, i2, i3;
const uint32_t *input_words = (uint32_t *)input;
uint32_t *output_words = (uint32_t *)output; uint32_t *output_words = (uint32_t *)output;
/* If no key is written to hardware yet, either the user hasn't called /* If no key is written to hardware yet, either the user hasn't called
@ -148,26 +89,12 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
bzero(output, 16); bzero(output, 16);
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
} }
/* Storing i0,i1,i2,i3 in registers not an array
helps a lot with optimisations at -Os level */
i0 = input_words[0]; i0 = input_words[0];
DPORT_REG_WRITE(AES_TEXT_BASE, i0);
i1 = input_words[1]; i1 = input_words[1];
DPORT_REG_WRITE(AES_TEXT_BASE + 4, i1);
i2 = input_words[2]; i2 = input_words[2];
DPORT_REG_WRITE(AES_TEXT_BASE + 8, i2);
i3 = input_words[3]; i3 = input_words[3];
DPORT_REG_WRITE(AES_TEXT_BASE + 12, i3);
DPORT_REG_WRITE(AES_START_REG, 1); aes_hal_transform_block(input, output);
while (DPORT_REG_READ(AES_IDLE_REG) != 1) { }
esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, 4);
/* Physical security check: Verify the AES accelerator actually ran, and wasn't /* Physical security check: Verify the AES accelerator actually ran, and wasn't
skipped due to external fault injection while starting the peripheral. skipped due to external fault injection while starting the peripheral.
@ -187,6 +114,13 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
return 0; return 0;
} }
void esp_aes_encrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
esp_internal_aes_encrypt(ctx, input, output);
}
/* /*
* AES-ECB block encryption * AES-ECB block encryption
*/ */
@ -202,12 +136,19 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
r = esp_aes_block(ctx, input, output); r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware(); esp_aes_release_hardware();
return r; return r;
} }
void esp_aes_decrypt(esp_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
esp_internal_aes_decrypt(ctx, input, output);
}
/* /*
* AES-ECB block decryption * AES-ECB block decryption
*/ */
@ -224,7 +165,7 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
r = esp_aes_block(ctx, input, output); r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware(); esp_aes_release_hardware();
return r; return r;
@ -246,7 +187,7 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
r = esp_aes_block(ctx, input, output); r = esp_aes_block(ctx, input, output);
esp_aes_release_hardware(); esp_aes_release_hardware();
@ -264,7 +205,6 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
const unsigned char *input, const unsigned char *input,
unsigned char *output ) unsigned char *output )
{ {
int i;
uint32_t *output_words = (uint32_t *)output; uint32_t *output_words = (uint32_t *)output;
const uint32_t *input_words = (const uint32_t *)input; const uint32_t *input_words = (const uint32_t *)input;
uint32_t *iv_words = (uint32_t *)iv; uint32_t *iv_words = (uint32_t *)iv;
@ -280,17 +220,18 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
esp_aes_setkey_hardware(ctx, mode);
if ( mode == ESP_AES_DECRYPT ) { if ( mode == ESP_AES_DECRYPT ) {
while ( length > 0 ) { while ( length > 0 ) {
memcpy(temp, input_words, 16); memcpy(temp, input_words, 16);
esp_aes_block(ctx, input_words, output_words); esp_aes_block(ctx, input_words, output_words);
for ( i = 0; i < 4; i++ ) { output_words[0] = output_words[0] ^ iv_words[0];
output_words[i] = output_words[i] ^ iv_words[i]; 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 ); memcpy( iv_words, temp, 16 );
@ -301,9 +242,10 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
} else { // ESP_AES_ENCRYPT } else { // ESP_AES_ENCRYPT
while ( length > 0 ) { while ( length > 0 ) {
for ( i = 0; i < 4; i++ ) { output_words[0] = input_words[0] ^ iv_words[0];
output_words[i] = input_words[i] ^ iv_words[i]; 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];
esp_aes_block(ctx, output_words, output_words); esp_aes_block(ctx, output_words, output_words);
memcpy( iv_words, output_words, 16 ); memcpy( iv_words, output_words, 16 );
@ -339,8 +281,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
if ( mode == ESP_AES_DECRYPT ) { if ( mode == ESP_AES_DECRYPT ) {
while ( length-- ) { while ( length-- ) {
@ -392,8 +333,8 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
while ( length-- ) { while ( length-- ) {
memcpy( ov, iv, 16 ); memcpy( ov, iv, 16 );
@ -437,18 +378,19 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
while ( length-- ) { while ( length-- ) {
if ( n == 0 ) { if ( n == 0 ) {
esp_aes_block(ctx, nonce_counter, stream_block); esp_aes_block(ctx, nonce_counter, stream_block);
for ( i = 16; i > 0; i-- ) for ( i = 16; i > 0; i-- ) {
if ( ++nonce_counter[i - 1] != 0 ) { if ( ++nonce_counter[i - 1] != 0 ) {
break; break;
} }
} }
}
c = *input++; c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] ); *output++ = (unsigned char)( c ^ stream_block[n] );
@ -491,8 +433,9 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
} }
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0;
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
while (length--) { while (length--) {
if ( n == 0 ) { if ( n == 0 ) {

View File

@ -1,5 +1,5 @@
/** /**
* \brief AES block cipher, ESP32-S2 hardware accelerated version * \brief AES block cipher, ESP DMA hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version. * Based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@ -26,17 +26,8 @@
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/ */
#include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/lock.h>
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#include "esp32s3/aes.h"
#include "soc/cpu.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
#include "soc/periph_defs.h"
#include "esp32s3/rom/lldesc.h"
#include "esp32s3/rom/cache.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "esp_log.h" #include "esp_log.h"
@ -44,18 +35,31 @@
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "sys/param.h" #include "sys/param.h"
#include "esp_pm.h" #include "esp_pm.h"
#include "soc/soc_memory_layout.h" #include "esp_crypto_lock.h"
#include "soc/gdma_reg.h" #include "hal/aes_hal.h"
#include "soc/gdma_struct.h" #include "aes/esp_aes_internal.h"
#include "soc/extmem_reg.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/cache.h"
#endif
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#define AES_BLOCK_BYTES 16 #if SOC_AES_SUPPORT_GCM
#define IV_WORDS 4 #include "aes/esp_aes_gcm.h"
#endif
#if SOC_AES_GENERAL_DMA
#define AES_LOCK() esp_crypto_aes_lock_acquire()
#define AES_RELEASE() esp_crypto_aes_lock_release()
#elif SOC_AES_CRYPTO_DMA
#define AES_LOCK() esp_crypto_dma_lock_acquire()
#define AES_RELEASE() esp_crypto_dma_lock_release()
#endif
#define DMA_PERIPH_AES 6 /* DMA peripheral indexes */
#define DMA_PERIPH_SHA 7
/* Max size of each chunk to process when output buffer is in unaligned external ram /* Max size of each chunk to process when output buffer is in unaligned external ram
must be a multiple of block size must be a multiple of block size
*/ */
@ -65,22 +69,6 @@
busy-waiting, 30000 bytes is approx 0.5 ms */ busy-waiting, 30000 bytes is approx 0.5 ms */
#define AES_DMA_INTR_TRIG_LEN 2000 #define AES_DMA_INTR_TRIG_LEN 2000
#define ESP_PUT_BE64(a, val) \
do { \
*(uint64_t*)(a) = __builtin_bswap64( (uint64_t)(val) ); \
} while (0)
/* DMA AES working modes*/
typedef enum {
ESP_AES_BLOCK_MODE_ECB = 0,
ESP_AES_BLOCK_MODE_CBC,
ESP_AES_BLOCK_MODE_OFB,
ESP_AES_BLOCK_MODE_CTR,
ESP_AES_BLOCK_MODE_CFB8,
ESP_AES_BLOCK_MODE_CFB128,
} esp_aes_mode_t;
#if defined(CONFIG_MBEDTLS_AES_USE_INTERRUPT) #if defined(CONFIG_MBEDTLS_AES_USE_INTERRUPT)
static SemaphoreHandle_t op_complete_sem; static SemaphoreHandle_t op_complete_sem;
@ -92,143 +80,50 @@ static esp_pm_lock_handle_t s_pm_sleep_lock;
static const char *TAG = "esp-aes"; static const char *TAG = "esp-aes";
static _lock_t s_aes_lock; /* Append a descriptor to the chain, set head if chain empty */
static inline void lldesc_append(lldesc_t **head, lldesc_t *item)
static inline bool valid_key_length(const esp_aes_context *ctx)
{ {
return ctx->key_bytes == 128 / 8 || ctx->key_bytes == 256 / 8; lldesc_t *it;
if (*head == NULL) {
*head = item;
return;
} }
it = *head;
while (it->empty != 0) {
it = (lldesc_t *)it->empty;
}
it->eof = 0;
it->empty = (uint32_t)item;
}
void esp_aes_acquire_hardware( void ) void esp_aes_acquire_hardware( void )
{ {
_lock_acquire(&s_aes_lock); /* Released by esp_aes_release_hardware()*/
AES_LOCK();
/* Enable AES hardware */ /* Enable AES and DMA hardware */
//periph_module_enable(PERIPH_AES_DMA_MODULE); #if SOC_AES_CRYPTO_DMA
/* Enable AES hardware */ periph_module_enable(PERIPH_AES_DMA_MODULE);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_CRYPTO_AES_CLK_EN | SYSTEM_DMA_CLK_EN); #elif SOC_AES_GENERAL_DMA
/* Clear reset on digital signature unit, periph_module_enable(PERIPH_AES_MODULE);
otherwise AES unit is held in reset also. */ periph_module_enable(PERIPH_GDMA_MODULE);
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, #endif
SYSTEM_CRYPTO_AES_RST | SYSTEM_DMA_RST | SYSTEM_CRYPTO_DS_RST);
} }
/* Function to disable AES and Crypto DMA clocks and release locks */ /* Function to disable AES and Crypto DMA clocks and release locks */
void esp_aes_release_hardware( void ) void esp_aes_release_hardware( void )
{ {
/* Disable AES hardware */ /* Disable AES and DMA hardware */
//periph_module_disable(PERIPH_AES_DMA_MODULE); #if SOC_AES_CRYPTO_DMA
/* Disable AES hardware */ periph_module_disable(PERIPH_AES_DMA_MODULE);
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_CRYPTO_AES_RST | SYSTEM_DMA_RST); #elif SOC_AES_GENERAL_DMA
/* Don't return other units to reset, as this pulls periph_module_disable(PERIPH_AES_MODULE);
reset on RSA & SHA units, respectively. */ periph_module_disable(PERIPH_GDMA_MODULE);
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_CRYPTO_AES_CLK_EN | SYSTEM_DMA_CLK_EN); #endif
_lock_release(&s_aes_lock); AES_RELEASE();
}
/* Function to init AES context to zero */
void esp_aes_init( esp_aes_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_aes_context ) );
}
/* Function to clear AES context */
void esp_aes_free( esp_aes_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_aes_context ) );
}
/*
* AES key schedule (same for encryption or decryption, as hardware handles schedule)
*
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
if (keybits == 192) {
return MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE;
}
if (keybits != 128 && keybits != 256) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
ctx->key_bytes = keybits / 8;
memcpy(ctx->key, key, ctx->key_bytes);
ctx->key_in_hardware = 0;
return 0;
}
/*
* Helper function to copy key from esp_aes_context buffer
* to hardware key registers.
*
* Call only while holding esp_aes_acquire_hardware().
*/
static void esp_aes_setkey_hardware( esp_aes_context *ctx, int crypt_mode)
{
const uint32_t MODE_DECRYPT_BIT = 4;
unsigned mode_reg_base = (crypt_mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
ctx->key_in_hardware = 0;
for (int i = 0; i < ctx->key_bytes / 4; ++i) {
REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
ctx->key_in_hardware += 4;
}
REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
/* Fault injection check: all words of key data should have been written to hardware */
if (ctx->key_in_hardware < 16
|| ctx->key_in_hardware != ctx->key_bytes) {
abort();
}
}
/*
* Sets the AES DMA block mode (ECB, CBC, CFB, OFB, GCM, CTR)
* and intializes the required registers for that working mode
*/
static inline void esp_aes_mode_init(esp_aes_mode_t mode)
{
/* Set the algorithm mode CBC, CFB ... */
REG_WRITE(AES_BLOCK_MODE_REG, mode);
/* Presently hard-coding the INC function to 32 bit */
if (mode == ESP_AES_BLOCK_MODE_CTR) {
REG_WRITE(AES_INC_SEL_REG, 0);
}
}
/*
* Write IV to hardware iv registers
*/
static inline void esp_aes_set_iv(uint8_t *iv)
{
uint32_t *iv_words = (uint32_t *)iv;
uint32_t *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
for (int i = 0; i < IV_WORDS; i++ ) {
REG_WRITE(&reg_addr_buf[i], iv_words[i]);
}
}
/*
* Read IV from hardware iv registers
*/
static inline void esp_aes_get_iv(uint8_t *iv)
{
esp_dport_access_read_buffer((uint32_t *)iv, AES_IV_BASE, IV_WORDS);
} }
@ -236,7 +131,7 @@ static inline void esp_aes_get_iv(uint8_t *iv)
static IRAM_ATTR void esp_aes_complete_isr(void *arg) static IRAM_ATTR void esp_aes_complete_isr(void *arg)
{ {
BaseType_t higher_woken; BaseType_t higher_woken;
REG_WRITE(AES_INT_CLR_REG, 1); aes_hal_interrupt_clear();
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken); xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
if (higher_woken) { if (higher_woken) {
portYIELD_FROM_ISR(); portYIELD_FROM_ISR();
@ -245,8 +140,8 @@ static IRAM_ATTR void esp_aes_complete_isr(void *arg)
static esp_err_t esp_aes_isr_initialise( void ) static esp_err_t esp_aes_isr_initialise( void )
{ {
REG_WRITE(AES_INT_CLR_REG, 1); aes_hal_interrupt_clear();
REG_WRITE(AES_INT_ENA_REG, 1); aes_hal_interrupt_enable(true);
if (op_complete_sem == NULL) { if (op_complete_sem == NULL) {
op_complete_sem = xSemaphoreCreateBinary(); op_complete_sem = xSemaphoreCreateBinary();
@ -281,8 +176,6 @@ static esp_err_t esp_aes_isr_initialise( void )
/* Wait for AES hardware block operation to complete */ /* Wait for AES hardware block operation to complete */
static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc) static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
{ {
__attribute__((unused)) volatile uint32_t dma_done;
#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
if (use_intr) { if (use_intr) {
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) { if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
@ -297,77 +190,10 @@ static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
} }
#endif #endif
/* Checking this if interrupt is used also, to avoid aes_hal_wait_dma_done(output_desc);
issues with AES fault injection
*/
while (REG_READ(AES_STATE_REG) != AES_STATE_DONE) {
} }
/* Wait for DMA write operation to complete */
while (1) {
dma_done = REG_READ(CRYPTO_DMA_INT_RAW_REG);
// Wait for ownership of buffer to be transferred back to CPU
if ( (output_desc->owner == 0) ) {
break;
}
}
}
/* Init DMA related registers for AES operation */
static void esp_aes_dma_init(lldesc_t *input, lldesc_t *output)
{
/* Enable DMA mode */
REG_WRITE(AES_DMA_ENABLE_REG, 1);
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
/* Initialize DMA registers - this is probably mostly one off initialization
Note: hardcoded to DMA channel 0
*/
/* Note: burst mode has alignment requirements that we have not checked here */
GDMA.conf0[0].outdscr_burst_en = 0;
GDMA.conf0[0].indscr_burst_en = 0;
GDMA.conf0[0].out_data_burst_en = 0;
GDMA.conf0[0].in_data_burst_en = 0;
GDMA.peri_sel[0].peri_out_sel = DMA_PERIPH_AES;
GDMA.peri_sel[0].peri_in_sel = DMA_PERIPH_AES;
/* Set descriptor addresses: NOTE BACKWARDS AS DMA IN/OUT is reverse of AES in/out */
GDMA.out_link[0].addr = (uint32_t)input;
GDMA.in_link[0].addr = (uint32_t)output;
GDMA.sram_size[0].in_size = 3; /* 40 bytes, also minimum size for EDMA */
GDMA.sram_size[0].out_size = 3;
GDMA.conf1[0].in_ext_mem_bk_size = 0; // 16 bytes
GDMA.conf1[0].out_ext_mem_bk_size = 0; // 16 bytes
/*
printf("DESC HEAD pointers IN/outlink %p OUT/inlink / %p\n", in_desc_head, out_desc_head);
printf("before starting in_desc_head owner %d out_desc_head owner %d INT_RAW 0x%08x\n",
in_desc_head->owner,
out_desc_head->owner,
DMA.int_raw.val);
*/
//REG_SET_BIT(EXTMEM_CACHE_MMU_OWNER_REG, 1<<23); //mark PSRAM DCache as belonging to DMA
GDMA.conf0[0].in_rst = 1;
GDMA.conf0[0].in_rst = 0;
GDMA.conf0[0].out_rst = 1;
GDMA.conf0[0].out_rst = 0;
/* Start transfer */
GDMA.out_link[0].start = 1;
GDMA.in_link[0].start = 1;
}
static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out); static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out);
@ -450,7 +276,7 @@ cleanup:
static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out) static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, uint8_t *stream_out)
{ {
lldesc_t stream_in_desc, stream_out_desc; lldesc_t stream_in_desc, stream_out_desc;
lldesc_t *in_desc_head, *out_desc_head; lldesc_t *in_desc_head = NULL, *out_desc_head = NULL;
lldesc_t *block_desc = NULL, *block_in_desc, *block_out_desc; lldesc_t *block_desc = NULL, *block_in_desc, *block_out_desc;
size_t lldesc_num; size_t lldesc_num;
uint8_t stream_in[16] = {}; uint8_t stream_in[16] = {};
@ -503,7 +329,6 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
return esp_aes_process_dma_ext_ram(ctx, input, output, len, stream_out, input_needs_realloc, output_needs_realloc); return esp_aes_process_dma_ext_ram(ctx, input, output, len, stream_out, input_needs_realloc, output_needs_realloc);
} }
/* Set up dma descriptors for input and output */ /* Set up dma descriptors for input and output */
lldesc_num = lldesc_get_required_num(block_bytes); lldesc_num = lldesc_get_required_num(block_bytes);
@ -540,11 +365,6 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
in_desc_head = (block_bytes > 0) ? block_in_desc : &stream_in_desc; in_desc_head = (block_bytes > 0) ? block_in_desc : &stream_in_desc;
out_desc_head = (block_bytes > 0) ? block_out_desc : &stream_out_desc; out_desc_head = (block_bytes > 0) ? block_out_desc : &stream_out_desc;
esp_aes_dma_init(in_desc_head, out_desc_head);
/* Write the number of blocks */
REG_WRITE(AES_BLOCK_NUM_REG, blocks);
#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT) #if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
/* Only use interrupt for long AES operations */ /* Only use interrupt for long AES operations */
@ -557,15 +377,12 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
} else } else
#endif #endif
{ {
REG_WRITE(AES_INT_ENA_REG, 0); aes_hal_interrupt_enable(false);
} }
/* Start AES operation */ aes_hal_transform_dma_start(in_desc_head, out_desc_head, blocks);
REG_WRITE(AES_TRIGGER_REG, 1);
esp_aes_dma_wait_complete(use_intr, out_desc_head); esp_aes_dma_wait_complete(use_intr, out_desc_head);
#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) #if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
if (block_bytes > 0) { if (block_bytes > 0) {
if (esp_ptr_external_ram(output)) { if (esp_ptr_external_ram(output)) {
@ -574,9 +391,7 @@ static int esp_aes_process_dma(esp_aes_context *ctx, const unsigned char *input,
} }
#endif #endif
REG_WRITE(AES_DMA_EXIT_REG, 0); aes_hal_transform_dma_finish();
/* Disable DMA mode */
REG_WRITE(AES_DMA_ENABLE_REG, 0);
if (stream_bytes > 0) { if (stream_bytes > 0) {
memcpy(output + block_bytes, stream_out, stream_bytes); memcpy(output + block_bytes, stream_out, stream_bytes);
@ -589,6 +404,118 @@ cleanup:
} }
#if SOC_AES_SUPPORT_GCM
/* Encrypt/decrypt with AES-GCM the input using DMA */
int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len)
{
lldesc_t *in_desc_head = NULL, *out_desc_head = NULL, *len_desc = NULL;
lldesc_t stream_in_desc, stream_out_desc;
lldesc_t *block_desc = NULL, *block_in_desc = NULL, *block_out_desc = NULL;
size_t lldesc_num;
uint32_t len_buf[4] = {};
uint8_t stream_in[16] = {};
uint8_t stream_out[16] = {};
unsigned stream_bytes = len % AES_BLOCK_BYTES; // bytes which aren't in a full block
unsigned block_bytes = len - stream_bytes; // bytes which are in a full block
unsigned blocks = (block_bytes / AES_BLOCK_BYTES) + ((stream_bytes > 0) ? 1 : 0);
bool use_intr = false;
int ret = 0;
/* 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) {
bzero(output, len);
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
/* Set up dma descriptors for input and output */
lldesc_num = lldesc_get_required_num(block_bytes);
/* Allocate both in and out descriptors to save a malloc/free per function call, add 1 for length descriptor */
block_desc = heap_caps_calloc( (lldesc_num * 2) + 1, sizeof(lldesc_t), MALLOC_CAP_DMA);
if (block_desc == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory");
ret = -1;
goto cleanup;
}
block_in_desc = block_desc;
len_desc = block_desc + lldesc_num;
block_out_desc = block_desc + lldesc_num + 1;
if (aad_desc != NULL) {
lldesc_append(&in_desc_head, aad_desc);
}
if (block_bytes > 0) {
lldesc_setup_link(block_in_desc, input, block_bytes, 0);
lldesc_setup_link(block_out_desc, output, block_bytes, 0);
lldesc_append(&in_desc_head, block_in_desc);
lldesc_append(&out_desc_head, block_out_desc);
}
/* Any leftover bytes which are appended as an additional DMA list */
if (stream_bytes > 0) {
memcpy(stream_in, input + block_bytes, stream_bytes);
lldesc_setup_link(&stream_in_desc, stream_in, AES_BLOCK_BYTES, 0);
lldesc_setup_link(&stream_out_desc, stream_out, AES_BLOCK_BYTES, 0);
lldesc_append(&in_desc_head, &stream_in_desc);
lldesc_append(&out_desc_head, &stream_out_desc);
}
len_buf[1] = __builtin_bswap32(aad_len * 8);
len_buf[3] = __builtin_bswap32(len * 8);
len_desc->length = sizeof(len_buf);
len_desc->size = sizeof(len_buf);
len_desc->owner = 1;
len_desc->eof = 1;
len_desc->buf = (uint8_t *)len_buf;
lldesc_append(&in_desc_head, len_desc);
#if defined (CONFIG_MBEDTLS_AES_USE_INTERRUPT)
/* Only use interrupt for long AES operations */
if (len > AES_DMA_INTR_TRIG_LEN) {
use_intr = true;
if (esp_aes_isr_initialise() == ESP_FAIL) {
ret = -1;
goto cleanup;
}
} else
#endif
{
aes_hal_interrupt_enable(false);
}
/* Start AES operation */
aes_hal_transform_dma_gcm_start(in_desc_head, out_desc_head, blocks);
esp_aes_dma_wait_complete(use_intr, out_desc_head);
aes_hal_transform_dma_finish();
if (stream_bytes > 0) {
memcpy(output + block_bytes, stream_out, stream_bytes);
}
cleanup:
free(block_desc);
return ret;
}
#endif //SOC_AES_SUPPORT_GCM
static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input, static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *input,
unsigned char *output ) unsigned char *output )
{ {
@ -628,8 +555,8 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB); aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL); r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
esp_aes_release_hardware(); esp_aes_release_hardware();
@ -662,8 +589,8 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB); aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL); r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
esp_aes_release_hardware(); esp_aes_release_hardware();
@ -698,8 +625,8 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB); aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL); r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
esp_aes_release_hardware(); esp_aes_release_hardware();
@ -739,9 +666,9 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CBC); aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC);
esp_aes_set_iv(iv); aes_hal_set_iv(iv);
r = esp_aes_process_dma(ctx, input, output, length, NULL); r = esp_aes_process_dma(ctx, input, output, length, NULL);
if (r != 0) { if (r != 0) {
@ -749,7 +676,7 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
return r; return r;
} }
esp_aes_get_iv(iv); aes_hal_read_iv(iv);
esp_aes_release_hardware(); esp_aes_release_hardware();
return r; return r;
@ -792,11 +719,11 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
if (block_bytes > 0) { if (block_bytes > 0) {
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB8); aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8);
esp_aes_set_iv(iv); aes_hal_set_iv(iv);
r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL); r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
esp_aes_get_iv(iv); aes_hal_read_iv(iv);
if (r != 0) { if (r != 0) {
esp_aes_release_hardware(); esp_aes_release_hardware();
@ -811,8 +738,8 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
// Process remaining bytes block-at-a-time in ECB mode // Process remaining bytes block-at-a-time in ECB mode
if (length > 0) { if (length > 0) {
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, MBEDTLS_AES_ENCRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, MBEDTLS_AES_ENCRYPT);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB); aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
while ( length-- ) { while ( length-- ) {
memcpy( ov, iv, 16 ); memcpy( ov, iv, 16 );
@ -898,9 +825,9 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
stream_bytes = length % AES_BLOCK_BYTES; stream_bytes = length % AES_BLOCK_BYTES;
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, mode); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB128); aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128);
esp_aes_set_iv(iv); aes_hal_set_iv(iv);
r = esp_aes_process_dma(ctx, input, output, length, iv); r = esp_aes_process_dma(ctx, input, output, length, iv);
if (r != 0) { if (r != 0) {
@ -910,7 +837,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
if (stream_bytes == 0) { if (stream_bytes == 0) {
// if we didn't need the partial 'stream block' then the new IV is in the IV register // if we didn't need the partial 'stream block' then the new IV is in the IV register
esp_aes_get_iv(iv); aes_hal_read_iv(iv);
} else { } 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), // 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 // In decrypt mode any partial bytes are output plaintext (iv ^ c) and need to be swapped back to ciphertext (as the next
@ -971,9 +898,9 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_OFB); aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB);
esp_aes_set_iv(iv); aes_hal_set_iv(iv);
r = esp_aes_process_dma(ctx, input, output, length, iv); r = esp_aes_process_dma(ctx, input, output, length, iv);
if (r != 0) { if (r != 0) {
@ -981,7 +908,7 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
return r; return r;
} }
esp_aes_get_iv(iv); aes_hal_read_iv(iv);
esp_aes_release_hardware(); esp_aes_release_hardware();
} }
@ -1036,10 +963,10 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
esp_aes_acquire_hardware(); esp_aes_acquire_hardware();
ctx->key_in_hardware = 0; ctx->key_in_hardware = 0;
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CTR); aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR);
esp_aes_set_iv(nonce_counter); aes_hal_set_iv(nonce_counter);
r = esp_aes_process_dma(ctx, input, output, length, stream_block); r = esp_aes_process_dma(ctx, input, output, length, stream_block);
@ -1048,7 +975,7 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
return r; return r;
} }
esp_aes_get_iv(nonce_counter); aes_hal_read_iv(nonce_counter);
esp_aes_release_hardware(); esp_aes_release_hardware();

View File

@ -0,0 +1,83 @@
/**
* \brief AES block cipher, ESP hardware accelerated version, common
* 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 "aes/esp_aes_internal.h"
#include "mbedtls/aes.h"
#include "hal/aes_hal.h"
#include "hal/aes_types.h"
#include "soc/soc_caps.h"
#include <string.h>
#include "mbedtls/platform.h"
bool valid_key_length(const esp_aes_context *ctx)
{
bool valid_len = (ctx->key_bytes == AES_128_KEY_BYTES) || (ctx->key_bytes == AES_256_KEY_BYTES);
#if SOC_AES_SUPPORT_AES_192
valid_len |= ctx->key_bytes == AES_192_KEY_BYTES;
#endif
return valid_len;
}
void esp_aes_init( esp_aes_context *ctx )
{
bzero( ctx, sizeof( esp_aes_context ) );
}
void esp_aes_free( esp_aes_context *ctx )
{
if ( ctx == NULL ) {
return;
}
bzero( ctx, sizeof( esp_aes_context ) );
}
/*
* AES key schedule (same for encryption or decryption, as hardware handles schedule)
*
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
#if !SOC_AES_SUPPORT_AES_192
if (keybits == 192) {
return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
}
#endif
if (keybits != 128 && keybits != 192 && keybits != 256) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
ctx->key_bytes = keybits / 8;
memcpy(ctx->key, key, ctx->key_bytes);
ctx->key_in_hardware = 0;
return 0;
}

View File

@ -0,0 +1,695 @@
/**
* \brief GCM 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 "soc/soc_caps.h"
#if SOC_AES_SUPPORT_GCM
#include "aes/esp_aes.h"
#include "aes/esp_aes_gcm.h"
#include "aes/esp_aes_internal.h"
#include "hal/aes_hal.h"
#include "esp_log.h"
#include "mbedtls/aes.h"
#include "esp_heap_caps.h"
#include "soc/soc_memory_layout.h"
#include <string.h>
#define ESP_PUT_BE64(a, val) \
do { \
*(uint64_t*)(a) = __builtin_bswap64( (uint64_t)(val) ); \
} while (0)
/* For simplicity limit the maxium amount of aad bytes to a single DMA descriptor
This should cover all normal, e.g. mbedtls, use cases */
#define ESP_AES_GCM_AAD_MAX_BYTES 4080
static const char *TAG = "esp-aes-gcm";
static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z);
/*
* Calculates the Initial Counter Block, J0
* and copies to to the esp_gcm_context
*/
static void esp_gcm_derive_J0(esp_gcm_context *ctx)
{
uint8_t len_buf[16];
memset(ctx->J0, 0, AES_BLOCK_BYTES);
memset(len_buf, 0, AES_BLOCK_BYTES);
/* If IV is 96 bits J0 = ( IV || 0^31 || 1 ) */
if (ctx->iv_len == 12) {
memcpy(ctx->J0, ctx->iv, ctx->iv_len);
ctx->J0[AES_BLOCK_BYTES - 1] |= 1;
} else {
/* For IV != 96 bit, J0 = GHASH(IV || 0[s+64] || [len(IV)]64) */
/* First calculate GHASH on IV */
esp_gcm_ghash(ctx, ctx->iv, ctx->iv_len, ctx->J0);
/* Next create 128 bit block which is equal to
64 bit 0 + iv length truncated to 64 bits */
ESP_PUT_BE64(len_buf + 8, ctx->iv_len * 8);
/* Calculate GHASH on last block */
esp_gcm_ghash(ctx, len_buf, 16, ctx->J0);
}
}
/*
* Increment J0 as per GCM spec, by applying the Standard Incrementing
Function INC_32 to it.
* j is the counter which needs to be incremented which is
* copied to ctx->J0 after incrementing
*/
static void increment32_j0(esp_gcm_context *ctx, uint8_t *j)
{
uint8_t j_len = AES_BLOCK_BYTES;
memcpy(j, ctx->J0, AES_BLOCK_BYTES);
if (j) {
for (uint32_t i = j_len; i > (j_len - 4); i--) {
if (++j[i - 1] != 0) {
break;
}
}
memcpy(ctx->J0, j, AES_BLOCK_BYTES);
}
}
/* Function to xor two data blocks */
static void xor_data(uint8_t *d, const uint8_t *s)
{
uint32_t *dst = (uint32_t *) d;
uint32_t *src = (uint32_t *) s;
*dst++ ^= *src++;
*dst++ ^= *src++;
*dst++ ^= *src++;
*dst++ ^= *src++;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
}
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
/* Based on MbedTLS's implemenation
*
* Precompute small multiples of H, that is set
* HH[i] || HL[i] = H times i,
* where i is seen as a field element as in [MGV], ie high-order bits
* correspond to low powers of P. The result is stored in the same way, that
* is the high-order bit of HH corresponds to P^0 and the low-order bit of HL
* corresponds to P^127.
*/
static int gcm_gen_table( esp_gcm_context *ctx )
{
int i, j;
uint64_t hi, lo;
uint64_t vl, vh;
unsigned char *h;
h = ctx->H;
/* pack h as two 64-bits ints, big-endian */
GET_UINT32_BE( hi, h, 0 );
GET_UINT32_BE( lo, h, 4 );
vh = (uint64_t) hi << 32 | lo;
GET_UINT32_BE( hi, h, 8 );
GET_UINT32_BE( lo, h, 12 );
vl = (uint64_t) hi << 32 | lo;
/* 8 = 1000 corresponds to 1 in GF(2^128) */
ctx->HL[8] = vl;
ctx->HH[8] = vh;
/* 0 corresponds to 0 in GF(2^128) */
ctx->HH[0] = 0;
ctx->HL[0] = 0;
for ( i = 4; i > 0; i >>= 1 ) {
uint32_t T = ( vl & 1 ) * 0xe1000000U;
vl = ( vh << 63 ) | ( vl >> 1 );
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
ctx->HL[i] = vl;
ctx->HH[i] = vh;
}
for ( i = 2; i <= 8; i *= 2 ) {
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
vh = *HiH;
vl = *HiL;
for ( j = 1; j < i; j++ ) {
HiH[j] = vh ^ ctx->HH[j];
HiL[j] = vl ^ ctx->HL[j];
}
}
return ( 0 );
}
/*
* Shoup's method for multiplication use this table with
* last4[x] = x times P^128
* where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
*/
static const uint64_t last4[16] = {
0x0000, 0x1c20, 0x3840, 0x2460,
0x7080, 0x6ca0, 0x48c0, 0x54e0,
0xe100, 0xfd20, 0xd940, 0xc560,
0x9180, 0x8da0, 0xa9c0, 0xb5e0
};
/* Based on MbedTLS's implemenation
*
* Sets output to x times H using the precomputed tables.
* x and output are seen as elements of GF(2^128) as in [MGV].
*/
static void gcm_mult( esp_gcm_context *ctx, const unsigned char x[16],
unsigned char output[16] )
{
int i = 0;
unsigned char lo, hi, rem;
uint64_t zh, zl;
lo = x[15] & 0xf;
zh = ctx->HH[lo];
zl = ctx->HL[lo];
for ( i = 15; i >= 0; i-- ) {
lo = x[i] & 0xf;
hi = x[i] >> 4;
if ( i != 15 ) {
rem = (unsigned char) zl & 0xf;
zl = ( zh << 60 ) | ( zl >> 4 );
zh = ( zh >> 4 );
zh ^= (uint64_t) last4[rem] << 48;
zh ^= ctx->HH[lo];
zl ^= ctx->HL[lo];
}
rem = (unsigned char) zl & 0xf;
zl = ( zh << 60 ) | ( zl >> 4 );
zh = ( zh >> 4 );
zh ^= (uint64_t) last4[rem] << 48;
zh ^= ctx->HH[hi];
zl ^= ctx->HL[hi];
}
PUT_UINT32_BE( zh >> 32, output, 0 );
PUT_UINT32_BE( zh, output, 4 );
PUT_UINT32_BE( zl >> 32, output, 8 );
PUT_UINT32_BE( zl, output, 12 );
}
/* Update the key value in gcm context */
int esp_aes_gcm_setkey( esp_gcm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits )
{
if (keybits != 128 && keybits != 192 && keybits != 256) {
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
ctx->aes_ctx.key_bytes = keybits / 8;
memcpy(ctx->aes_ctx.key, key, ctx->aes_ctx.key_bytes);
return ( 0 );
}
/* AES-GCM GHASH calculation z = GHASH(x) using h0 hash key
*/
static void esp_gcm_ghash(esp_gcm_context *ctx, const unsigned char *x, size_t x_len, uint8_t *z)
{
uint8_t tmp[AES_BLOCK_BYTES];
memset(tmp, 0, AES_BLOCK_BYTES);
/* GHASH(X) is calculated on input string which is multiple of 128 bits
* If input string bit length is not multiple of 128 bits it needs to
* be padded by 0
*
* Steps:
* 1. Let X1, X2, ... , Xm-1, Xm denote the unique sequence of blocks such
* that X = X1 || X2 || ... || Xm-1 || Xm.
* 2. Let Y0 be the zero block, 0128.
* 3. Fori=1,...,m,letYi =(Yi-1 ^ Xi)H.
* 4. Return Ym
*/
/* If input bit string is >= 128 bits, process full 128 bit blocks */
while (x_len >= AES_BLOCK_BYTES) {
xor_data(z, x);
gcm_mult(ctx, z, z);
x += AES_BLOCK_BYTES;
x_len -= AES_BLOCK_BYTES;
}
/* If input bit string is not multiple of 128 create last 128 bit
* block by padding necessary 0s
*/
if (x_len) {
memcpy(tmp, x, x_len);
xor_data(z, tmp);
gcm_mult(ctx, z, z);
}
}
/* Function to init AES GCM context to zero */
void esp_aes_gcm_init( esp_gcm_context *ctx)
{
if (ctx == NULL) {
return;
}
bzero(ctx, sizeof(esp_gcm_context));
ctx->gcm_state = ESP_AES_GCM_STATE_INIT;
}
/* Function to clear AES-GCM context */
void esp_aes_gcm_free( esp_gcm_context *ctx)
{
if (ctx == NULL) {
return;
}
bzero(ctx, sizeof(esp_gcm_context));
}
/* Setup AES-GCM */
int esp_aes_gcm_starts( esp_gcm_context *ctx,
int mode,
const unsigned char *iv,
size_t iv_len,
const unsigned char *aad,
size_t aad_len )
{
/* IV and AD are limited to 2^32 bits, so 2^29 bytes */
/* IV is not allowed to be zero length */
if ( iv_len == 0 ||
( (uint32_t) iv_len ) >> 29 != 0 ||
( (uint32_t) aad_len ) >> 29 != 0 ) {
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
}
if (!ctx) {
ESP_LOGE(TAG, "No AES context supplied");
return -1;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return -1;
}
if ( (aad_len > 0) && !aad) {
ESP_LOGE(TAG, "No aad supplied");
return -1;
}
/* Initialize AES-GCM context */
memset(ctx->ghash, 0, sizeof(ctx->ghash));
ctx->data_len = 0;
ctx->iv = iv;
ctx->iv_len = iv_len;
ctx->aad = aad;
ctx->aad_len = aad_len;
ctx->mode = mode;
/* H and the lookup table are only generated once per ctx */
if (ctx->gcm_state == ESP_AES_GCM_STATE_INIT) {
/* Lock the AES engine to calculate ghash key H in hardware */
esp_aes_acquire_hardware();
ctx->aes_ctx.key_in_hardware = aes_hal_setkey(ctx->aes_ctx.key, ctx->aes_ctx.key_bytes, mode);
aes_hal_mode_init(ESP_AES_BLOCK_MODE_GCM);
aes_hal_gcm_calc_hash(ctx->H);
esp_aes_release_hardware();
gcm_gen_table(ctx);
}
ctx->gcm_state = ESP_AES_GCM_STATE_START;
/* Once H is obtained we need to derive J0 (Initial Counter Block) */
esp_gcm_derive_J0(ctx);
/* The initial counter block keeps updating during the esp_gcm_update call
* however to calculate final authentication tag T we need original J0
* so we make a copy here
*/
memcpy(ctx->ori_j0, ctx->J0, 16);
esp_gcm_ghash(ctx, ctx->aad, ctx->aad_len, ctx->ghash);
return ( 0 );
}
/* Perform AES-GCM operation */
int esp_aes_gcm_update( esp_gcm_context *ctx,
size_t length,
const unsigned char *input,
unsigned char *output )
{
size_t nc_off = 0;
uint8_t nonce_counter[AES_BLOCK_BYTES] = {0};
uint8_t stream[AES_BLOCK_BYTES] = {0};
if (!ctx) {
ESP_LOGE(TAG, "No GCM context supplied");
return -1;
}
if (!input) {
ESP_LOGE(TAG, "No input supplied");
return -1;
}
if (!output) {
ESP_LOGE(TAG, "No output supplied");
return -1;
}
if ( output > input && (size_t) ( output - input ) < length ) {
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
}
/* If this is the first time esp_gcm_update is getting called
* calculate GHASH on aad and preincrement the ICB
*/
if (ctx->gcm_state == ESP_AES_GCM_STATE_START) {
/* Jo needs to be incremented first time, later the CTR
* operation will auto update it
*/
increment32_j0(ctx, nonce_counter);
ctx->gcm_state = ESP_AES_GCM_STATE_UPDATE;
} else if (ctx->gcm_state == ESP_AES_GCM_STATE_UPDATE) {
memcpy(nonce_counter, ctx->J0, AES_BLOCK_BYTES);
}
/* Perform intermediate GHASH on "encrypted" data during decryption */
if (ctx->mode == ESP_AES_DECRYPT) {
esp_gcm_ghash(ctx, input, length, ctx->ghash);
}
/* Output = GCTR(J0, Input): Encrypt/Decrypt the input */
esp_aes_crypt_ctr(&ctx->aes_ctx, length, &nc_off, nonce_counter, stream, input, output);
/* ICB gets auto incremented after GCTR operation here so update the context */
memcpy(ctx->J0, nonce_counter, AES_BLOCK_BYTES);
/* Keep updating the length counter for final tag calculation */
ctx->data_len += length;
/* Perform intermediate GHASH on "encrypted" data during encryption*/
if (ctx->mode == ESP_AES_ENCRYPT) {
esp_gcm_ghash(ctx, output, length, ctx->ghash);
}
return 0;
}
/* Function to read the tag value */
int esp_aes_gcm_finish( esp_gcm_context *ctx,
unsigned char *tag,
size_t tag_len )
{
size_t nc_off = 0;
uint8_t len_block[AES_BLOCK_BYTES] = {0};
if ( tag_len > 16 || tag_len < 4 ) {
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
}
/* Calculate final GHASH on aad_len, data length */
ESP_PUT_BE64(len_block, ctx->aad_len * 8);
ESP_PUT_BE64(len_block + 8, ctx->data_len * 8);
esp_gcm_ghash(ctx, len_block, AES_BLOCK_BYTES, ctx->ghash);
/* Tag T = GCTR(J0, ) where T is truncated to tag_len */
esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, 0, ctx->ghash, tag);
return 0;
}
/* Due to restrictions in the hardware (e.g. need to do the whole conversion in one go),
some combinations of inputs are not supported */
static bool esp_aes_gcm_input_support_hw_accel(size_t length, const unsigned char *aad, size_t aad_len,
const unsigned char *input, unsigned char *output)
{
bool support_hw_accel = true;
if (aad_len > ESP_AES_GCM_AAD_MAX_BYTES) {
support_hw_accel = false;
} else if (!esp_ptr_dma_capable(aad) && aad_len > 0) {
/* aad in non internal DMA memory */
support_hw_accel = false;
} else if (!esp_ptr_dma_capable(input) && length > 0) {
/* input in non internal DMA memory */
support_hw_accel = false;
} else if (!esp_ptr_dma_capable(output) && length > 0) {
/* output in non internal DMA memory */
support_hw_accel = false;
} else if (length == 0) {
support_hw_accel = false;
}
return support_hw_accel;
}
static int esp_aes_gcm_crypt_and_tag_partial_hw( esp_gcm_context *ctx,
int mode,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
size_t tag_len,
unsigned char *tag )
{
int ret = 0;
if ( ( ret = esp_aes_gcm_starts( ctx, mode, iv, iv_len, aad, aad_len ) ) != 0 ) {
return ( ret );
}
if ( ( ret = esp_aes_gcm_update( ctx, length, input, output ) ) != 0 ) {
return ( ret );
}
if ( ( ret = esp_aes_gcm_finish( ctx, tag, tag_len ) ) != 0 ) {
return ( ret );
}
return ret;
}
int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
int mode,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
size_t tag_len,
unsigned char *tag )
{
int ret;
lldesc_t aad_desc[2] = {};
lldesc_t *aad_head_desc = NULL;
size_t remainder_bit;
uint8_t stream_in[AES_BLOCK_BYTES] = {};
unsigned stream_bytes = aad_len % AES_BLOCK_BYTES; // bytes which aren't in a full block
unsigned block_bytes = aad_len - stream_bytes; // bytes which are in a full block
/* Due to hardware limition only certain cases are fully supported in HW */
if (!esp_aes_gcm_input_support_hw_accel(length, aad, aad_len, input, output)) {
return esp_aes_gcm_crypt_and_tag_partial_hw(ctx, mode, length, iv, iv_len, aad, aad_len, input, output, tag_len, tag);
}
/* Limit aad len to a single DMA descriptor to simplify DMA handling
In practice, e.g. with mbedtls the length of aad will always be short
*/
if (aad_len > LLDESC_MAX_NUM_PER_DESC) {
return -1;
}
/* IV and AD are limited to 2^32 bits, so 2^29 bytes */
/* IV is not allowed to be zero length */
if ( iv_len == 0 ||
( (uint32_t) iv_len ) >> 29 != 0 ||
( (uint32_t) aad_len ) >> 29 != 0 ) {
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
}
if (!ctx) {
ESP_LOGE(TAG, "No AES context supplied");
return -1;
}
if (!iv) {
ESP_LOGE(TAG, "No IV supplied");
return -1;
}
if ( (aad_len > 0) && !aad) {
ESP_LOGE(TAG, "No aad supplied");
return -1;
}
/* Initialize AES-GCM context */
memset(ctx->ghash, 0, sizeof(ctx->ghash));
ctx->data_len = 0;
ctx->iv = iv;
ctx->iv_len = iv_len;
ctx->aad = aad;
ctx->aad_len = aad_len;
ctx->mode = mode;
esp_aes_acquire_hardware();
ctx->aes_ctx.key_in_hardware = 0;
ctx->aes_ctx.key_in_hardware = aes_hal_setkey(ctx->aes_ctx.key, ctx->aes_ctx.key_bytes, mode);
if (block_bytes > 0) {
aad_desc[0].length = block_bytes;
aad_desc[0].size = block_bytes;
aad_desc[0].owner = 1;
aad_desc[0].buf = aad;
}
if (stream_bytes > 0) {
memcpy(stream_in, aad + block_bytes, stream_bytes);
aad_desc[0].empty = (uint32_t)&aad_desc[1];
aad_desc[1].length = AES_BLOCK_BYTES;
aad_desc[1].size = AES_BLOCK_BYTES;
aad_desc[1].owner = 1;
aad_desc[1].buf = stream_in;
}
if (block_bytes > 0) {
aad_head_desc = &aad_desc[0];
} else if (stream_bytes > 0) {
aad_head_desc = &aad_desc[1];
}
aes_hal_mode_init(ESP_AES_BLOCK_MODE_GCM);
/* See TRM GCM chapter for description of this calculation */
remainder_bit = (8 * length) % 128;
aes_hal_gcm_init( (aad_len + AES_BLOCK_BYTES - 1) / AES_BLOCK_BYTES, remainder_bit);
aes_hal_gcm_calc_hash(ctx->H);
gcm_gen_table(ctx);
esp_gcm_derive_J0(ctx);
aes_hal_gcm_set_j0(ctx->J0);
ret = esp_aes_process_dma_gcm(&ctx->aes_ctx, input, output, length, aad_head_desc, aad_len);
aes_hal_gcm_read_tag(tag, tag_len);
esp_aes_release_hardware();
return ( ret );
}
int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *aad,
size_t aad_len,
const unsigned char *tag,
size_t tag_len,
const unsigned char *input,
unsigned char *output )
{
int ret;
unsigned char check_tag[16];
size_t i;
int diff;
if ( ( ret = esp_aes_gcm_crypt_and_tag( ctx, ESP_AES_DECRYPT, length,
iv, iv_len, aad, aad_len,
input, output, tag_len, check_tag ) ) != 0 ) {
return ( ret );
}
/* Check tag in "constant-time" */
for ( diff = 0, i = 0; i < tag_len; i++ ) {
diff |= tag[i] ^ check_tag[i];
}
if ( diff != 0 ) {
bzero( output, length );
return ( MBEDTLS_ERR_GCM_AUTH_FAILED );
}
return ( 0 );
}
#endif //SOC_AES_SUPPORT_GCM

View File

@ -38,19 +38,7 @@
#include <sys/lock.h> #include <sys/lock.h>
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#if CONFIG_IDF_TARGET_ESP32 #include "aes/esp_aes.h"
#include "esp32/aes.h"
#endif
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/aes.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/aes.h"
#endif
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/aes.h"
#endif
void esp_aes_xts_init( esp_aes_xts_context *ctx ) void esp_aes_xts_init( esp_aes_xts_context *ctx )
{ {

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/** /**
* \brief AES block cipher, ESP32 hardware accelerated version * \brief AES block cipher, ESP hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version. * Based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -21,31 +21,23 @@
* *
*/ */
#ifndef ESP_AES_H #pragma once
#define ESP_AES_H
#include "esp_types.h" #include "esp_types.h"
#include "esp32s3/rom/aes.h" #include "hal/aes_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* padlock.c and aesni.c rely on these values! */
#define ESP_AES_ENCRYPT 1
#define ESP_AES_DECRYPT 0
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ #define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/** /**
* \brief AES context structure * \brief AES context structure
* *
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/ */
typedef struct { typedef struct {
uint8_t key_bytes; uint8_t key_bytes;
@ -53,17 +45,20 @@ typedef struct {
uint8_t key[32]; uint8_t key[32];
} esp_aes_context; } esp_aes_context;
/** /**
* \brief The AES XTS context-type definition. * \brief The AES XTS context-type definition.
*/ */
typedef struct { typedef struct
{
esp_aes_context crypt; /*!< The AES context to use for AES block esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */ encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak esp_aes_context tweak; /*!< The AES context used for tweak
computation. */ computation. */
} esp_aes_xts_context; } esp_aes_xts_context;
/** /**
* \brief Lock access to AES hardware unit * \brief Lock access to AES hardware unit
* *
@ -99,7 +94,7 @@ void esp_aes_init( esp_aes_context *ctx );
*/ */
void esp_aes_free( esp_aes_context *ctx ); void esp_aes_free( esp_aes_context *ctx );
/* /**
* \brief This function initializes the specified AES XTS context. * \brief This function initializes the specified AES XTS context.
* *
* It must be the first API called before using * It must be the first API called before using
@ -116,16 +111,6 @@ void esp_aes_xts_init( esp_aes_xts_context *ctx );
*/ */
void esp_aes_xts_free( esp_aes_xts_context *ctx ); void esp_aes_xts_free( esp_aes_xts_context *ctx );
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
/** /**
* \brief AES set key schedule (encryption or decryption) * \brief AES set key schedule (encryption or decryption)
* *
@ -317,13 +302,18 @@ int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
unsigned int keybits ); unsigned int keybits );
/** /**
* \brief Internal AES block encryption function * \brief This function prepares an XTS context for decryption and
* (Only exposed to allow overriding it, * sets the decryption key.
* see AES_ENCRYPT_ALT)
* *
* \param ctx AES context * \param ctx The AES XTS context to which the key should be bound.
* \param input Plaintext block * \param key The decryption key. This is comprised of the XTS key1
* \param output Output (ciphertext) block * concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/ */
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx, int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key, const unsigned char *key,
@ -341,9 +331,6 @@ int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
*/ */
int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_encrypt */
void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/** /**
* \brief Internal AES block decryption function * \brief Internal AES block decryption function
* (Only exposed to allow overriding it, * (Only exposed to allow overriding it,
@ -355,15 +342,15 @@ void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsig
*/ */
int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_decrypt */
void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/** AES-XTS buffer encryption/decryption */ /** AES-XTS 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 ); 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 );
/** Deprecated, see esp_aes_internal_decrypt */
void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/** Deprecated, see esp_aes_internal_encrypt */
void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* aes.h */

View File

@ -1,5 +1,5 @@
/** /**
* \brief AES block cipher, ESP32C hardware accelerated version * \brief AES GCM block cipher, ESP hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version. * Based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
@ -21,11 +21,12 @@
* *
*/ */
#ifndef ESP_GCM_H #pragma once
#define ESP_GCM_H
#include "aes.h" #include "aes/esp_aes.h"
#include "mbedtls/cipher.h" #include "mbedtls/cipher.h"
#include "soc/lldesc.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -36,6 +37,7 @@ extern "C" {
typedef enum { typedef enum {
ESP_AES_GCM_STATE_INIT, ESP_AES_GCM_STATE_INIT,
ESP_AES_GCM_STATE_START,
ESP_AES_GCM_STATE_UPDATE, ESP_AES_GCM_STATE_UPDATE,
ESP_AES_GCM_STATE_FINISH ESP_AES_GCM_STATE_FINISH
} esp_aes_gcm_state; } esp_aes_gcm_state;
@ -59,6 +61,7 @@ typedef struct {
esp_aes_gcm_state gcm_state; esp_aes_gcm_state gcm_state;
} esp_gcm_context; } esp_gcm_context;
/** /**
* \brief This function initializes the specified GCM context * \brief This function initializes the specified GCM context
* *
@ -96,8 +99,8 @@ int esp_aes_gcm_setkey( esp_gcm_context *ctx,
* \param iv The initialization vector. * \param iv The initialization vector.
* \param iv_len The length of the IV. * \param iv_len The length of the IV.
* \param add The buffer holding the additional data, or NULL * \param add The buffer holding the additional data, or NULL
* if \p add_len is 0. * if \p aad_len is 0.
* \param add_len The length of the additional data. If 0, * \param aad_len The length of the additional data. If 0,
* \p add is NULL. * \p add is NULL.
* *
* \return \c 0 on success. * \return \c 0 on success.
@ -176,7 +179,7 @@ void esp_aes_gcm_free( esp_gcm_context *ctx);
* \param iv The initialization vector. * \param iv The initialization vector.
* \param iv_len The length of the IV. * \param iv_len The length of the IV.
* \param add The buffer holding the additional data. * \param add The buffer holding the additional data.
* \param add_len The length of the additional data. * \param aad_len The length of the additional data.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
* \param output The buffer for holding the output data. * \param output The buffer for holding the output data.
* \param tag_len The length of the tag to generate. * \param tag_len The length of the tag to generate.
@ -190,7 +193,7 @@ int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
const unsigned char *iv, const unsigned char *iv,
size_t iv_len, size_t iv_len,
const unsigned char *add, const unsigned char *add,
size_t add_len, size_t aad_len,
const unsigned char *input, const unsigned char *input,
unsigned char *output, unsigned char *output,
size_t tag_len, size_t tag_len,
@ -211,7 +214,7 @@ int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
* \param iv The initialization vector. * \param iv The initialization vector.
* \param iv_len The length of the IV. * \param iv_len The length of the IV.
* \param add The buffer holding the additional data. * \param add The buffer holding the additional data.
* \param add_len The length of the additional data. * \param aad_len The length of the additional data.
* \param tag The buffer holding the tag. * \param tag The buffer holding the tag.
* \param tag_len The length of the tag. * \param tag_len The length of the tag.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
@ -225,7 +228,7 @@ int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
const unsigned char *iv, const unsigned char *iv,
size_t iv_len, size_t iv_len,
const unsigned char *add, const unsigned char *add,
size_t add_len, size_t aad_len,
const unsigned char *tag, const unsigned char *tag,
size_t tag_len, size_t tag_len,
const unsigned char *input, const unsigned char *input,
@ -234,5 +237,3 @@ int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* gcm.h */

View File

@ -1,4 +1,7 @@
/** /**
* \brief AES block cipher, ESP-IDF hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd * Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
@ -15,26 +18,37 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* * Internal API
*/ */
#ifndef ESP_CRYPTO_DMA_H #pragma once
#define ESP_CRYPTO_DMA_H
#include <freertos/FreeRTOS.h>
#include "aes/esp_aes.h"
#include "aes/esp_aes_gcm.h"
#include <stdbool.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
bool valid_key_length(const esp_aes_context *ctx);
/* Since crypto DMA is shared between DMA-AES and SHA blocks
* Needs to be taken by respective blocks before using Crypto DMA /**
* @brief Run a AES-GCM conversion using DMA
*
* @param ctx Aes context
* @param input Pointer to input data
* @param output Pointer to output data
* @param len Length of the input data
* @param aad_desc GCM additional data DMA descriptor
* @param aad_len GCM additional data length
* @return int -1 on error
*/ */
extern _lock_t crypto_dma_lock; int esp_aes_process_dma_gcm(esp_aes_context *ctx, const unsigned char *input, unsigned char *output, size_t len, lldesc_t *aad_desc, size_t aad_len);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* crypto_dma.h */

View File

@ -28,15 +28,7 @@ extern "C" {
#endif #endif
#if defined(MBEDTLS_AES_ALT) #if defined(MBEDTLS_AES_ALT)
#if CONFIG_IDF_TARGET_ESP32 #include "aes/esp_aes.h"
#include "esp32/aes.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/aes.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/aes.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/aes.h"
#endif
typedef esp_aes_context mbedtls_aes_context; typedef esp_aes_context mbedtls_aes_context;

View File

@ -24,330 +24,8 @@
#ifndef ESP_AES_H #ifndef ESP_AES_H
#define ESP_AES_H #define ESP_AES_H
#include "esp_types.h" #warning "esp32/aes.h is deprecated, please use aes/esp_aes.h instead"
#include "esp32/rom/aes.h"
#ifdef __cplusplus #include "aes/esp_aes.h"
extern "C" {
#endif
/* padlock.c and aesni.c rely on these values! */
#define ESP_AES_ENCRYPT 1
#define ESP_AES_DECRYPT 0
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/**
* \brief AES context structure
*
*/
typedef struct {
uint8_t key_bytes;
volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
uint8_t key[32];
} esp_aes_context;
/**
* \brief The AES XTS context-type definition.
*/
typedef struct
{
esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak
computation. */
} esp_aes_xts_context;
/**
* \brief Lock access to AES hardware unit
*
* AES hardware unit can only be used by one
* consumer at a time.
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_acquire_hardware( void );
/**
* \brief Unlock access to AES hardware unit
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_release_hardware( void );
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void esp_aes_init( esp_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void esp_aes_free( esp_aes_context *ctx );
/**
* \brief This function initializes the specified AES XTS context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The AES XTS context to initialize.
*/
void esp_aes_xts_init( esp_aes_xts_context *ctx );
/**
* \brief This function releases and clears the specified AES XTS context.
*
* \param ctx The AES XTS context to clear.
*/
void esp_aes_xts_free( esp_aes_xts_context *ctx );
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] );
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or ERR_AES_INVALID_INPUT_LENGTH
*/
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 );
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
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 );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
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 );
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
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 );
/**
* \brief This function prepares an XTS context for encryption and
* sets the encryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function performs an AES-OFB (Output Feedback Mode)
* encryption or decryption operation.
*
* \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param length The length of the input data.
* \param iv_off The offset in IV (updated after use).
* It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
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 );
/**
* \brief This function prepares an XTS context for decryption and
* sets the decryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The decryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** AES-XTS 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
#endif /* aes.h */ #endif /* aes.h */

View File

@ -24,346 +24,10 @@
#ifndef ESP_AES_H #ifndef ESP_AES_H
#define ESP_AES_H #define ESP_AES_H
#include "esp_types.h"
#include "esp32s2/rom/aes.h"
#ifdef __cplusplus //#warning "esp32s2/aes.h is deprecated, please use aes/esp_aes.h instead"
extern "C" {
#endif
/* padlock.c and aesni.c rely on these values! */ #include "aes/esp_aes.h"
#define ESP_AES_ENCRYPT 1
#define ESP_AES_DECRYPT 0
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/**
* \brief AES context structure
*
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/
typedef struct {
uint8_t key_bytes;
volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
uint8_t key[32];
} esp_aes_context;
/**
* \brief The AES XTS context-type definition.
*/
typedef struct {
esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak
computation. */
} esp_aes_xts_context;
/**
* \brief Lock access to AES hardware unit
*
* AES hardware unit can only be used by one
* consumer at a time.
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_acquire_hardware( void );
/**
* \brief Unlock access to AES hardware unit
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_release_hardware( void );
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void esp_aes_init( esp_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void esp_aes_free( esp_aes_context *ctx );
/*
* \brief This function initializes the specified AES XTS context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The AES XTS context to initialize.
*/
void esp_aes_xts_init( esp_aes_xts_context *ctx );
/**
* \brief This function releases and clears the specified AES XTS context.
*
* \param ctx The AES XTS context to clear.
*/
void esp_aes_xts_free( esp_aes_xts_context *ctx );
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] );
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or ERR_AES_INVALID_INPUT_LENGTH
*/
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 );
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
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 );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
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 );
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
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 );
/**
* \brief This function performs an AES-OFB (Output Feedback Mode)
* encryption or decryption operation.
*
* \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param length The length of the input data.
* \param iv_off The offset in IV (updated after use).
* It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
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 );
/**
* \brief This function prepares an XTS context for encryption and
* sets the encryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_encrypt */
void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_decrypt */
void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/** AES-XTS 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
#endif /* aes.h */ #endif /* aes.h */

View File

@ -20,220 +20,8 @@
* *
* *
*/ */
#pragma once
#ifndef ESP_GCM_H #warning "esp32s2/gcm.h is deprecated, please use aes/esp_aes_gcm.h instead"
#define ESP_GCM_H
#include "aes.h" #include "aes/esp_aes_gcm.h"
#include "mbedtls/cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function.*/
typedef enum {
ESP_AES_GCM_STATE_INIT,
ESP_AES_GCM_STATE_START,
ESP_AES_GCM_STATE_UPDATE,
ESP_AES_GCM_STATE_FINISH
} esp_aes_gcm_state;
/**
* \brief The GCM context structure.
*/
typedef struct {
uint8_t H[16]; /*!< Initial hash value */
uint8_t ghash[16]; /*!< GHASH value. */
uint8_t J0[16];
uint64_t HL[16]; /*!< Precalculated HTable low. */
uint64_t HH[16]; /*!< Precalculated HTable high. */
uint8_t ori_j0[16]; /*!< J0 from first iteration. */
const uint8_t *iv;
size_t iv_len; /*!< The length of IV. */
uint64_t aad_len; /*!< The total length of the additional data. */
size_t data_len;
int mode;
const unsigned char *aad; /*!< The additional data. */
esp_aes_context aes_ctx;
esp_aes_gcm_state gcm_state;
} esp_gcm_context;
/**
* \brief This function initializes the specified GCM context
*
* \param ctx The GCM context to initialize.
*/
void esp_aes_gcm_init( esp_gcm_context *ctx);
/**
* \brief This function associates a GCM context with a
* key.
*
* \param ctx The GCM context to initialize.
* \param cipher The 128-bit block cipher to use.
* \param key The encryption key.
* \param keybits The key size in bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return A cipher-specific error code on failure.
*/
int esp_aes_gcm_setkey( esp_gcm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function starts a GCM encryption or decryption
* operation.
*
* \param ctx The GCM context.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data, or NULL
* if \p add_len is 0.
* \param add_len The length of the additional data. If 0,
* \p add is NULL.
*
* \return \c 0 on success.
*/
int esp_aes_gcm_starts( esp_gcm_context *ctx,
int mode,
const unsigned char *iv,
size_t iv_len,
const unsigned char *aad,
size_t aad_len );
/**
* \brief This function feeds an input buffer into an ongoing GCM
* encryption or decryption operation.
*
* ` The function expects input to be a multiple of 16
* Bytes. Only the last call before calling
* mbedtls_gcm_finish() can be less than 16 Bytes.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/
int esp_aes_gcm_update( esp_gcm_context *ctx,
size_t length,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function finishes the GCM operation and generates
* the authentication tag.
*
* It wraps up the GCM stream, and generates the
* tag. The tag can have a maximum length of 16 Bytes.
*
* \param ctx The GCM context.
* \param tag The buffer for holding the tag.
* \param tag_len The length of the tag to generate. Must be at least four.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/
int esp_aes_gcm_finish( esp_gcm_context *ctx,
unsigned char *tag,
size_t tag_len );
/**
* \brief This function clears a GCM context
*
* \param ctx The GCM context to clear.
*/
void esp_aes_gcm_free( esp_gcm_context *ctx);
/**
* \brief This function performs GCM encryption or decryption of a buffer.
*
* \note For encryption, the output buffer can be the same as the
* input buffer. For decryption, the output buffer cannot be
* the same as input buffer. If the buffers overlap, the output
* buffer must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context to use for encryption or decryption.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
* \param tag_len The length of the tag to generate.
* \param tag The buffer for holding the tag.
*
* \return \c 0 on success.
*/
int esp_aes_gcm_crypt_and_tag( esp_gcm_context *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 );
/**
* \brief This function performs a GCM authenticated decryption of a
* buffer.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context.
* \param length The length of the input data. This must be a multiple
* of 16 except in the last call before mbedtls_gcm_finish().
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag.
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
*
* \return 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
*/
int esp_aes_gcm_auth_decrypt( esp_gcm_context *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 );
#ifdef __cplusplus
}
#endif
#endif /* gcm.h */

View File

@ -23,18 +23,16 @@
#ifndef GCM_ALT_H #ifndef GCM_ALT_H
#define GCM_ALT_H #define GCM_ALT_H
#include "soc/soc_caps.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if defined(MBEDTLS_GCM_ALT) #if defined(MBEDTLS_GCM_ALT)
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 #if SOC_AES_SUPPORT_GCM
#if CONFIG_IDF_TARGET_ESP32C3 #include "aes/esp_aes_gcm.h"
#include "esp32s3/gcm.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/gcm.h"
#endif
typedef esp_gcm_context mbedtls_gcm_context; typedef esp_gcm_context mbedtls_gcm_context;
@ -48,24 +46,7 @@ typedef esp_gcm_context mbedtls_gcm_context;
#define mbedtls_gcm_auth_decrypt esp_aes_gcm_auth_decrypt #define mbedtls_gcm_auth_decrypt esp_aes_gcm_auth_decrypt
#define mbedtls_gcm_crypt_and_tag esp_aes_gcm_crypt_and_tag #define mbedtls_gcm_crypt_and_tag esp_aes_gcm_crypt_and_tag
#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 #endif // SOC_AES_SUPPORT_GCM
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/gcm.h"
typedef esp_gcm_context mbedtls_gcm_context;
#define mbedtls_gcm_init esp_aes_gcm_init
#define mbedtls_gcm_free esp_aes_gcm_free
#define mbedtls_gcm_setkey esp_aes_gcm_setkey
#define mbedtls_gcm_starts esp_aes_gcm_starts
#define mbedtls_gcm_update esp_aes_gcm_update
#define mbedtls_gcm_finish esp_aes_gcm_finish
#define mbedtls_gcm_auth_decrypt esp_aes_gcm_auth_decrypt
#define mbedtls_gcm_crypt_and_tag esp_aes_gcm_crypt_and_tag
#endif // CONFIG_IDF_TARGET_ESP32S2
#endif /* MBEDTLS_GCM_ALT */ #endif /* MBEDTLS_GCM_ALT */

View File

@ -335,9 +335,9 @@ TEST_CASE("mbedtls CTR stream test", "[aes]")
memset(key, 0x44, 16); memset(key, 0x44, 16);
// allocate internal memory // allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext); TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(plaintext);
@ -383,113 +383,6 @@ TEST_CASE("mbedtls CTR stream test", "[aes]")
free(decryptedtext); free(decryptedtext);
} }
TEST_CASE("mbedtls GCM stream test", "[aes]")
{
const unsigned SZ = 100;
mbedtls_gcm_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t tag[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
/* Cipher produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = b'\x56' * 16
iv = b'\x89' * 16
data = b'\xab' * 100
aesgcm = AESGCM(key)
ct = aesgcm.encrypt(iv, data, '')
ct_arr = ""
for idx, b in enumerate(ct):
if idx % 8 == 0:
ct_arr += '\n'
ct_arr += "0x{}, ".format(binascii.hexlify(b))
print(ct_arr)
*/
const uint8_t expected_cipher[] = {
0x03, 0x92, 0x13, 0x49, 0x1f, 0x1f, 0x24, 0x41,
0xe8, 0xeb, 0x89, 0x47, 0x50, 0x0a, 0xce, 0xa3,
0xc7, 0x1c, 0x10, 0x70, 0xb0, 0x89, 0x82, 0x5e,
0x0f, 0x4a, 0x23, 0xee, 0xd2, 0xfc, 0xff, 0x45,
0x61, 0x4c, 0xd1, 0xfb, 0x6d, 0xe2, 0xbe, 0x67,
0x6f, 0x94, 0x72, 0xa3, 0xe7, 0x04, 0x99, 0xb3,
0x4a, 0x46, 0xf9, 0x2b, 0xaf, 0xac, 0xa9, 0x0e,
0x43, 0x7e, 0x8b, 0xc4, 0xbf, 0x49, 0xa4, 0x83,
0x9c, 0x31, 0x11, 0x1c, 0x09, 0xac, 0x90, 0xdf,
0x00, 0x34, 0x08, 0xe5, 0x70, 0xa3, 0x7e, 0x4b,
0x36, 0x48, 0x5a, 0x3f, 0x28, 0xc7, 0x1c, 0xd9,
0x1b, 0x1b, 0x49, 0x96, 0xe9, 0x7c, 0xea, 0x54,
0x7c, 0x71, 0x29, 0x0d
};
const uint8_t expected_tag[] = {
0x35, 0x1c, 0x21, 0xc6, 0xbc, 0x6b, 0x18, 0x52,
0x90, 0xe1, 0xf2, 0x5b, 0xe1, 0xf6, 0x15, 0xee,
};
memset(nonce, 0x89, 16);
memset(key, 0x56, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
memset(plaintext, 0xAB, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
for (int bytes_to_process = 16; bytes_to_process < SZ; bytes_to_process = bytes_to_process + 16) {
memset(nonce, 0x89, 16);
memset(chipertext, 0x0, SZ);
memset(decryptedtext, 0x0, SZ);
memset(tag, 0x0, 16);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, key, 128);
mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, nonce, sizeof(nonce), NULL, 0 );
// Encrypt
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_gcm_update(&ctx, length, plaintext + idx, chipertext + idx );
}
mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag, sizeof(tag));
// Decrypt
memset(nonce, 0x89, 16);
mbedtls_gcm_free( &ctx );
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, key, 128);
mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, nonce, sizeof(nonce), NULL, 0 );
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_gcm_update(&ctx, length, chipertext + idx, decryptedtext + idx );
}
mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_gcm_free( &ctx );
}
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls OFB stream test", "[aes]") TEST_CASE("mbedtls OFB stream test", "[aes]")
{ {
@ -534,9 +427,9 @@ TEST_CASE("mbedtls OFB stream test", "[aes]")
memset(key, 0x44, 16); memset(key, 0x44, 16);
// allocate internal memory // allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext); TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(plaintext);
@ -620,9 +513,9 @@ TEST_CASE("mbedtls CFB8 stream test", "[aes]")
memset(key, 0x44, 16); memset(key, 0x44, 16);
// allocate internal memory // allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext); TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(plaintext);
@ -703,9 +596,9 @@ TEST_CASE("mbedtls CFB128 stream test", "[aes]")
memset(key, 0x44, 16); memset(key, 0x44, 16);
// allocate internal memory // allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext); TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(plaintext);
@ -790,7 +683,7 @@ void aes_psram_ctr_test(uint32_t input_buf_caps, uint32_t output_buf_caps)
// allocate memory according the requested caps // allocate memory according the requested caps
uint8_t *chipertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps); uint8_t *chipertext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, output_buf_caps);
uint8_t *plaintext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, input_buf_caps); uint8_t *plaintext = heap_caps_malloc(SZ + ALIGNMENT_SIZE_BYTES, input_buf_caps);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext); TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext); TEST_ASSERT_NOT_NULL(plaintext);
@ -1392,7 +1285,7 @@ const uint8_t expected_cipher_long_input_end[] = {
0x6a, 0xde, 0xe3, 0x53, 0x6a, 0xde, 0xe3, 0x53,
}; };
void aes_icache_ctr_test(uint32_t output_buf_caps) void aes_ext_flash_ctr_test(uint32_t output_buf_caps)
{ {
mbedtls_aes_context ctx; mbedtls_aes_context ctx;
uint8_t nonce[16]; uint8_t nonce[16];
@ -1402,9 +1295,8 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
memset(nonce, 0x2F, 16); memset(nonce, 0x2F, 16);
memset(key, 0x1E, 16); memset(key, 0x1E, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, output_buf_caps); uint8_t *chipertext = heap_caps_malloc(SZ, output_buf_caps);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA); uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext); TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(decryptedtext); TEST_ASSERT_NOT_NULL(decryptedtext);
@ -1414,7 +1306,7 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
size_t offset; size_t offset;
// Encrypt with input buffer in external ram // Encrypt with input buffer in external flash
offset = 0; offset = 0;
memset(nonce, 0x2F, 16); memset(nonce, 0x2F, 16);
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, chipertext); mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, long_input, chipertext);
@ -1423,7 +1315,7 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
// Decrypt // Decrypt
offset = 0; offset = 0;
memset(nonce, 0x2F, 16); memset(nonce, 0x2F, 16);
// Decrypt with input buffer in instruction memory, the crypto DMA can't access this // Decrypt with input buffer in external flash, the crypto DMA can't access this
mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext, decryptedtext); mbedtls_aes_crypt_ctr(&ctx, SZ, &offset, nonce, stream_block, chipertext, decryptedtext);
TEST_ASSERT_EQUAL_HEX8_ARRAY(long_input, decryptedtext, SZ); TEST_ASSERT_EQUAL_HEX8_ARRAY(long_input, decryptedtext, SZ);
@ -1435,87 +1327,16 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
/* Tests how crypto DMA handles data in external memory */ /* Tests how crypto DMA handles data in external memory */
TEST_CASE("mbedtls AES PSRAM tests", "[aes]") TEST_CASE("mbedtls AES PSRAM tests", "[aes]")
{ {
aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); aes_psram_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); aes_psram_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
aes_psram_one_buf_ctr_test(); aes_psram_one_buf_ctr_test();
} }
/* Tests how crypto DMA handles data from iCache */ /* Tests how crypto DMA handles data from external flash */
TEST_CASE("mbedtls AES iCache tests", "[aes]") TEST_CASE("mbedtls AES external flash tests", "[aes]")
{ {
aes_icache_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); aes_ext_flash_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
aes_icache_ctr_test(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); aes_ext_flash_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
} }
#endif // CONFIG_SPIRAM_USE_MALLOC #endif // CONFIG_SPIRAM_USE_MALLOC
TEST_CASE("mbedtls AES GCM self-tests", "[aes]")
{
TEST_ASSERT_FALSE_MESSAGE(mbedtls_gcm_self_test(1), "AES GCM self-test should pass.");
}
TEST_CASE("mbedtls AES GCM crypt-and-tag", "[aes]")
{
const unsigned CALL_SZ = 32 * 1024;
mbedtls_gcm_context ctx;
unsigned char tag_buf[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
uint8_t aad[16];
memset(aad, 0x22, 16);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
memset(buf, 0xAA, CALL_SZ);
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
Last block and tag produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = b'\x44' * 16
iv = b'\xEE' * 16
data = b'\xAA' * 100
aad = b'\x22 * 16
aesgcm = AESGCM(key)
ct = aesgcm.encrypt(iv, data, aad)
*/
const uint8_t expected_last_block[] = {
0x7d, 0x3d, 0x16, 0x84, 0xd0, 0xb4, 0x38, 0x30,
0xd1, 0x24, 0x6f, 0x7e, 0x9a, 0x9c, 0x81, 0x58,
};
const uint8_t expected_tag[] = {
0x7e, 0x16, 0x04, 0x07, 0x4b, 0x7e, 0x6b, 0xf7,
0x5d, 0xce, 0x9e, 0x7d, 0x3f, 0x85, 0xc5, 0xa5,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
memset(iv, 0xEE, 16);
TEST_ASSERT_EQUAL(mbedtls_gcm_auth_decrypt(&ctx, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), expected_tag, sizeof(expected_tag), buf, buf), 0);
TEST_ASSERT_EACH_EQUAL_HEX8(0xAA, buf, CALL_SZ);
free(buf);
}

View File

@ -0,0 +1,494 @@
/* mbedTLS GCM test
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
#include "ccomp_timer.h"
#include "sys/param.h"
#if CONFIG_MBEDTLS_HARDWARE_GCM
/*
Python example code for generating test vectors
import os, binascii
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def as_c_array(byte_arr):
hex_str = ''
for idx, byte in enumerate(byte_arr):
hex_str += "0x{:02x}, ".format(byte)
bytes_per_line = 8
if idx % bytes_per_line == bytes_per_line - 1:
hex_str += '\n'
return hex_str
key = b'\x44' * 16
iv = b'\xEE' * 16
data = b'\xAA' * 3200
aad = b'\x76' * 16
aesgcm = AESGCM(key)
ct = aesgcm.encrypt(iv, data, aad)
print(as_c_array(ct))
*/
TEST_CASE("mbedtls GCM stream test", "[aes-gcm]")
{
const unsigned SZ = 100;
mbedtls_gcm_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t tag[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
const uint8_t expected_cipher[] = {
0x03, 0x92, 0x13, 0x49, 0x1f, 0x1f, 0x24, 0x41,
0xe8, 0xeb, 0x89, 0x47, 0x50, 0x0a, 0xce, 0xa3,
0xc7, 0x1c, 0x10, 0x70, 0xb0, 0x89, 0x82, 0x5e,
0x0f, 0x4a, 0x23, 0xee, 0xd2, 0xfc, 0xff, 0x45,
0x61, 0x4c, 0xd1, 0xfb, 0x6d, 0xe2, 0xbe, 0x67,
0x6f, 0x94, 0x72, 0xa3, 0xe7, 0x04, 0x99, 0xb3,
0x4a, 0x46, 0xf9, 0x2b, 0xaf, 0xac, 0xa9, 0x0e,
0x43, 0x7e, 0x8b, 0xc4, 0xbf, 0x49, 0xa4, 0x83,
0x9c, 0x31, 0x11, 0x1c, 0x09, 0xac, 0x90, 0xdf,
0x00, 0x34, 0x08, 0xe5, 0x70, 0xa3, 0x7e, 0x4b,
0x36, 0x48, 0x5a, 0x3f, 0x28, 0xc7, 0x1c, 0xd9,
0x1b, 0x1b, 0x49, 0x96, 0xe9, 0x7c, 0xea, 0x54,
0x7c, 0x71, 0x29, 0x0d
};
const uint8_t expected_tag[] = {
0x35, 0x1c, 0x21, 0xc6, 0xbc, 0x6b, 0x18, 0x52,
0x90, 0xe1, 0xf2, 0x5b, 0xe1, 0xf6, 0x15, 0xee,
};
memset(nonce, 0x89, 16);
memset(key, 0x56, 16);
// allocate internal memory
uint8_t *chipertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(chipertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
memset(plaintext, 0xAB, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
for (int bytes_to_process = 16; bytes_to_process < SZ; bytes_to_process = bytes_to_process + 16) {
memset(nonce, 0x89, 16);
memset(chipertext, 0x0, SZ);
memset(decryptedtext, 0x0, SZ);
memset(tag, 0x0, 16);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, key, 128);
mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, nonce, sizeof(nonce), NULL, 0 );
// Encrypt
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_gcm_update(&ctx, length, plaintext + idx, chipertext + idx );
}
mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, chipertext, SZ);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag, sizeof(tag));
// Decrypt
memset(nonce, 0x89, 16);
mbedtls_gcm_free( &ctx );
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, key, 128);
mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, nonce, sizeof(nonce), NULL, 0 );
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_gcm_update(&ctx, length, chipertext + idx, decryptedtext + idx );
}
mbedtls_gcm_finish( &ctx, tag, sizeof(tag) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_gcm_free( &ctx );
}
free(plaintext);
free(chipertext);
free(decryptedtext);
}
TEST_CASE("mbedtls AES GCM self-tests", "[aes-gcm]")
{
TEST_ASSERT_FALSE_MESSAGE(mbedtls_gcm_self_test(1), "AES GCM self-test should pass.");
}
typedef struct {
uint8_t *plaintext;
size_t plaintext_length;
uint32_t output_caps;
uint8_t *add_buf;
size_t add_length;
uint8_t *iv;
size_t iv_length;
uint8_t *key;
size_t key_bits;
size_t tag_len;
} aes_gcm_test_cfg_t;
typedef struct {
const uint8_t *expected_tag;
const uint8_t *ciphertext_last_block; // Last block of the chipertext
} aes_gcm_test_expected_res_t;
typedef enum {
AES_GCM_TEST_CRYPT_N_TAG,
AES_GCM_TEST_START_UPDATE_FINISH,
} aes_gcm_test_type_t;
static void aes_gcm_test(aes_gcm_test_cfg_t *cfg, aes_gcm_test_expected_res_t *res, aes_gcm_test_type_t aes_gcm_type)
{
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
mbedtls_gcm_context ctx;
uint8_t tag_buf_encrypt[16] = {};
uint8_t tag_buf_decrypt[16] = {};
uint8_t iv_buf[16] = {};
uint8_t *ciphertext = heap_caps_malloc(cfg->plaintext_length, cfg->output_caps);
uint8_t *output = heap_caps_malloc(cfg->plaintext_length, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
if (cfg->plaintext_length != 0) {
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(output);
}
memset(ciphertext, 0, cfg->plaintext_length);
memset(output, 0, cfg->plaintext_length);
memcpy(iv_buf, cfg->iv, cfg->iv_length);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits);
/* Encrypt and tag */
if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) {
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt);
} else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH){
TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length) == 0 );
TEST_ASSERT(mbedtls_gcm_update( &ctx, cfg->plaintext_length, cfg->plaintext, ciphertext) == 0 );
TEST_ASSERT(mbedtls_gcm_finish( &ctx, tag_buf_encrypt, cfg->tag_len) == 0 );
}
size_t offset = cfg->plaintext_length > 16 ? cfg->plaintext_length - 16 : 0;
/* Sanity check: make sure the last ciphertext block matches what we expect to see. */
TEST_ASSERT_EQUAL_HEX8_ARRAY(res->ciphertext_last_block, ciphertext + offset, MIN(16, cfg->plaintext_length));
TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_encrypt, cfg->tag_len);
/* Decrypt and authenticate */
if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) {
TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0);
} else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH){
TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length) == 0 );
TEST_ASSERT(mbedtls_gcm_update( &ctx, cfg->plaintext_length, ciphertext, output) == 0 );
TEST_ASSERT(mbedtls_gcm_finish( &ctx, tag_buf_decrypt, cfg->tag_len) == 0 );
/* mbedtls_gcm_auth_decrypt already checks tag so only needed for AES_GCM_TEST_START_UPDATE_FINISH */
TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_decrypt, cfg->tag_len);
}
TEST_ASSERT_EQUAL_HEX8_ARRAY(cfg->plaintext, output, cfg->plaintext_length);
free(ciphertext);
free(output);
}
TEST_CASE("mbedtls AES GCM", "[aes-gcm]")
{
uint8_t iv[16];
uint8_t key[16];
uint8_t add[30];
memset(iv, 0xB1, sizeof(iv));
memset(key, 0x27, sizeof(key));
memset(add, 0x90, sizeof(add));
size_t length[] = {10, 16, 500, 5000, 12345};
const uint8_t expected_last_block[][16] = {
{0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1,
0x60, 0x72},
{0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1,
0x60, 0x72, 0x9a, 0x81, 0x8d, 0x3c, 0x69, 0x66},
{0x9d, 0x7a, 0xac, 0x84,0xe3, 0x70, 0x43, 0x0f,
0xa7, 0x83, 0x43, 0xc9, 0x04, 0xf8, 0x7d, 0x48},
{0xee, 0xfd, 0xab, 0x2a, 0x09, 0x44, 0x41, 0x6a,
0x91, 0xb0, 0x74, 0x24, 0xee, 0x35, 0xb1, 0x39},
{0x51, 0xf7, 0x1f, 0x67, 0x1a, 0x4a, 0x12, 0x37,
0x60, 0x3b, 0x68, 0x01, 0x20, 0x4f, 0xf3, 0xd9},
};
const uint8_t expected_tag[][16] = {
{0x06, 0x4f, 0xb5, 0x91, 0x12, 0x24, 0xb4, 0x24,
0x0b, 0xc2, 0x85, 0x59, 0x6a, 0x7c, 0x1f, 0xc9},
{0x45, 0xc2, 0xa8, 0xfe, 0xff, 0x49, 0x1f, 0x45,
0x8e, 0x29, 0x74, 0x41, 0xed, 0x9b, 0x54, 0x28},
{0xe1, 0xf9, 0x40, 0xfa, 0x29, 0x6f, 0x30, 0xae,
0xb6, 0x9b, 0x33, 0xdb, 0x8a, 0xf9, 0x70, 0xc4},
{0x22, 0xe1, 0x22, 0x34, 0x0c, 0x91, 0x0b, 0xcf,
0xa3, 0x42, 0xe0, 0x48, 0xe6, 0xfe, 0x2e, 0x28},
{0xfb, 0xfe, 0x5a, 0xed, 0x26, 0x5c, 0x5e, 0x66,
0x4e, 0xb2, 0x48, 0xce, 0xe9, 0x88, 0x1c, 0xe0},
};
aes_gcm_test_cfg_t cfg = {
.output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
.iv = iv,
.iv_length = sizeof(iv),
.key = key,
.key_bits = 8*sizeof(key),
.add_buf = add,
.add_length = sizeof(add),
.tag_len = 16
};
aes_gcm_test_expected_res_t res = {
};
for (int i = 0; i < sizeof(length)/sizeof(length[0]); i++) {
printf("Test AES-GCM with plaintext length = %d\n", length[i]);
uint8_t *input = heap_caps_malloc(length[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT(input != NULL || length[i] == 0);
memset(input, 0x36, length[i]);
cfg.plaintext = input;
cfg.plaintext_length = length[i];
res.expected_tag = expected_tag[i];
res.ciphertext_last_block = expected_last_block[i],
aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
free(input);
}
}
TEST_CASE("mbedtls AES GCM - Different add messages", "[aes-gcm]")
{
const unsigned CALL_SZ = 160;
uint8_t iv[16];
uint8_t key[16];
uint8_t *input = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(input);
memset(input, 0x67, CALL_SZ);
memset(iv, 0xA2, sizeof(iv));
memset(key, 0x48, sizeof(key));
const uint8_t expected_last_block[] = {
0xcd, 0xb9, 0xad, 0x6f, 0xc9, 0x35, 0x21, 0x0d,
0xc9, 0x5d, 0xea, 0xd9, 0xf7, 0x1d, 0x43, 0xed
};
size_t add_len[] = {0, 10, 16, 500, 5000};
const uint8_t expected_tag[][16] = {
{0xe3, 0x91, 0xad, 0x40, 0x96, 0xb7, 0x8c, 0x53,
0x4d, 0x15, 0x7d, 0x55, 0x15, 0xdf, 0x10, 0x69},
{0xc2, 0x38, 0x36, 0xe9, 0x12, 0x72, 0x5b, 0x31,
0x0c, 0xde, 0xb5, 0xc9, 0x8c, 0xa3, 0xcb, 0xe7},
{0x57, 0x10, 0x22, 0x91, 0x65, 0xfa, 0x89, 0xba,
0x0a, 0x3e, 0xc1, 0x7c, 0x93, 0x6e, 0x35, 0xac},
{0x3c, 0x28, 0x03, 0xc2, 0x14, 0x40, 0xec, 0xb6,
0x25, 0xfb, 0xdd, 0x55, 0xa0, 0xb2, 0x47, 0x7b},
{0xfa, 0x66, 0x4a, 0x97, 0x2d, 0x02, 0x32, 0x5b,
0x92, 0x94, 0xf1, 0x00, 0x1c, 0xfa, 0xe3, 0x07}
};
aes_gcm_test_cfg_t cfg = {
.plaintext = input,
.plaintext_length = CALL_SZ,
.output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
.iv = iv,
.iv_length = sizeof(iv),
.key = key,
.key_bits = 8*sizeof(key),
.tag_len = 16
};
aes_gcm_test_expected_res_t res = {
.ciphertext_last_block = expected_last_block,
};
for (int i = 0; i < sizeof(add_len)/sizeof(add_len[0]); i++) {
printf("Test AES-GCM with add length = %d\n", add_len[i]);
uint8_t *add = heap_caps_malloc(add_len[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT(add != NULL || add_len[i] == 0);
memset(add, 0x12, add_len[i]);
cfg.add_buf = add;
cfg.add_length = add_len[i];
res.expected_tag = expected_tag[i];
aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
free(add);
}
free(input);
}
TEST_CASE("mbedtls AES GCM performance, start, update, ret", "[aes-gcm]")
{
const unsigned CALL_SZ = 16*3200;
mbedtls_gcm_context ctx;
float elapsed_usec;
unsigned char tag_buf[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
uint8_t aad[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
memset(aad, 0x76, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
ccomp_timer_start();
memset(buf, 0xAA, CALL_SZ);
TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv, sizeof(iv), aad, sizeof(aad) ) == 0 );
TEST_ASSERT(mbedtls_gcm_update( &ctx, CALL_SZ, buf, buf ) == 0 );
TEST_ASSERT(mbedtls_gcm_finish( &ctx, tag_buf, 16 ) == 0 );
elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
*/
const uint8_t expected_last_block[] = {
0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f,
0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d,
};
const uint8_t expected_tag[] = {
0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f,
0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16 , 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
free(buf);
// bytes/usec = MB/sec
float mb_sec = CALL_SZ / elapsed_usec;
printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
// Don't put a hard limit on software AES performance
TEST_PERFORMANCE_GREATER_THAN(AES_GCM_UPDATE_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif
}
TEST_CASE("mbedtls AES GCM performance, crypt-and-tag", "[aes-gcm]")
{
const unsigned CALL_SZ = 16*3200;
mbedtls_gcm_context ctx;
float elapsed_usec;
unsigned char tag_buf[16] = {};
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
uint8_t aad[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
memset(aad, 0x76, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
memset(buf, 0xAA, CALL_SZ);
ccomp_timer_start();
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
*/
const uint8_t expected_last_block[] = {
0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f,
0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d,
};
const uint8_t expected_tag[] = {
0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f,
0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16 , 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
free(buf);
// bytes/usec = MB/sec
float mb_sec = CALL_SZ / elapsed_usec;
printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
// Don't put a hard limit on software AES performance
TEST_PERFORMANCE_GREATER_THAN(AES_GCM_CRYPT_TAG_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif
}
#endif //CONFIG_MBEDTLS_HARDWARE_GCM

View File

@ -25,7 +25,7 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
memset(key, 0x44, 16); memset(key, 0x44, 16);
// allocate internal memory // allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf); TEST_ASSERT_NOT_NULL(buf);
mbedtls_aes_init(&ctx); mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128); mbedtls_aes_setkey_enc(&ctx, key, 128);
@ -67,75 +67,3 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
TEST_PERFORMANCE_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); TEST_PERFORMANCE_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif #endif
} }
TEST_CASE("mbedtls AES GCM performance", "[aes]")
{
const unsigned CALL_SZ = 32 * 1024;
mbedtls_gcm_context ctx;
float elapsed_usec;
unsigned char tag_buf[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
uint8_t aad[16];
memset(aad, 0x22, 16);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
ccomp_timer_start();
memset(buf, 0xAA, CALL_SZ);
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
Last block and tag produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
key = b'\x44' * 16
iv = b'\xEE' * 16
data = b'\xAA' * 100
aad = b'\x22 * 16
aesgcm = AESGCM(key)
ct = aesgcm.encrypt(iv, data, aad)
*/
const uint8_t expected_last_block[] = {
0x7d, 0x3d, 0x16, 0x84, 0xd0, 0xb4, 0x38, 0x30,
0xd1, 0x24, 0x6f, 0x7e, 0x9a, 0x9c, 0x81, 0x58,
};
const uint8_t expected_tag[] = {
0x7e, 0x16, 0x04, 0x07, 0x4b, 0x7e, 0x6b, 0xf7,
0x5d, 0xce, 0x9e, 0x7d, 0x3f, 0x85, 0xc5, 0xa5,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16 , 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
free(buf);
// bytes/usec = MB/sec
float mb_sec = CALL_SZ / elapsed_usec;
printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
// Don't put a hard limit on software AES performance
TEST_PERFORMANCE_GREATER_THAN(AES_GCM_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif
}

View File

@ -309,6 +309,7 @@ exit:
return ret; return ret;
} }
TEST_CASE("custom certificate bundle", "[mbedtls]") TEST_CASE("custom certificate bundle", "[mbedtls]")
{ {
esp_crt_validate_res_t validate_res; esp_crt_validate_res_t validate_res;

View File

@ -20,7 +20,7 @@ TEST_CASE("mbedtls SHA performance", "[aes]")
unsigned char sha256[32]; unsigned char sha256[32];
// allocate internal memory // allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf); TEST_ASSERT_NOT_NULL(buf);
memset(buf, 0x55, CALL_SZ); memset(buf, 0x55, CALL_SZ);

View File

@ -258,6 +258,11 @@
#define SOC_RSA_MAX_BIT_LEN (4096) #define SOC_RSA_MAX_BIT_LEN (4096)
/*-------------------------- AES CAPS -----------------------------------------*/
#define SOC_AES_SUPPORT_AES_128 (1)
#define SOC_AES_SUPPORT_AES_192 (1)
#define SOC_AES_SUPPORT_AES_256 (1)
/* ---------------------------- Compatibility ------------------------------- */ /* ---------------------------- Compatibility ------------------------------- */
#define SOC_CAN_SUPPORTED SOC_TWAI_SUPPORTED #define SOC_CAN_SUPPORTED SOC_TWAI_SUPPORTED
#define CAN_BRP_MIN SOC_TWAI_BRP_MIN #define CAN_BRP_MIN SOC_TWAI_BRP_MIN

View File

@ -44,3 +44,12 @@
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
#define SOC_TOUCH_SENSOR_NUM (0) /*! No touch sensors on ESP32-C3 */ #define SOC_TOUCH_SENSOR_NUM (0) /*! No touch sensors on ESP32-C3 */
/*-------------------------- AES CAPS -----------------------------------------*/
#define SOC_AES_SUPPORT_DMA (1)
/* Has a centralized DMA, which is shared with all peripherals */
#define SOC_AES_GENERAL_DMA (1)
#define SOC_AES_SUPPORT_AES_128 (1)
#define SOC_AES_SUPPORT_AES_256 (1)

View File

@ -276,6 +276,18 @@
#define SOC_RSA_MAX_BIT_LEN (4096) #define SOC_RSA_MAX_BIT_LEN (4096)
/*-------------------------- AES CAPS -----------------------------------------*/
#define SOC_AES_SUPPORT_DMA (1)
#define SOC_AES_SUPPORT_GCM (1)
/* Has "crypto DMA", which is shared with SHA */
#define SOC_AES_CRYPTO_DMA (1)
#define SOC_AES_SUPPORT_AES_128 (1)
#define SOC_AES_SUPPORT_AES_192 (1)
#define SOC_AES_SUPPORT_AES_256 (1)
/* ---------------------------- Compatibility ------------------------------- */ /* ---------------------------- Compatibility ------------------------------- */
// No contents // No contents

View File

@ -258,10 +258,14 @@
#define SOC_DIRAM_DRAM_LOW 0x3FC88000 #define SOC_DIRAM_DRAM_LOW 0x3FC88000
#define SOC_DIRAM_DRAM_HIGH 0x3FCF0000 #define SOC_DIRAM_DRAM_HIGH 0x3FCF0000
// Region of memory accessible via DMA. See esp_ptr_dma_capable(). // Region of memory accessible via DMA in internal memory. See esp_ptr_dma_capable().
#define SOC_DMA_LOW 0x3FC88000 #define SOC_DMA_LOW 0x3FC88000
#define SOC_DMA_HIGH 0x3FD00000 #define SOC_DMA_HIGH 0x3FD00000
// Region of memory accessible via DMA in external memory. See esp_ptr_dma_ext_capable().
#define SOC_DMA_EXT_LOW 0x3C000000
#define SOC_DMA_EXT_HIGH 0x3DFFFFFF
// Region of memory that is byte-accessible. See esp_ptr_byte_accessible(). // Region of memory that is byte-accessible. See esp_ptr_byte_accessible().
#define SOC_BYTE_ACCESSIBLE_LOW 0x3FC88000 #define SOC_BYTE_ACCESSIBLE_LOW 0x3FC88000
#define SOC_BYTE_ACCESSIBLE_HIGH 0x3FD00000 #define SOC_BYTE_ACCESSIBLE_HIGH 0x3FD00000

View File

@ -138,9 +138,19 @@
#define SOC_RSA_MAX_BIT_LEN (4096) #define SOC_RSA_MAX_BIT_LEN (4096)
/*-------------------------- AES CAPS -----------------------------------------*/
#define SOC_AES_SUPPORT_DMA (1)
/* Has a centralized DMA, which is shared with all peripherals */
#define SOC_AES_GENERAL_DMA (1)
#define SOC_AES_SUPPORT_AES_128 (1)
#define SOC_AES_SUPPORT_AES_256 (1)
// Attention: These fixed DMA channels are temporarily workaround before we have a centralized DMA controller API to help alloc the channel dynamically // Attention: These fixed DMA channels are temporarily workaround before we have a centralized DMA controller API to help alloc the channel dynamically
// Remove them when GDMA driver API is ready // Remove them when GDMA driver API is ready
#define SOC_GDMA_M2M_DMA_CHANNEL (0) #define SOC_GDMA_M2M_DMA_CHANNEL (0)
#define SOC_GDMA_SPI2_DMA_CHANNEL (1) #define SOC_GDMA_SPI2_DMA_CHANNEL (1)
#define SOC_GDMA_SPI3_DMA_CHANNEL (2) #define SOC_GDMA_SPI3_DMA_CHANNEL (2)
#define SOC_GDMA_SHA_DMA_CHANNEL (3) #define SOC_GDMA_SHA_DMA_CHANNEL (3)
#define SOC_GDMA_AES_DMA_CHANNEL (4)

View File

@ -148,7 +148,7 @@ inline static bool IRAM_ATTR esp_ptr_dma_capable(const void *p)
inline static bool IRAM_ATTR esp_ptr_dma_ext_capable(const void *p) inline static bool IRAM_ATTR esp_ptr_dma_ext_capable(const void *p)
{ {
#if CONFIG_IDF_TARGET_ESP32S2 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH; return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH;
#else #else
return false; return false;