refactor(hal): Created esp_hal_security for security code

This commit is contained in:
Aditya Patwardhan
2026-01-21 09:59:46 +05:30
parent 469ead652b
commit 5ee7af3afd
220 changed files with 4098 additions and 3766 deletions
-352
View File
@@ -1,352 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <string.h>
#include "soc/dport_reg.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 Enable the bus clock for AES peripheral module
*
* @param enable true to enable the module, false to disable the module
*/
static inline void aes_ll_enable_bus_clock(bool enable)
{
if (enable) {
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_AES_CLK_EN);
} else {
CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_AES_CLK_EN);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define aes_ll_enable_bus_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
aes_ll_enable_bus_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Reset the AES peripheral module
*/
static inline void aes_ll_reset_register(void)
{
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_AES_RST);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_AES_RST);
// Clear reset on digital signature and crypto DMA also, otherwise AES is held in reset
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_DS_RST);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define aes_ll_reset_register(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
aes_ll_reset_register(__VA_ARGS__); \
} while(0)
/**
* @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;
/* Memcpy to avoid potential unaligned access */
uint32_t key_word;
for (int i = 0; i < key_word_len; i++) {
memcpy(&key_word, key + 4 * i, 4);
REG_WRITE(AES_KEY_BASE + i * 4, key_word);
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)
{
uint32_t input_word;
for (int i = 0; i < AES_BLOCK_WORDS; i++) {
memcpy(&input_word, (uint8_t*)input + 4 * i, 4);
REG_WRITE(AES_TEXT_IN_BASE + i * 4, input_word);
}
}
/**
* @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_word;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
output_word = REG_READ(AES_TEXT_OUT_BASE + (i * REG_WIDTH));
/* Memcpy to avoid potential unaligned access */
memcpy( (uint8_t*)output + i * 4, &output_word, sizeof(output_word));
}
}
/**
* @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 (esp_aes_state_t)REG_READ(AES_STATE_REG);
}
/**
* @brief Set mode of operation
*
* @note Only used for DMA transforms
*
* @param mode Mode of operation to set (e.g., ECB, CBC, CTR, etc.)
*/
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 *reg_addr_buf = (uint32_t *)(AES_IV_BASE);
uint32_t iv_word;
for (int i = 0; i < IV_WORDS; i++ ) {
/* Memcpy to avoid potential unaligned access */
memcpy(&iv_word, iv + 4 * i, sizeof(iv_word));
REG_WRITE(&reg_addr_buf[i], iv_word);
}
}
/*
* Read IV from hardware iv registers
*/
static inline void aes_ll_read_iv(uint8_t *iv)
{
uint32_t iv_word;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < IV_WORDS; i++) {
iv_word = REG_READ(AES_IV_BASE + (i * REG_WIDTH));
/* Memcpy to avoid potential unaligned access */
memcpy(iv + i * 4, &iv_word, sizeof(iv_word));
}
}
/**
* @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_CLEAR_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)
{
const size_t REG_WIDTH = sizeof(uint32_t);
uint32_t hash_word;
for (size_t i = 0; i < AES_BLOCK_WORDS; i++) {
hash_word = REG_READ(AES_H_BASE + (i * REG_WIDTH));
/* Memcpy to avoid potential unaligned access */
memcpy(gcm_hash + i * 4, &hash_word, sizeof(hash_word));
}
}
/**
* @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 *reg_addr_buf = (uint32_t *)(AES_J_BASE);
uint32_t j0_word;
for (int i = 0; i < AES_BLOCK_WORDS; i++ ) {
/* Memcpy to avoid potential unaligned access */
memcpy(&j0_word, j0 + 4 * i, sizeof(j0_word));
REG_WRITE(&reg_addr_buf[i], j0_word);
}
}
/**
* @brief Sets the number of effective bits of incomplete blocks in plaintext/ciphertext.
*
* @note Only affects AES-GCM
*
* @param num_valid_bits the number of effective bits of incomplete blocks in plaintext/ciphertext.
*/
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_word;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < TAG_WORDS; i++) {
tag_word = REG_READ(AES_T_BASE + (i * REG_WIDTH));
/* Memcpy to avoid potential unaligned access */
memcpy(tag + i * 4, &tag_word, sizeof(tag_word));
}
}
#ifdef __cplusplus
}
#endif
@@ -1,133 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "soc/hwcrypto_reg.h"
#include "soc/crypto_dma_reg.h"
#include "soc/dport_reg.h"
typedef enum {
CRYPTO_DMA_AES= 0,
CRYPTO_DMA_SHA,
} crypto_dma_mode_t;
/**
* @brief Enable the bus clock for crypto DMA peripheral module
*
* @param enable true to enable the module, false to disable the module
*/
static inline void crypto_dma_ll_enable_bus_clock(bool enable)
{
if (enable) {
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_DMA_CLK_EN);
} else {
CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_DMA_CLK_EN);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define crypto_dma_ll_enable_bus_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
crypto_dma_ll_enable_bus_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Reset the crypto DMA peripheral module
*/
static inline void crypto_dma_ll_reset_register(void)
{
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_DMA_RST);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_DMA_RST);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define crypto_dma_ll_reset_register(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
crypto_dma_ll_reset_register(__VA_ARGS__); \
} while(0)
/**
* @brief Resets the DMA
*
*/
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
*
* @param mode Mode to use, AES or SHA
*/
static inline void crypto_dma_ll_set_mode(crypto_dma_mode_t mode)
{
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, mode);
}
/**
* @brief Sets up the outlink for a transfer
*
* @param outlink_addr Address of the outlink buffer
*/
static inline void crypto_dma_ll_outlink_set(uint32_t outlink_addr)
{
CLEAR_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_ADDR);
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, outlink_addr & OUT_LINK_REG_OUTLINK_ADDR);
}
/**
* @brief Sets up the inlink for a transfer
*
* @param inlink_addr Address of the inlink buffer
*/
static inline void crypto_dma_ll_inlink_set(uint32_t inlink_addr)
{
CLEAR_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, IN_LINK_REG_INLINK_ADDR);
SET_PERI_REG_MASK(CRYPTO_DMA_IN_LINK_REG, inlink_addr & IN_LINK_REG_INLINK_ADDR);
}
/**
* @brief Starts the outlink
*
*/
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
}
#endif
-194
View File
@@ -1,194 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <string.h>
#include <sys/param.h>
#include "hal/assert.h"
#include "hal/mpi_types.h"
#include "soc/hwcrypto_periph.h"
#include "soc/dport_reg.h"
#include "soc/mpi_periph.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the bus clock for MPI peripheral module
*
* @param enable true to enable the module, false to disable the module
*/
static inline void mpi_ll_enable_bus_clock(bool enable)
{
if (enable) {
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_RSA_CLK_EN);
} else {
CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_RSA_CLK_EN);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define mpi_ll_enable_bus_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
mpi_ll_enable_bus_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Reset the MPI peripheral module
*/
static inline void mpi_ll_reset_register(void)
{
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_RSA_RST);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_RSA_RST);
// Clear reset on digital signature also, otherwise RSA is held in reset
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_DS_RST);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define mpi_ll_reset_register(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
mpi_ll_reset_register(__VA_ARGS__); \
} while(0)
static inline size_t mpi_ll_calculate_hardware_words(size_t words)
{
return words;
}
static inline void mpi_ll_power_up(void)
{
REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_MEM_PD);
}
static inline void mpi_ll_power_down(void)
{
REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
}
static inline void mpi_ll_enable_interrupt(void)
{
REG_WRITE(RSA_INTERRUPT_REG, 1);
}
static inline void mpi_ll_disable_interrupt(void)
{
REG_WRITE(RSA_INTERRUPT_REG, 0);
}
static inline void mpi_ll_clear_interrupt(void)
{
REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
}
static inline bool mpi_ll_check_memory_init_complete(void)
{
return REG_READ(RSA_QUERY_CLEAN_REG) == 0;
}
static inline void mpi_ll_start_op(mpi_op_t op)
{
REG_WRITE(MPI_OPERATIONS_REG[op], 1);
}
static inline bool mpi_ll_get_int_status(void)
{
return REG_READ(RSA_QUERY_INTERRUPT_REG) == 0;
}
/* Copy MPI bignum (p) to hardware memory block at 'mem_base'.
If num_words is higher than the number of words (n) in the bignum then
these additional words will be zeroed in the memory buffer.
*/
static inline void mpi_ll_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words)
{
uint32_t mem_base = MPI_BLOCK_BASES[param] + offset;
uint32_t* pbase = (uint32_t*) mem_base;
uint32_t copy_words = MIN(num_words, n);
/* Copy MPI data to memory block registers */
for (int i = 0; i < copy_words; i++) {
pbase[i] = p[i];
}
/* Zero any remaining memory block data */
for (int i = copy_words; i < num_words; i++) {
pbase[i] = 0;
}
}
static inline void mpi_ll_write_m_prime(uint32_t Mprime)
{
REG_WRITE(RSA_M_DASH_REG, Mprime);
}
static inline void mpi_ll_write_rinv(uint32_t rinv)
{
REG_WRITE(MPI_BLOCK_BASES[MPI_PARAM_Z], rinv);
}
static inline void mpi_ll_write_at_offset(mpi_param_t param, int offset, uint32_t value)
{
uint32_t mem_base = MPI_BLOCK_BASES[param] + offset;
REG_WRITE(mem_base, value);
}
/* Read MPI bignum (p) back from hardware memory block.
Reads z_words words from block.
*/
static inline void mpi_ll_read_from_mem_block(uint32_t* p, size_t n, size_t num_words)
{
uint32_t mem_base = MPI_BLOCK_BASES[MPI_PARAM_Z];
/* Copy data from memory block registers */
esp_dport_access_read_buffer(p, mem_base, num_words);
/* Zero any remaining limbs in the bignum, if the buffer is bigger
than num_words */
for (size_t i = num_words; i < n; i++) {
p[i] = 0;
}
}
static inline void mpi_ll_set_mode(size_t length)
{
REG_WRITE(RSA_LENGTH_REG, length);
}
static inline void mpi_ll_disable_constant_time(void)
{
REG_WRITE(RSA_CONSTANT_TIME_REG, 0);
}
static inline void mpi_ll_enable_constant_time(void)
{
REG_WRITE(RSA_CONSTANT_TIME_REG, 1);
}
static inline void mpi_ll_disable_search(void)
{
REG_WRITE(RSA_SEARCH_OPEN_REG, 0);
}
static inline void mpi_ll_enable_search(void)
{
REG_WRITE(RSA_SEARCH_OPEN_REG, 1);
}
static inline void mpi_ll_set_search_position(size_t pos)
{
REG_WRITE(RSA_SEARCH_POS_REG, pos);
}
#ifdef __cplusplus
}
#endif
@@ -1,54 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "soc/soc_caps.h"
#include "xt_instr_macros.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline uint32_t mpu_ll_id_to_addr(unsigned id)
{
// vpn - id
// 0x00000000 = 0
// 0x20000000 = 1
// 0x40000000 = 2
// 0x60000000 = 3
// 0x80000000 = 4
// 0xa0000000 = 5
// 0xc0000000 = 6
// 0xe0000000 = 7
return id * SOC_MPU_MIN_REGION_SIZE;
}
static inline void mpu_ll_set_region_rw(uint32_t addr)
{
WDTLB(0x0, addr); // cached, no allocate
}
static inline void mpu_ll_set_region_rwx(uint32_t addr)
{
WDTLB(0x2, addr); // bypass cache
}
static inline void mpu_ll_set_region_x(uint32_t addr)
{
WITLB(0x3, addr); // cached
}
static inline void mpu_ll_set_region_illegal(uint32_t addr)
{
WITLB(0xF, addr);
WDTLB(0xF, addr);
}
#ifdef __cplusplus
}
#endif
-228
View File
@@ -1,228 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <string.h>
#include "soc/hwcrypto_reg.h"
#include "hal/sha_types.h"
#include "soc/dport_reg.h"
#include "hal/mmu_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the bus clock for SHA peripheral module
*
* @param enable true to enable the module, false to disable the module
*/
static inline void sha_ll_enable_bus_clock(bool enable)
{
if (enable) {
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_SHA_CLK_EN);
} else {
CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_SHA_CLK_EN);
}
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define sha_ll_enable_bus_clock(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
sha_ll_enable_bus_clock(__VA_ARGS__); \
} while(0)
/**
* @brief Reset the SHA peripheral module
*/
static inline void sha_ll_reset_register(void)
{
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST);
// Clear reset on digital signature and hmac also, otherwise SHA is held in reset
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_DS_RST);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_HMAC_RST);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define sha_ll_reset_register(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
sha_ll_reset_register(__VA_ARGS__); \
} while(0)
/**
* @brief Load the mode for the SHA engine
*
* @param sha_type The SHA algorithm type
*/
static inline void sha_ll_set_mode(esp_sha_type sha_type)
{
REG_WRITE(SHA_MODE_REG, sha_type);
}
/**
* @brief Start a new SHA block conversions (no initial hash in HW)
*
* @param sha_type The SHA algorithm type
*/
static inline void sha_ll_start_block(esp_sha_type sha_type)
{
(void) sha_type;
REG_WRITE(SHA_START_REG, 1);
}
/**
* @brief Continue a SHA block conversion (initial hash in HW)
*
* @param sha_type The SHA algorithm type
*/
static inline void sha_ll_continue_block(esp_sha_type sha_type)
{
(void) sha_type;
REG_WRITE(SHA_CONTINUE_REG, 1);
}
/**
* @brief Start a new SHA message conversion using DMA (no initial hash in HW)
*/
static inline void sha_ll_start_dma(void)
{
REG_WRITE(SHA_DMA_START_REG, 1);
}
/**
* @brief Continue a SHA message conversion using DMA (initial hash in HW)
*/
static inline void sha_ll_continue_dma(void)
{
REG_WRITE(SHA_DMA_CONTINUE_REG, 1);
}
/**
* @brief Load the current hash digest to digest register
*
* @note Happens automatically on ESP32S2
*
* @param sha_type The SHA algorithm type
*/
static inline void sha_ll_load(esp_sha_type sha_type)
{
}
/**
* @brief Sets the number of message blocks to be hashed
*
* @note DMA operation only
*
* @param num_blocks Number of message blocks to process
*/
static inline void sha_ll_set_block_num(size_t num_blocks)
{
REG_WRITE(SHA_BLOCK_NUM_REG, num_blocks);
}
/**
* @brief Checks if the SHA engine is currently busy hashing a block
*
* @return true SHA engine busy
* @return false SHA engine idle
*/
static inline bool sha_ll_busy(void)
{
return REG_READ(SHA_BUSY_REG);
}
/**
* @brief Write a text (message) block to the SHA engine
*
* @param input_text Input buffer to be written to the SHA engine
* @param block_word_len Number of words in block
*/
static inline void sha_ll_fill_text_block(const void *input_text, size_t block_word_len)
{
uint32_t input_word;
uint8_t *data_bytes = (uint8_t *)input_text;
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
bool force_word_aligned_access = false;
/* In case of ESP32-S2, the DPORT bus region is word-aligned memory
* and does not support 8-bit accesses.
* Thus, when accessing data from these addresses we need to ensure
* the operations are word-aligned.
*/
if (mmu_ll_vaddr_in_dport_bus_region((uint32_t)input_text)) {
force_word_aligned_access = true;
}
for (size_t i = 0; i < block_word_len; i++) {
if (force_word_aligned_access) {
memcpy(&input_word, data_bytes + 4 * i, 4);
REG_WRITE(&reg_addr_buf[i], input_word);
} else {
REG_WRITE(&reg_addr_buf[i], *((uint32_t *)data_bytes + i));
}
}
}
/**
* @brief Read the message digest from the SHA engine
*
* @param sha_type The SHA algorithm type
* @param digest_state Buffer that message digest will be written to
* @param digest_word_len Length of the message digest
*/
static inline void sha_ll_read_digest(esp_sha_type sha_type, void *digest_state, size_t digest_word_len)
{
uint32_t *digest_state_words = (uint32_t *)digest_state;
esp_dport_access_read_buffer(digest_state_words, SHA_H_BASE, digest_word_len);
}
/**
* @brief Write the message digest to the SHA engine
*
* @param sha_type The SHA algorithm type
* @param digest_state Message digest to be written to SHA engine
* @param digest_word_len Length of the message digest
*/
static inline void sha_ll_write_digest(esp_sha_type sha_type, void *digest_state, size_t digest_word_len)
{
uint32_t *digest_state_words = (uint32_t *)digest_state;
uint32_t *reg_addr_buf = (uint32_t *)(SHA_H_BASE);
for (size_t i = 0; i < digest_word_len; i++) {
REG_WRITE(&reg_addr_buf[i], digest_state_words[i]);
}
}
/**
* @brief Sets SHA512_t T_string parameter
*
* @param t_string T_string parameter
*/
static inline void sha_ll_t_string_set(uint32_t t_string)
{
REG_WRITE(SHA_T_STRING_REG, t_string);
}
/**
* @brief Sets SHA512_t T_string parameter's length
*
* @param t_len T_string parameter length
*/
static inline void sha_ll_t_len_set(uint8_t t_len)
{
REG_WRITE(SHA_T_LENGTH_REG, t_len);
}
#ifdef __cplusplus
}
#endif