mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
8929a9cdb1
@ -17,7 +17,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "sha/sha_parallel_engine.h"
|
||||
#include "esp32/aes.h"
|
||||
#include "aes/esp_aes.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
|
||||
static const char *TAG = "test";
|
||||
|
@ -2,7 +2,7 @@
|
||||
ROM functions for hardware AES support.
|
||||
|
||||
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
|
||||
|
@ -28,6 +28,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"soc_hal.c"
|
||||
"interrupt_controller_hal.c"
|
||||
"sha_hal.c"
|
||||
"aes_hal.c"
|
||||
"twai_hal.c"
|
||||
"twai_hal_iram.c"
|
||||
"${target}/interrupt_descriptor_table.c")
|
||||
|
227
components/hal/aes_hal.c
Normal file
227
components/hal/aes_hal.c
Normal 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
|
137
components/hal/esp32/include/hal/aes_ll.h
Normal file
137
components/hal/esp32/include/hal/aes_ll.h
Normal 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
|
235
components/hal/esp32c3/include/hal/aes_ll.h
Normal file
235
components/hal/esp32c3/include/hal/aes_ll.h
Normal 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(®_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
|
317
components/hal/esp32s2/include/hal/aes_ll.h
Normal file
317
components/hal/esp32s2/include/hal/aes_ll.h
Normal 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(®_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(®_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
|
@ -19,29 +19,28 @@
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
|
||||
typedef enum {
|
||||
CRYPTO_DMA_AES = 0,
|
||||
CRYPTO_DMA_AES= 0,
|
||||
CRYPTO_DMA_SHA,
|
||||
} 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);
|
||||
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
|
||||
*
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
|
235
components/hal/esp32s3/include/hal/aes_ll.h
Normal file
235
components/hal/esp32s3/include/hal/aes_ll.h
Normal 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(®_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
|
@ -52,6 +52,19 @@ extern "C" {
|
||||
#define GDMA_LL_TRIG_SRC_SHA (7)
|
||||
#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 /////////////////////////////////////////
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
@ -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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
162
components/hal/include/hal/aes_hal.h
Normal file
162
components/hal/include/hal/aes_hal.h
Normal 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
|
48
components/hal/include/hal/aes_types.h
Normal file
48
components/hal/include/hal/aes_types.h
Normal 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)
|
@ -26,7 +26,6 @@
|
||||
#include "hal/crypto_dma_ll.h"
|
||||
#elif SOC_SHA_GENERAL_DMA
|
||||
#include "hal/gdma_ll.h"
|
||||
#define DMA_PERIPH_SHA 7
|
||||
#endif
|
||||
|
||||
#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_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
|
||||
/* 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)
|
||||
{
|
||||
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_start();
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
// 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_GCM_THROUGHPUT_MBSEC 0.5
|
||||
|
||||
// SHA256 hardware throughput at 240MHz, threshold set lower than worst case
|
||||
#define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 8.0
|
||||
|
@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#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
|
||||
#define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 90.0
|
||||
|
@ -84,16 +84,19 @@ target_sources(mbedtls PRIVATE ${mbedtls_target_sources})
|
||||
# Choose perihperal type
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
set(SHA_PERIPHERAL_TYPE "parallel_engine")
|
||||
set(AES_PERIPHERAL_TYPE "block")
|
||||
else()
|
||||
set(SHA_PERIPHERAL_TYPE "dma")
|
||||
set(AES_PERIPHERAL_TYPE "dma")
|
||||
endif()
|
||||
|
||||
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c"
|
||||
"${COMPONENT_DIR}/port/esp_mem.c"
|
||||
"${COMPONENT_DIR}/port/esp_timing.c"
|
||||
"${COMPONENT_DIR}/port/sha/esp_sha.c"
|
||||
"${COMPONENT_DIR}/port/esp_aes_xts.c"
|
||||
"${COMPONENT_DIR}/port/${idf_target}/aes.c"
|
||||
"${COMPONENT_DIR}/port/aes/esp_aes_xts.c"
|
||||
"${COMPONENT_DIR}/port/aes/esp_aes_common.c"
|
||||
"${COMPONENT_DIR}/port/aes/${AES_PERIPHERAL_TYPE}/esp_aes.c"
|
||||
"${COMPONENT_DIR}/port/sha/${SHA_PERIPHERAL_TYPE}/sha.c"
|
||||
)
|
||||
|
||||
@ -121,6 +124,9 @@ if(CONFIG_MBEDTLS_HARDWARE_SHA)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_MBEDTLS_HARDWARE_GCM)
|
||||
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/aes/esp_aes_gcm.c")
|
||||
endif()
|
||||
|
||||
foreach(target ${mbedtls_targets})
|
||||
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
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
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
@ -28,9 +28,11 @@
|
||||
#include <string.h>
|
||||
#include "mbedtls/aes.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "esp32/aes.h"
|
||||
#include "aes/esp_aes.h"
|
||||
#include "soc/hwcrypto_periph.h"
|
||||
#include <sys/lock.h>
|
||||
#include "hal/aes_hal.h"
|
||||
#include "aes/esp_aes_internal.h"
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
@ -49,10 +51,6 @@
|
||||
*/
|
||||
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 )
|
||||
{
|
||||
@ -70,64 +68,7 @@ void esp_aes_release_hardware( void )
|
||||
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.
|
||||
*
|
||||
@ -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)
|
||||
{
|
||||
const uint32_t *input_words = (const uint32_t *)input;
|
||||
uint32_t i0, i1, i2, i3;
|
||||
const uint32_t *input_words = (uint32_t *)input;
|
||||
uint32_t *output_words = (uint32_t *)output;
|
||||
|
||||
/* If no key is written to hardware yet, either the user hasn't called
|
||||
@ -148,26 +89,12 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
|
||||
bzero(output, 16);
|
||||
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];
|
||||
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);
|
||||
|
||||
DPORT_REG_WRITE(AES_START_REG, 1);
|
||||
|
||||
while (DPORT_REG_READ(AES_IDLE_REG) != 1) { }
|
||||
|
||||
esp_dport_access_read_buffer(output_words, AES_TEXT_BASE, 4);
|
||||
aes_hal_transform_block(input, output);
|
||||
|
||||
/* Physical security check: Verify the AES accelerator actually ran, and wasn't
|
||||
skipped due to external fault injection while starting the peripheral.
|
||||
@ -176,7 +103,7 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
|
||||
|
||||
Bypassing this check requires at least one additional fault.
|
||||
*/
|
||||
if(i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
|
||||
if (i0 == output_words[0] && i1 == output_words[1] && i2 == output_words[2] && i3 == output_words[3]) {
|
||||
// calling zeroing functions to narrow the
|
||||
// window for a double-fault of the abort step, here
|
||||
memset(output, 0, 16);
|
||||
@ -187,12 +114,19 @@ static int esp_aes_block(esp_aes_context *ctx, const void *input, void *output)
|
||||
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
|
||||
*/
|
||||
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] )
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -202,19 +136,26 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
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);
|
||||
esp_aes_release_hardware();
|
||||
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
|
||||
*/
|
||||
|
||||
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] )
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -224,7 +165,7 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
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);
|
||||
esp_aes_release_hardware();
|
||||
return r;
|
||||
@ -233,10 +174,10 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
int esp_aes_crypt_ecb(esp_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -246,7 +187,7 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
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);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
@ -257,14 +198,13 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CBC buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_cbc(esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int i;
|
||||
uint32_t *output_words = (uint32_t *)output;
|
||||
const uint32_t *input_words = (const uint32_t *)input;
|
||||
uint32_t *iv_words = (uint32_t *)iv;
|
||||
@ -280,17 +220,18 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
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 ) {
|
||||
while ( length > 0 ) {
|
||||
memcpy(temp, input_words, 16);
|
||||
esp_aes_block(ctx, input_words, output_words);
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
output_words[i] = output_words[i] ^ iv_words[i];
|
||||
}
|
||||
output_words[0] = output_words[0] ^ iv_words[0];
|
||||
output_words[1] = output_words[1] ^ iv_words[1];
|
||||
output_words[2] = output_words[2] ^ iv_words[2];
|
||||
output_words[3] = output_words[3] ^ iv_words[3];
|
||||
|
||||
memcpy( iv_words, temp, 16 );
|
||||
|
||||
@ -301,9 +242,10 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
} else { // ESP_AES_ENCRYPT
|
||||
while ( length > 0 ) {
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
output_words[i] = input_words[i] ^ iv_words[i];
|
||||
}
|
||||
output_words[0] = input_words[0] ^ iv_words[0];
|
||||
output_words[1] = input_words[1] ^ iv_words[1];
|
||||
output_words[2] = input_words[2] ^ iv_words[2];
|
||||
output_words[3] = input_words[3] ^ iv_words[3];
|
||||
|
||||
esp_aes_block(ctx, output_words, output_words);
|
||||
memcpy( iv_words, output_words, 16 );
|
||||
@ -322,13 +264,13 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CFB128 buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int c;
|
||||
size_t n = *iv_off;
|
||||
@ -339,8 +281,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
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);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
while ( length-- ) {
|
||||
@ -376,12 +317,12 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CFB8 buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
@ -392,8 +333,8 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
|
||||
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-- ) {
|
||||
memcpy( ov, iv, 16 );
|
||||
@ -420,13 +361,13 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CTR buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_ctr(esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int c, i;
|
||||
size_t n = *nc_off;
|
||||
@ -437,17 +378,18 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
||||
|
||||
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-- ) {
|
||||
if ( n == 0 ) {
|
||||
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 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ stream_block[n] );
|
||||
@ -465,25 +407,25 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_ofb(esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int ret = 0;
|
||||
size_t n;
|
||||
|
||||
if ( ctx == NULL || iv_off == NULL || iv == NULL ||
|
||||
input == NULL || output == NULL ) {
|
||||
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
|
||||
if (ctx == NULL || iv_off == NULL || iv == NULL ||
|
||||
input == NULL || output == NULL ) {
|
||||
return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
n = *iv_off;
|
||||
|
||||
if( n > 15 ) {
|
||||
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
|
||||
if (n > 15) {
|
||||
return (MBEDTLS_ERR_AES_BAD_INPUT_DATA);
|
||||
}
|
||||
|
||||
if (!valid_key_length(ctx)) {
|
||||
@ -491,11 +433,12 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
}
|
||||
|
||||
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-- ) {
|
||||
if( n == 0 ) {
|
||||
while (length--) {
|
||||
if ( n == 0 ) {
|
||||
esp_aes_block(ctx, iv, iv);
|
||||
}
|
||||
*output++ = *input++ ^ iv[n];
|
||||
@ -507,5 +450,5 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_release_hardware();
|
||||
|
||||
return( ret );
|
||||
return ( ret );
|
||||
}
|
@ -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.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
@ -26,17 +26,8 @@
|
||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/lock.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 "driver/periph_ctrl.h"
|
||||
#include "esp_log.h"
|
||||
@ -44,18 +35,31 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "sys/param.h"
|
||||
#include "esp_pm.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/gdma_reg.h"
|
||||
#include "soc/gdma_struct.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "hal/aes_hal.h"
|
||||
#include "aes/esp_aes_internal.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/semphr.h"
|
||||
|
||||
#define AES_BLOCK_BYTES 16
|
||||
#define IV_WORDS 4
|
||||
#if SOC_AES_SUPPORT_GCM
|
||||
#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
|
||||
must be a multiple of block size
|
||||
*/
|
||||
@ -65,22 +69,6 @@
|
||||
busy-waiting, 30000 bytes is approx 0.5 ms */
|
||||
#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)
|
||||
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 _lock_t s_aes_lock;
|
||||
|
||||
static inline bool valid_key_length(const esp_aes_context *ctx)
|
||||
/* Append a descriptor to the chain, set head if chain empty */
|
||||
static inline void lldesc_append(lldesc_t **head, lldesc_t *item)
|
||||
{
|
||||
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 )
|
||||
{
|
||||
_lock_acquire(&s_aes_lock);
|
||||
/* Released by esp_aes_release_hardware()*/
|
||||
AES_LOCK();
|
||||
|
||||
/* Enable AES hardware */
|
||||
//periph_module_enable(PERIPH_AES_DMA_MODULE);
|
||||
/* Enable AES hardware */
|
||||
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_CRYPTO_AES_CLK_EN | SYSTEM_DMA_CLK_EN);
|
||||
/* Clear reset on digital signature unit,
|
||||
otherwise AES unit is held in reset also. */
|
||||
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG,
|
||||
SYSTEM_CRYPTO_AES_RST | SYSTEM_DMA_RST | SYSTEM_CRYPTO_DS_RST);
|
||||
/* Enable AES and DMA hardware */
|
||||
#if SOC_AES_CRYPTO_DMA
|
||||
periph_module_enable(PERIPH_AES_DMA_MODULE);
|
||||
#elif SOC_AES_GENERAL_DMA
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
periph_module_enable(PERIPH_GDMA_MODULE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function to disable AES and Crypto DMA clocks and release locks */
|
||||
void esp_aes_release_hardware( void )
|
||||
{
|
||||
/* Disable AES hardware */
|
||||
//periph_module_disable(PERIPH_AES_DMA_MODULE);
|
||||
/* Disable AES hardware */
|
||||
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_CRYPTO_AES_RST | SYSTEM_DMA_RST);
|
||||
/* Don't return other units to reset, as this pulls
|
||||
reset on RSA & SHA units, respectively. */
|
||||
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_CRYPTO_AES_CLK_EN | SYSTEM_DMA_CLK_EN);
|
||||
/* Disable AES and DMA hardware */
|
||||
#if SOC_AES_CRYPTO_DMA
|
||||
periph_module_disable(PERIPH_AES_DMA_MODULE);
|
||||
#elif SOC_AES_GENERAL_DMA
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
periph_module_disable(PERIPH_GDMA_MODULE);
|
||||
#endif
|
||||
|
||||
_lock_release(&s_aes_lock);
|
||||
}
|
||||
|
||||
|
||||
/* 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(®_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);
|
||||
AES_RELEASE();
|
||||
}
|
||||
|
||||
|
||||
@ -236,7 +131,7 @@ static inline void esp_aes_get_iv(uint8_t *iv)
|
||||
static IRAM_ATTR void esp_aes_complete_isr(void *arg)
|
||||
{
|
||||
BaseType_t higher_woken;
|
||||
REG_WRITE(AES_INT_CLR_REG, 1);
|
||||
aes_hal_interrupt_clear();
|
||||
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
|
||||
if (higher_woken) {
|
||||
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 )
|
||||
{
|
||||
REG_WRITE(AES_INT_CLR_REG, 1);
|
||||
REG_WRITE(AES_INT_ENA_REG, 1);
|
||||
aes_hal_interrupt_clear();
|
||||
aes_hal_interrupt_enable(true);
|
||||
if (op_complete_sem == NULL) {
|
||||
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 */
|
||||
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 (use_intr) {
|
||||
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
|
||||
@ -297,76 +190,9 @@ static void esp_aes_dma_wait_complete(bool use_intr, lldesc_t *output_desc)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Checking this if interrupt is used also, to avoid
|
||||
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;
|
||||
}
|
||||
}
|
||||
aes_hal_wait_dma_done(output_desc);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
size_t lldesc_num;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/* Set up dma descriptors for input and output */
|
||||
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;
|
||||
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)
|
||||
/* 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
|
||||
#endif
|
||||
{
|
||||
REG_WRITE(AES_INT_ENA_REG, 0);
|
||||
aes_hal_interrupt_enable(false);
|
||||
}
|
||||
|
||||
/* Start AES operation */
|
||||
REG_WRITE(AES_TRIGGER_REG, 1);
|
||||
aes_hal_transform_dma_start(in_desc_head, out_desc_head, blocks);
|
||||
esp_aes_dma_wait_complete(use_intr, out_desc_head);
|
||||
|
||||
|
||||
|
||||
#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||
if (block_bytes > 0) {
|
||||
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
|
||||
|
||||
REG_WRITE(AES_DMA_EXIT_REG, 0);
|
||||
/* Disable DMA mode */
|
||||
REG_WRITE(AES_DMA_ENABLE_REG, 0);
|
||||
aes_hal_transform_dma_finish();
|
||||
|
||||
if (stream_bytes > 0) {
|
||||
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,
|
||||
unsigned char *output )
|
||||
{
|
||||
@ -612,9 +539,9 @@ static int esp_aes_validate_input(esp_aes_context *ctx, const unsigned char *inp
|
||||
/*
|
||||
* AES-ECB single block encryption
|
||||
*/
|
||||
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] )
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -628,17 +555,17 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_ENCRYPT);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void esp_aes_encrypt( esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
void esp_aes_encrypt(esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
esp_internal_aes_encrypt(ctx, input, output);
|
||||
}
|
||||
@ -646,9 +573,9 @@ void esp_aes_encrypt( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-ECB single block decryption
|
||||
*/
|
||||
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] )
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -662,17 +589,17 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void esp_aes_decrypt( esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
void esp_aes_decrypt(esp_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
esp_internal_aes_decrypt(ctx, input, output);
|
||||
}
|
||||
@ -681,10 +608,10 @@ void esp_aes_decrypt( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
int esp_aes_crypt_ecb(esp_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -698,8 +625,8 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
r = esp_aes_process_dma(ctx, input, output, AES_BLOCK_BYTES, NULL);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
@ -709,12 +636,12 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CBC buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_cbc(esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int r = 0;
|
||||
if (esp_aes_validate_input(ctx, input, output)) {
|
||||
@ -739,9 +666,9 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CBC);
|
||||
esp_aes_set_iv(iv);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CBC);
|
||||
aes_hal_set_iv(iv);
|
||||
|
||||
r = esp_aes_process_dma(ctx, input, output, length, NULL);
|
||||
if (r != 0) {
|
||||
@ -749,7 +676,7 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
esp_aes_get_iv(iv);
|
||||
aes_hal_read_iv(iv);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
return r;
|
||||
@ -758,12 +685,12 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CFB8 buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
@ -792,11 +719,11 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
if (block_bytes > 0) {
|
||||
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB8);
|
||||
esp_aes_set_iv(iv);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB8);
|
||||
aes_hal_set_iv(iv);
|
||||
r = esp_aes_process_dma(ctx, input, output, block_bytes, NULL);
|
||||
esp_aes_get_iv(iv);
|
||||
aes_hal_read_iv(iv);
|
||||
|
||||
if (r != 0) {
|
||||
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
|
||||
if (length > 0) {
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, MBEDTLS_AES_ENCRYPT);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, MBEDTLS_AES_ENCRYPT);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_ECB);
|
||||
|
||||
while ( length-- ) {
|
||||
memcpy( ov, iv, 16 );
|
||||
@ -844,13 +771,13 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CFB128 buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
|
||||
{
|
||||
uint8_t c;
|
||||
@ -898,9 +825,9 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
stream_bytes = length % AES_BLOCK_BYTES;
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_CFB128);
|
||||
esp_aes_set_iv(iv);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, mode);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CFB128);
|
||||
aes_hal_set_iv(iv);
|
||||
|
||||
r = esp_aes_process_dma(ctx, input, output, length, iv);
|
||||
if (r != 0) {
|
||||
@ -910,7 +837,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
|
||||
if (stream_bytes == 0) {
|
||||
// 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 {
|
||||
// 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
|
||||
@ -932,12 +859,12 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
||||
* AES-OFB (Output Feedback Mode) buffer encryption/decryption
|
||||
*/
|
||||
|
||||
int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_ofb(esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int r = 0;
|
||||
size_t n;
|
||||
@ -971,9 +898,9 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
ctx->key_in_hardware = 0;
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
|
||||
esp_aes_mode_init(ESP_AES_BLOCK_MODE_OFB);
|
||||
esp_aes_set_iv(iv);
|
||||
ctx->key_in_hardware = aes_hal_setkey(ctx->key, ctx->key_bytes, ESP_AES_DECRYPT);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_OFB);
|
||||
aes_hal_set_iv(iv);
|
||||
|
||||
r = esp_aes_process_dma(ctx, input, output, length, iv);
|
||||
if (r != 0) {
|
||||
@ -981,7 +908,7 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
esp_aes_get_iv(iv);
|
||||
aes_hal_read_iv(iv);
|
||||
esp_aes_release_hardware();
|
||||
}
|
||||
|
||||
@ -993,13 +920,13 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
/*
|
||||
* AES-CTR buffer encryption/decryption
|
||||
*/
|
||||
int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
int esp_aes_crypt_ctr(esp_aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
int r = 0;
|
||||
size_t n;
|
||||
@ -1036,10 +963,10 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
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);
|
||||
esp_aes_set_iv(nonce_counter);
|
||||
aes_hal_mode_init(ESP_AES_BLOCK_MODE_CTR);
|
||||
aes_hal_set_iv(nonce_counter);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
esp_aes_get_iv(nonce_counter);
|
||||
aes_hal_read_iv(nonce_counter);
|
||||
|
||||
esp_aes_release_hardware();
|
||||
|
83
components/mbedtls/port/aes/esp_aes_common.c
Normal file
83
components/mbedtls/port/aes/esp_aes_common.c
Normal 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;
|
||||
}
|
695
components/mbedtls/port/aes/esp_aes_gcm.c
Normal file
695
components/mbedtls/port/aes/esp_aes_gcm.c
Normal 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
|
@ -38,19 +38,7 @@
|
||||
#include <sys/lock.h>
|
||||
#include "mbedtls/aes.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#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
|
||||
#include "aes/esp_aes.h"
|
||||
|
||||
void esp_aes_xts_init( esp_aes_xts_context *ctx )
|
||||
{
|
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
@ -21,31 +21,23 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_AES_H
|
||||
#define ESP_AES_H
|
||||
#pragma once
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "esp32s3/rom/aes.h"
|
||||
#include "hal/aes_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
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
|
||||
*
|
||||
* \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;
|
||||
@ -53,17 +45,20 @@ typedef struct {
|
||||
uint8_t key[32];
|
||||
} esp_aes_context;
|
||||
|
||||
|
||||
/**
|
||||
* \brief The AES XTS context-type definition.
|
||||
*/
|
||||
typedef struct {
|
||||
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
|
||||
*
|
||||
@ -99,7 +94,7 @@ void esp_aes_init( esp_aes_context *ctx );
|
||||
*/
|
||||
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
|
||||
@ -116,16 +111,6 @@ void esp_aes_xts_init( 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)
|
||||
*
|
||||
@ -313,21 +298,26 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
|
||||
* \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 );
|
||||
const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief Internal AES block encryption function
|
||||
* (Only exposed to allow overriding it,
|
||||
* see AES_ENCRYPT_ALT)
|
||||
* \brief This function prepares an XTS context for decryption and
|
||||
* sets the decryption key.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param input Plaintext block
|
||||
* \param output Output (ciphertext) block
|
||||
* \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 );
|
||||
const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
|
||||
/**
|
||||
@ -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] );
|
||||
|
||||
/** 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,
|
||||
@ -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] );
|
||||
|
||||
/** 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 );
|
||||
|
||||
/** 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
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* aes.h */
|
@ -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.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
@ -21,11 +21,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ESP_GCM_H
|
||||
#define ESP_GCM_H
|
||||
#pragma once
|
||||
|
||||
#include "aes.h"
|
||||
#include "aes/esp_aes.h"
|
||||
#include "mbedtls/cipher.h"
|
||||
#include "soc/lldesc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -36,6 +37,7 @@ extern "C" {
|
||||
|
||||
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;
|
||||
@ -59,6 +61,7 @@ typedef struct {
|
||||
esp_aes_gcm_state gcm_state;
|
||||
} esp_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_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,
|
||||
* if \p aad_len is 0.
|
||||
* \param aad_len The length of the additional data. If 0,
|
||||
* \p add is NULL.
|
||||
*
|
||||
* \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_len The length of the IV.
|
||||
* \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 output The buffer for holding the output data.
|
||||
* \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,
|
||||
size_t iv_len,
|
||||
const unsigned char *add,
|
||||
size_t add_len,
|
||||
size_t aad_len,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
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_len The length of the IV.
|
||||
* \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_len The length of the tag.
|
||||
* \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,
|
||||
size_t iv_len,
|
||||
const unsigned char *add,
|
||||
size_t add_len,
|
||||
size_t aad_len,
|
||||
const unsigned char *tag,
|
||||
size_t tag_len,
|
||||
const unsigned char *input,
|
||||
@ -234,5 +237,3 @@ int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* gcm.h */
|
@ -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
|
||||
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
@ -15,26 +18,37 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*
|
||||
* Internal API
|
||||
*/
|
||||
|
||||
#ifndef ESP_CRYPTO_DMA_H
|
||||
#define ESP_CRYPTO_DMA_H
|
||||
#pragma once
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#include "aes/esp_aes.h"
|
||||
#include "aes/esp_aes_gcm.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* crypto_dma.h */
|
@ -28,15 +28,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#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
|
||||
#include "aes/esp_aes.h"
|
||||
|
||||
typedef esp_aes_context mbedtls_aes_context;
|
||||
|
||||
|
@ -24,330 +24,8 @@
|
||||
#ifndef ESP_AES_H
|
||||
#define ESP_AES_H
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "esp32/rom/aes.h"
|
||||
#warning "esp32/aes.h is deprecated, please use aes/esp_aes.h instead"
|
||||
|
||||
#ifdef __cplusplus
|
||||
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
|
||||
#include "aes/esp_aes.h"
|
||||
|
||||
#endif /* aes.h */
|
||||
|
@ -24,346 +24,10 @@
|
||||
#ifndef ESP_AES_H
|
||||
#define ESP_AES_H
|
||||
|
||||
#include "esp_types.h"
|
||||
#include "esp32s2/rom/aes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
//#warning "esp32s2/aes.h is deprecated, please use aes/esp_aes.h instead"
|
||||
|
||||
/* padlock.c and aesni.c rely on these values! */
|
||||
#define ESP_AES_ENCRYPT 1
|
||||
#define ESP_AES_DECRYPT 0
|
||||
#include "aes/esp_aes.h"
|
||||
|
||||
#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 */
|
||||
|
@ -20,220 +20,8 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef ESP_GCM_H
|
||||
#define ESP_GCM_H
|
||||
#warning "esp32s2/gcm.h is deprecated, please use aes/esp_aes_gcm.h instead"
|
||||
|
||||
#include "aes.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 */
|
||||
#include "aes/esp_aes_gcm.h"
|
||||
|
@ -23,18 +23,16 @@
|
||||
#ifndef GCM_ALT_H
|
||||
#define GCM_ALT_H
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_GCM_ALT)
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32s3/gcm.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/gcm.h"
|
||||
#endif
|
||||
#if SOC_AES_SUPPORT_GCM
|
||||
#include "aes/esp_aes_gcm.h"
|
||||
|
||||
|
||||
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_crypt_and_tag esp_aes_gcm_crypt_and_tag
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
#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 // SOC_AES_SUPPORT_GCM
|
||||
|
||||
#endif /* MBEDTLS_GCM_ALT */
|
||||
|
||||
|
@ -335,9 +335,9 @@ TEST_CASE("mbedtls CTR stream test", "[aes]")
|
||||
memset(key, 0x44, 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);
|
||||
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);
|
||||
@ -383,113 +383,6 @@ TEST_CASE("mbedtls CTR stream test", "[aes]")
|
||||
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]")
|
||||
{
|
||||
@ -534,9 +427,9 @@ TEST_CASE("mbedtls OFB stream test", "[aes]")
|
||||
memset(key, 0x44, 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);
|
||||
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);
|
||||
@ -620,9 +513,9 @@ TEST_CASE("mbedtls CFB8 stream test", "[aes]")
|
||||
memset(key, 0x44, 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);
|
||||
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);
|
||||
@ -703,9 +596,9 @@ TEST_CASE("mbedtls CFB128 stream test", "[aes]")
|
||||
memset(key, 0x44, 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);
|
||||
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);
|
||||
@ -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
|
||||
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 *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(plaintext);
|
||||
@ -1392,7 +1285,7 @@ const uint8_t expected_cipher_long_input_end[] = {
|
||||
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;
|
||||
uint8_t nonce[16];
|
||||
@ -1402,9 +1295,8 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
|
||||
memset(nonce, 0x2F, 16);
|
||||
memset(key, 0x1E, 16);
|
||||
|
||||
// allocate internal memory
|
||||
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(decryptedtext);
|
||||
@ -1414,7 +1306,7 @@ void aes_icache_ctr_test(uint32_t output_buf_caps)
|
||||
|
||||
size_t offset;
|
||||
|
||||
// Encrypt with input buffer in external ram
|
||||
// Encrypt with input buffer in external flash
|
||||
offset = 0;
|
||||
memset(nonce, 0x2F, 16);
|
||||
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
|
||||
offset = 0;
|
||||
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);
|
||||
|
||||
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 */
|
||||
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_8BIT | MALLOC_CAP_SPIRAM, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
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_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_one_buf_ctr_test();
|
||||
}
|
||||
|
||||
/* Tests how crypto DMA handles data from iCache */
|
||||
TEST_CASE("mbedtls AES iCache tests", "[aes]")
|
||||
/* Tests how crypto DMA handles data from external flash */
|
||||
TEST_CASE("mbedtls AES external flash tests", "[aes]")
|
||||
{
|
||||
aes_icache_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_8BIT | MALLOC_CAP_SPIRAM);
|
||||
aes_ext_flash_ctr_test(MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
494
components/mbedtls/test/test_aes_gcm.c
Normal file
494
components/mbedtls/test/test_aes_gcm.c
Normal 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
|
@ -25,7 +25,7 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
|
||||
memset(key, 0x44, 16);
|
||||
|
||||
// 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);
|
||||
mbedtls_aes_init(&ctx);
|
||||
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);
|
||||
#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
|
||||
}
|
||||
|
@ -309,35 +309,36 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("custom certificate bundle", "[mbedtls]")
|
||||
{
|
||||
esp_crt_validate_res_t validate_res;
|
||||
esp_crt_validate_res_t validate_res;
|
||||
|
||||
test_case_uses_tcpip();
|
||||
test_case_uses_tcpip();
|
||||
|
||||
xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
|
||||
xSemaphoreHandle exit_sema = xSemaphoreCreateBinary();
|
||||
|
||||
exit_flag = false;
|
||||
xTaskCreate(server_task, "server task", 8192, &exit_sema, 10, NULL);
|
||||
exit_flag = false;
|
||||
xTaskCreate(server_task, "server task", 8192, &exit_sema, 10, NULL);
|
||||
|
||||
// Wait for the server to start up
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
// Wait for the server to start up
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
|
||||
/* Test with default crt bundle that doesnt contain the ca crt */
|
||||
client_task(NULL, &validate_res);
|
||||
TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_FAIL);
|
||||
/* Test with default crt bundle that doesnt contain the ca crt */
|
||||
client_task(NULL, &validate_res);
|
||||
TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_FAIL);
|
||||
|
||||
/* Test with bundle that does contain the CA crt */
|
||||
client_task(server_cert_bundle_start, &validate_res);
|
||||
TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_OK);
|
||||
/* Test with bundle that does contain the CA crt */
|
||||
client_task(server_cert_bundle_start, &validate_res);
|
||||
TEST_ASSERT(validate_res == ESP_CRT_VALIDATE_OK);
|
||||
|
||||
exit_flag = true;
|
||||
exit_flag = true;
|
||||
|
||||
if (!xSemaphoreTake(exit_sema, 10000 / portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sem not released by server task");
|
||||
}
|
||||
if (!xSemaphoreTake(exit_sema, 10000 / portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sem not released by server task");
|
||||
}
|
||||
|
||||
vSemaphoreDelete(exit_sema);
|
||||
vSemaphoreDelete(exit_sema);
|
||||
}
|
||||
|
||||
TEST_CASE("custom certificate bundle - weak hash", "[mbedtls]")
|
||||
|
@ -20,7 +20,7 @@ TEST_CASE("mbedtls SHA performance", "[aes]")
|
||||
unsigned char sha256[32];
|
||||
|
||||
// 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);
|
||||
memset(buf, 0x55, CALL_SZ);
|
||||
|
||||
|
@ -258,6 +258,11 @@
|
||||
#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 ------------------------------- */
|
||||
#define SOC_CAN_SUPPORTED SOC_TWAI_SUPPORTED
|
||||
#define CAN_BRP_MIN SOC_TWAI_BRP_MIN
|
||||
|
@ -44,3 +44,12 @@
|
||||
|
||||
/*-------------------------- TOUCH SENSOR CAPS -------------------------------*/
|
||||
#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)
|
||||
|
@ -276,6 +276,18 @@
|
||||
#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 ------------------------------- */
|
||||
// No contents
|
||||
|
@ -258,10 +258,14 @@
|
||||
#define SOC_DIRAM_DRAM_LOW 0x3FC88000
|
||||
#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_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().
|
||||
#define SOC_BYTE_ACCESSIBLE_LOW 0x3FC88000
|
||||
#define SOC_BYTE_ACCESSIBLE_HIGH 0x3FD00000
|
||||
|
@ -138,9 +138,19 @@
|
||||
#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
|
||||
// Remove them when GDMA driver API is ready
|
||||
#define SOC_GDMA_M2M_DMA_CHANNEL (0)
|
||||
#define SOC_GDMA_SPI2_DMA_CHANNEL (1)
|
||||
#define SOC_GDMA_SPI3_DMA_CHANNEL (2)
|
||||
#define SOC_GDMA_SHA_DMA_CHANNEL (3)
|
||||
#define SOC_GDMA_AES_DMA_CHANNEL (4)
|
||||
|
@ -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)
|
||||
{
|
||||
#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;
|
||||
#else
|
||||
return false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user