refactor(hal): Created esp_hal_security for security code

This commit is contained in:
Aditya Patwardhan
2026-01-30 17:12:49 +05:30
parent aa4034b197
commit 6c2716cd27
219 changed files with 4095 additions and 4071 deletions
@@ -0,0 +1,244 @@
/*
* SPDX-FileCopyrightText: 2023-2024 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 "soc/pcr_struct.h"
#include "esp_hal_security/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)
{
PCR.aes_conf.aes_clk_en = enable;
}
/**
* @brief Reset the AES peripheral module
*/
static inline void aes_ll_reset_register(void)
{
PCR.aes_conf.aes_rst_en = 1;
PCR.aes_conf.aes_rst_en = 0;
// Clear reset on digital signature also, otherwise AES is held in reset
PCR.ds_conf.ds_rst_en = 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_0_REG + 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_0_REG + 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_0_REG + (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 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_MEM);
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_MEM + (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);
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,658 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "soc/apm_defs.h"
#include "soc/tee_reg.h"
#include "soc/lp_tee_reg.h"
#include "soc/hp_apm_reg.h"
#include "soc/hp_apm_struct.h"
#include "soc/lp_apm0_reg.h"
#include "soc/lp_apm0_struct.h"
#include "soc/lp_apm_reg.h"
#include "soc/lp_apm_struct.h"
#include "soc/pcr_reg.h"
#include "soc/interrupts.h"
#include "esp_hal_security/apm_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Helper macros for calculating pms attr field position for given security mode */
#define APM_REGION_PMS_SHIFT(mode) (4U * ((mode) - 1))
#define APM_REGION_PMS_MASK(mode) (0x07U << APM_REGION_PMS_SHIFT(mode))
#define APM_REGION_PMS_FIELD(mode, pms) ((pms) << APM_REGION_PMS_SHIFT(mode))
/**
* @brief Set security mode for a specific master in HP-TEE
*
* @param id Master ID
* @param mode Security mode to set
*/
static inline void apm_ll_hp_tee_set_master_sec_mode(apm_master_id_t id, apm_security_mode_t mode)
{
REG_WRITE(TEE_M0_MODE_CTRL_REG + APM_TEE_MODE_CTRL_OFFSET * id, mode);
}
/**
* @brief Enable/disable clock gating for HP-TEE
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_hp_tee_enable_clk_gating(bool enable)
{
if (enable) {
REG_CLR_BIT(TEE_CLOCK_GATE_REG, TEE_CLK_EN);
} else {
REG_SET_BIT(TEE_CLOCK_GATE_REG, TEE_CLK_EN);
}
}
/**
* @brief Set security mode for a specific master in LP-TEE
*
* @param id Master ID (unused)
* @param mode Security mode to set
*/
static inline void apm_ll_lp_tee_set_master_sec_mode(apm_master_id_t id, apm_security_mode_t mode)
{
(void)id;
REG_WRITE(LP_TEE_M0_MODE_CTRL_REG, mode);
}
/**
* @brief Enable/disable clock gating for LP-TEE
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_tee_enable_clk_gating(bool enable)
{
if (enable) {
REG_CLR_BIT(LP_TEE_CLOCK_GATE_REG, LP_TEE_CLK_EN);
} else {
REG_SET_BIT(LP_TEE_CLOCK_GATE_REG, LP_TEE_CLK_EN);
}
}
/**
* @brief Enable/disable forced HP memory access for LP-TEE
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_tee_enable_force_hp_mem_access(bool enable)
{
if (enable) {
REG_SET_BIT(LP_TEE_FORCE_ACC_HP_REG, LP_TEE_FORCE_ACC_HPMEM_EN);
} else {
REG_CLR_BIT(LP_TEE_FORCE_ACC_HP_REG, LP_TEE_FORCE_ACC_HPMEM_EN);
}
}
/**
* @brief Enable/disable all controller filters in HP-APM
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_hp_apm_enable_ctrl_filter_all(bool enable)
{
REG_WRITE(HP_APM_FUNC_CTRL_REG, enable ? UINT32_MAX : 0);
}
/**
* @brief Enable/disable region filter in HP-APM
*
* @param regn_num Region number
* @param enable True to enable, false to disable
*/
static inline void apm_ll_hp_apm_enable_region_filter(uint32_t regn_num, bool enable)
{
if (enable) {
REG_SET_BIT(HP_APM_REGION_FILTER_EN_REG, BIT(regn_num));
} else {
REG_CLR_BIT(HP_APM_REGION_FILTER_EN_REG, BIT(regn_num));
}
}
/**
* @brief Set region start address in HP-APM
*
* @param regn_num Region number
* @param addr Start address
*/
static inline void apm_ll_hp_apm_set_region_start_addr(uint32_t regn_num, uint32_t addr)
{
REG_WRITE(HP_APM_REGION0_ADDR_START_REG + APM_REGION_ADDR_OFFSET * regn_num, addr);
}
/**
* @brief Set region end address in HP-APM
*
* @param regn_num Region number
* @param addr End address
*/
static inline void apm_ll_hp_apm_set_region_end_addr(uint32_t regn_num, uint32_t addr)
{
REG_WRITE(HP_APM_REGION0_ADDR_END_REG + APM_REGION_ADDR_OFFSET * regn_num, addr);
}
/**
* @brief Set security mode region attributes in HP-APM
*
* @param regn_num Region number
* @param mode Security mode
* @param regn_pms Region PMS attributes
*/
static inline void apm_ll_hp_apm_set_sec_mode_region_attr(uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms)
{
uint32_t reg = HP_APM_REGION0_PMS_ATTR_REG + APM_REGION_PMS_ATTR_OFFSET * regn_num;
uint32_t val = REG_READ(reg);
val &= ~APM_REGION_PMS_MASK(mode);
val |= APM_REGION_PMS_FIELD(mode, regn_pms);
REG_WRITE(reg, val);
}
/**
* @brief Get exception data (regn, master, security mode) from HP-APM
*
* @param path Access path
* @return Exception data
*/
static inline uint32_t apm_ll_hp_apm_get_excp_data(apm_ctrl_access_path_t path)
{
return REG_READ(HP_APM_M0_EXCEPTION_INFO0_REG + APM_EXCP_INFO_OFFSET * path);
}
/**
* @brief Get exception status from HP-APM
*
* @param path Access path
* @return Exception type
*/
static inline uint32_t apm_ll_hp_apm_get_excp_type(apm_ctrl_access_path_t path)
{
return REG_READ(HP_APM_M0_STATUS_REG + APM_EXCP_INFO_OFFSET * path);
}
/**
* @brief Get exception address from HP-APM
*
* @param path Access path
* @return Exception address
*/
static inline uint32_t apm_ll_hp_apm_get_excp_addr(apm_ctrl_access_path_t path)
{
return REG_READ(HP_APM_M0_EXCEPTION_INFO1_REG + APM_EXCP_INFO_OFFSET * path);
}
/**
* @brief Get exception information from HP-APM
*
* @param path Access path
* @param info Pointer to store exception information
*/
static inline void apm_ll_hp_apm_get_excp_info(apm_ctrl_access_path_t path, apm_ctrl_exception_info_t *info)
{
hp_apm_m0_exception_info0_reg_t reg;
reg.val = apm_ll_hp_apm_get_excp_data(path);
info->regn = reg.m0_exception_region;
info->mode = reg.m0_exception_mode;
info->id = reg.m0_exception_id;
info->type = apm_ll_hp_apm_get_excp_type(path);
info->addr = apm_ll_hp_apm_get_excp_addr(path);
}
/**
* @brief Clear controller exception status in HP-APM
*
* @param path Access path
*/
static inline void apm_ll_hp_apm_clear_ctrl_excp_status(apm_ctrl_access_path_t path)
{
REG_SET_BIT(HP_APM_M0_STATUS_CLR_REG + APM_EXCP_INFO_OFFSET * path, APM_EXCP_STATUS_CLR_BIT);
}
/**
* @brief Enable/disable controller interrupt in HP-APM
*
* @param path Access path
* @param enable True to enable, false to disable
*/
static inline void apm_ll_hp_apm_enable_ctrl_intr(apm_ctrl_access_path_t path, bool enable)
{
if (enable) {
REG_SET_BIT(HP_APM_INT_EN_REG, BIT(path));
} else {
REG_CLR_BIT(HP_APM_INT_EN_REG, BIT(path));
}
}
/**
* @brief Get controller interrupt source number from HP-APM
*
* @param path Access path
* @return Interrupt source number
*/
static inline int apm_ll_hp_apm_get_ctrl_intr_src(apm_ctrl_access_path_t path)
{
return ETS_HP_APM_M0_INTR_SOURCE + path;
}
/**
* @brief Enable/disable controller clock gating in HP-APM
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_hp_apm_enable_ctrl_clk_gating(bool enable)
{
if (enable) {
REG_CLR_BIT(HP_APM_CLOCK_GATE_REG, HP_APM_CLK_EN);
} else {
REG_SET_BIT(HP_APM_CLOCK_GATE_REG, HP_APM_CLK_EN);
}
}
/**
* @brief Enable/disable controller filter for specific path in LP-APM0
*
* @param path Access path
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm0_enable_ctrl_filter(apm_ctrl_access_path_t path, bool enable)
{
if (enable) {
REG_SET_BIT(LP_APM0_FUNC_CTRL_REG, BIT(path));
} else {
REG_CLR_BIT(LP_APM0_FUNC_CTRL_REG, BIT(path));
}
}
/**
* @brief Enable/disable all controller filters in LP-APM0
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm0_enable_ctrl_filter_all(bool enable)
{
REG_WRITE(LP_APM0_FUNC_CTRL_REG, enable ? UINT32_MAX : 0);
}
/**
* @brief Enable/disable region filter in LP-APM0
*
* @param regn_num Region number
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm0_enable_region_filter(uint32_t regn_num, bool enable)
{
if (enable) {
REG_SET_BIT(LP_APM0_REGION_FILTER_EN_REG, BIT(regn_num));
} else {
REG_CLR_BIT(LP_APM0_REGION_FILTER_EN_REG, BIT(regn_num));
}
}
/**
* @brief Set region start address in LP-APM0
*
* @param regn_num Region number
* @param addr Start address
*/
static inline void apm_ll_lp_apm0_set_region_start_addr(uint32_t regn_num, uint32_t addr)
{
REG_WRITE(LP_APM0_REGION0_ADDR_START_REG + APM_REGION_ADDR_OFFSET * regn_num, addr);
}
/**
* @brief Set region end address in LP-APM0
*
* @param regn_num Region number
* @param addr End address
*/
static inline void apm_ll_lp_apm0_set_region_end_addr(uint32_t regn_num, uint32_t addr)
{
REG_WRITE(LP_APM0_REGION0_ADDR_END_REG + APM_REGION_ADDR_OFFSET * regn_num, addr);
}
/**
* @brief Set security mode region attributes in LP-APM0
*
* @param regn_num Region number
* @param mode Security mode
* @param regn_pms Region PMS attributes
*/
static inline void apm_ll_lp_apm0_set_sec_mode_region_attr(uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms)
{
uint32_t reg = LP_APM0_REGION0_PMS_ATTR_REG + APM_REGION_PMS_ATTR_OFFSET * regn_num;
uint32_t val = REG_READ(reg);
val &= ~APM_REGION_PMS_MASK(mode);
val |= APM_REGION_PMS_FIELD(mode, regn_pms);
REG_WRITE(reg, val);
}
/**
* @brief Get exception data (regn, master, security mode) from LP-APM0
*
* @param path Access path
* @return Exception data
*/
static inline uint32_t apm_ll_lp_apm0_get_excp_data(apm_ctrl_access_path_t path)
{
(void)path;
return REG_READ(LP_APM0_M0_EXCEPTION_INFO0_REG);
}
/**
* @brief Get exception status from LP-APM0
*
* @param path Access path
* @return Exception type
*/
static inline uint32_t apm_ll_lp_apm0_get_excp_type(apm_ctrl_access_path_t path)
{
(void)path;
return REG_READ(LP_APM0_M0_STATUS_REG);
}
/**
* @brief Get exception address from LP-APM0
*
* @param path Access path
* @return Exception address
*/
static inline uint32_t apm_ll_lp_apm0_get_excp_addr(apm_ctrl_access_path_t path)
{
(void)path;
return REG_READ(LP_APM0_M0_EXCEPTION_INFO1_REG);
}
/**
* @brief Get exception information from LP-APM0
*
* @param path Access path
* @param info Pointer to store exception information
*/
static inline void apm_ll_lp_apm0_get_excp_info(apm_ctrl_access_path_t path, apm_ctrl_exception_info_t *info)
{
lp_apm0_m0_exception_info0_reg_t reg;
reg.val = apm_ll_lp_apm0_get_excp_data(path);
info->regn = reg.m0_exception_region;
info->mode = reg.m0_exception_mode;
info->id = reg.m0_exception_id;
info->type = apm_ll_lp_apm0_get_excp_type(path);
info->addr = apm_ll_lp_apm0_get_excp_addr(path);
}
/**
* @brief Clear controller exception status in LP-APM0
*
* @param path Access path
*/
static inline void apm_ll_lp_apm0_clear_ctrl_excp_status(apm_ctrl_access_path_t path)
{
(void)path;
REG_SET_BIT(LP_APM0_M0_STATUS_CLR_REG, APM_EXCP_STATUS_CLR_BIT);
}
/**
* @brief Enable/disable controller interrupt in LP-APM0
*
* @param path Access path
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm0_enable_ctrl_intr(apm_ctrl_access_path_t path, bool enable)
{
if (enable) {
REG_SET_BIT(LP_APM0_INT_EN_REG, BIT(path));
} else {
REG_CLR_BIT(LP_APM0_INT_EN_REG, BIT(path));
}
}
/**
* @brief Get controller interrupt source number from LP-APM0
*
* @param path Access path
* @return Interrupt source number
*/
static inline int apm_ll_lp_apm0_get_ctrl_intr_src(apm_ctrl_access_path_t path)
{
(void)path;
return ETS_LP_APM0_INTR_SOURCE;
}
/**
* @brief Enable/disable controller clock gating in LP-APM0
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm0_enable_ctrl_clk_gating(bool enable)
{
if (enable) {
REG_CLR_BIT(LP_APM0_CLOCK_GATE_REG, LP_APM0_CLK_EN);
} else {
REG_SET_BIT(LP_APM0_CLOCK_GATE_REG, LP_APM0_CLK_EN);
}
}
/**
* @brief Enable/disable controller filter for specific path in HP-APM
*
* @param path Access path
* @param enable True to enable, false to disable
*/
static inline void apm_ll_hp_apm_enable_ctrl_filter(apm_ctrl_access_path_t path, bool enable)
{
if (enable) {
REG_SET_BIT(HP_APM_FUNC_CTRL_REG, BIT(path));
} else {
REG_CLR_BIT(HP_APM_FUNC_CTRL_REG, BIT(path));
}
}
/**
* @brief Enable/disable controller filter for specific path in LP-APM
*
* @param path Access path
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm_enable_ctrl_filter(apm_ctrl_access_path_t path, bool enable)
{
if (enable) {
REG_SET_BIT(LP_APM_FUNC_CTRL_REG, BIT(path));
} else {
REG_CLR_BIT(LP_APM_FUNC_CTRL_REG, BIT(path));
}
}
/**
* @brief Enable/disable all controller filters in LP-APM
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm_enable_ctrl_filter_all(bool enable)
{
REG_WRITE(LP_APM_FUNC_CTRL_REG, enable ? UINT32_MAX : 0);
}
/**
* @brief Enable/disable region filter in LP-APM
*
* @param regn_num Region number
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm_enable_region_filter(uint32_t regn_num, bool enable)
{
if (enable) {
REG_SET_BIT(LP_APM_REGION_FILTER_EN_REG, BIT(regn_num));
} else {
REG_CLR_BIT(LP_APM_REGION_FILTER_EN_REG, BIT(regn_num));
}
}
/**
* @brief Set region start address in LP-APM
*
* @param regn_num Region number
* @param addr Start address
*/
static inline void apm_ll_lp_apm_set_region_start_addr(uint32_t regn_num, uint32_t addr)
{
REG_WRITE(LP_APM_REGION0_ADDR_START_REG + APM_REGION_ADDR_OFFSET * regn_num, addr);
}
/**
* @brief Set region end address in LP-APM
*
* @param regn_num Region number
* @param addr End address
*/
static inline void apm_ll_lp_apm_set_region_end_addr(uint32_t regn_num, uint32_t addr)
{
REG_WRITE(LP_APM_REGION0_ADDR_END_REG + APM_REGION_ADDR_OFFSET * regn_num, addr);
}
/**
* @brief Set security mode region attributes in LP-APM
*
* @param regn_num Region number
* @param mode Security mode
* @param regn_pms Region PMS attributes
*/
static inline void apm_ll_lp_apm_set_sec_mode_region_attr(uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms)
{
uint32_t reg = LP_APM_REGION0_PMS_ATTR_REG + APM_REGION_PMS_ATTR_OFFSET * regn_num;
uint32_t val = REG_READ(reg);
val &= ~APM_REGION_PMS_MASK(mode);
val |= APM_REGION_PMS_FIELD(mode, regn_pms);
REG_WRITE(reg, val);
}
/**
* @brief Get exception data (regn, master, security mode) from LP-APM
*
* @param path Access path
* @return Exception data
*/
static inline uint32_t apm_ll_lp_apm_get_excp_data(apm_ctrl_access_path_t path)
{
return REG_READ(LP_APM_M0_EXCEPTION_INFO0_REG + APM_EXCP_INFO_OFFSET * path);
}
/**
* @brief Get exception status from LP-APM
*
* @param path Access path
* @return Exception type
*/
static inline uint32_t apm_ll_lp_apm_get_excp_type(apm_ctrl_access_path_t path)
{
return REG_READ(LP_APM_M0_STATUS_REG + APM_EXCP_INFO_OFFSET * path);
}
/**
* @brief Get exception address from LP-APM
*
* @param path Access path
* @return Exception address
*/
static inline uint32_t apm_ll_lp_apm_get_excp_addr(apm_ctrl_access_path_t path)
{
return REG_READ(LP_APM_M0_EXCEPTION_INFO1_REG + APM_EXCP_INFO_OFFSET * path);
}
/**
* @brief Get exception information from LP-APM
*
* @param path Access path
* @param info Pointer to store exception information
*/
static inline void apm_ll_lp_apm_get_excp_info(apm_ctrl_access_path_t path, apm_ctrl_exception_info_t *info)
{
lp_apm_m0_exception_info0_reg_t reg;
reg.val = apm_ll_lp_apm_get_excp_data(path);
info->regn = reg.m0_exception_region;
info->mode = reg.m0_exception_mode;
info->id = reg.m0_exception_id;
info->type = apm_ll_lp_apm_get_excp_type(path);
info->addr = apm_ll_lp_apm_get_excp_addr(path);
}
/**
* @brief Clear controller exception status in LP-APM
*
* @param path Access path
*/
static inline void apm_ll_lp_apm_clear_ctrl_excp_status(apm_ctrl_access_path_t path)
{
REG_SET_BIT(LP_APM_M0_STATUS_CLR_REG + APM_EXCP_INFO_OFFSET * path, APM_EXCP_STATUS_CLR_BIT);
}
/**
* @brief Enable/disable controller interrupt in LP-APM
*
* @param path Access path
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm_enable_ctrl_intr(apm_ctrl_access_path_t path, bool enable)
{
if (enable) {
REG_SET_BIT(LP_APM_INT_EN_REG, BIT(path));
} else {
REG_CLR_BIT(LP_APM_INT_EN_REG, BIT(path));
}
}
/**
* @brief Enable/disable controller clock gating in LP-APM
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_lp_apm_enable_ctrl_clk_gating(bool enable)
{
if (enable) {
REG_CLR_BIT(LP_APM_CLOCK_GATE_REG, LP_APM_CLK_EN);
} else {
REG_SET_BIT(LP_APM_CLOCK_GATE_REG, LP_APM_CLK_EN);
}
}
/**
* @brief Get controller interrupt source number from LP-APM
*
* @param path Access path
* @return Interrupt source number
*/
static inline int apm_ll_lp_apm_get_ctrl_intr_src(apm_ctrl_access_path_t path)
{
return ETS_LP_APM_M0_INTR_SOURCE + path;
}
/**
* @brief Enable/disable APM reset event bypass
*
* @param enable True to enable, false to disable
*/
static inline void apm_ll_enable_reset_event_bypass(bool enable)
{
if (enable) {
REG_SET_BIT(PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_APM);
} else {
REG_CLR_BIT(PCR_RESET_EVENT_BYPASS_REG, PCR_RESET_EVENT_BYPASS_APM);
}
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,194 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use it in application code.
******************************************************************************/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "soc/hwcrypto_reg.h"
#include "soc/soc_caps.h"
#include "soc/pcr_struct.h"
#include "esp_hal_security/ds_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the bus clock for Digital Signature peripheral module
*
* @param true to enable the module, false to disable the module
*/
static inline void ds_ll_enable_bus_clock(bool enable)
{
PCR.ds_conf.ds_clk_en = enable;
}
/**
* @brief Reset the Digital Signature peripheral module
*/
static inline void ds_ll_reset_register(void)
{
PCR.ds_conf.ds_rst_en = 1;
PCR.ds_conf.ds_rst_en = 0;
}
static inline void ds_ll_start(void)
{
REG_WRITE(DS_SET_START_REG, 1);
}
/**
* @brief Wait until DS peripheral has finished any outstanding operation.
*/
static inline bool ds_ll_busy(void)
{
return (REG_READ(DS_QUERY_BUSY_REG) > 0) ? true : false;
}
/**
* @brief Busy wait until the hardware is ready.
*/
static inline void ds_ll_wait_busy(void)
{
while (ds_ll_busy());
}
/**
* @brief In case of a key error, check what caused it.
*/
static inline ds_key_check_t ds_ll_key_error_source(void)
{
uint32_t key_error = REG_READ(DS_QUERY_KEY_WRONG_REG);
if (key_error == 0) {
return DS_NO_KEY_INPUT;
} else {
return DS_OTHER_WRONG;
}
}
/**
* @brief Write the initialization vector to the corresponding register field.
*/
static inline void ds_ll_configure_iv(const uint32_t *iv)
{
for (size_t i = 0; i < (SOC_DS_KEY_PARAM_MD_IV_LENGTH / sizeof(uint32_t)); i++) {
REG_WRITE(DS_IV_MEM + (i * 4), iv[i]);
}
}
/**
* @brief Write the message which should be signed.
*
* @param msg Pointer to the message.
* @param size Length of msg in bytes. It is the RSA signature length in bytes.
*/
static inline void ds_ll_write_message(const uint8_t *msg, size_t size)
{
memcpy((uint8_t*) DS_X_MEM, msg, size);
// Fence ensures all memory operations are completed before proceeding further
asm volatile("fence");
}
/**
* @brief Write the encrypted private key parameters.
*/
static inline void ds_ll_write_private_key_params(const uint8_t *encrypted_key_params)
{
/* Note: as the internal peripheral still has RSA 4096 structure,
but C is encrypted based on the actual max RSA length (ETS_DS_MAX_BITS), need to fragment it
when copying to hardware...
(note if ETS_DS_MAX_BITS == 4096, this should be the same as copying data->c to hardware in one fragment)
*/
typedef struct {
uint32_t addr;
size_t len;
} frag_t;
const frag_t frags[] = {
{DS_Y_MEM, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8},
{DS_M_MEM, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8},
{DS_RB_MEM, SOC_DS_SIGNATURE_MAX_BIT_LEN / 8},
{DS_BOX_MEM, DS_IV_MEM - DS_BOX_MEM},
};
const size_t NUM_FRAGS = sizeof(frags) / sizeof(frag_t);
const uint8_t *from = encrypted_key_params;
for (int i = 0; i < NUM_FRAGS; i++) {
memcpy((uint8_t *)frags[i].addr, from, frags[i].len);
// Fence ensures all memory operations are completed before proceeding further
asm volatile("fence");
from += frags[i].len;
}
}
/**
* @brief Begin signing procedure.
*/
static inline void ds_ll_start_sign(void)
{
REG_WRITE(DS_SET_CONTINUE_REG, 1);
}
/**
* @brief check the calculated signature.
*
* @return
* - DS_SIGNATURE_OK if no issue is detected with the signature.
* - DS_SIGNATURE_PADDING_FAIL if the padding of the private key parameters is wrong.
* - DS_SIGNATURE_MD_FAIL if the message digest check failed. This means that the message digest calculated using
* the private key parameters fails, i.e., the integrity of the private key parameters is not protected.
* - DS_SIGNATURE_PADDING_AND_MD_FAIL if both padding and message digest check fail.
*/
static inline ds_signature_check_t ds_ll_check_signature(void)
{
uint32_t result = REG_READ(DS_QUERY_CHECK_REG);
switch (result) {
case 0:
return DS_SIGNATURE_OK;
case 1:
return DS_SIGNATURE_MD_FAIL;
case 2:
return DS_SIGNATURE_PADDING_FAIL;
default:
return DS_SIGNATURE_PADDING_AND_MD_FAIL;
}
}
/**
* @brief Read the signature from the hardware.
*
* @param result The signature result.
* @param size Length of signature result in bytes. It is the RSA signature length in bytes.
*/
static inline void ds_ll_read_result(uint8_t *result, size_t size)
{
memcpy(result, (uint8_t*) DS_Z_MEM, size);
// Fence ensures all memory operations are completed before proceeding further
asm volatile("fence");
}
/**
* @brief Exit the signature operation.
*
* @note This does not deactivate the module. Corresponding clock/reset bits have to be triggered for deactivation.
*/
static inline void ds_ll_finish(void)
{
REG_WRITE(DS_SET_FINISH_REG, 1);
ds_ll_wait_busy();
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,184 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <string.h>
#include "hal/assert.h"
#include "esp_hal_security/ecc_types.h"
#include "soc/ecc_mult_reg.h"
#include "soc/pcr_struct.h"
#include "soc/pcr_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ECC_PARAM_PX = 0x0,
ECC_PARAM_PY,
ECC_PARAM_K,
} ecc_ll_param_t;
/**
* @brief Enable the bus clock for ECC peripheral module
*
* @param true to enable the module, false to disable the module
*/
static inline void ecc_ll_enable_bus_clock(bool enable)
{
PCR.ecc_conf.ecc_clk_en = enable;
}
/**
* @brief Reset the ECC peripheral module
*/
static inline void ecc_ll_reset_register(void)
{
PCR.ecc_conf.ecc_rst_en = 1;
PCR.ecc_conf.ecc_rst_en = 0;
}
static inline void ecc_ll_power_up(void)
{
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PD);
}
static inline void ecc_ll_power_down(void)
{
REG_CLR_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_FORCE_PU);
REG_SET_BIT(PCR_ECC_PD_CTRL_REG, PCR_ECC_MEM_PD);
}
static inline void ecc_ll_enable_interrupt(void)
{
REG_SET_FIELD(ECC_MULT_INT_ENA_REG, ECC_MULT_CALC_DONE_INT_ENA, 1);
}
static inline void ecc_ll_disable_interrupt(void)
{
REG_SET_FIELD(ECC_MULT_INT_ENA_REG, ECC_MULT_CALC_DONE_INT_ENA, 0);
}
static inline void ecc_ll_clear_interrupt(void)
{
REG_SET_FIELD(ECC_MULT_INT_CLR_REG, ECC_MULT_CALC_DONE_INT_CLR, 1);
}
static inline void ecc_ll_set_mode(ecc_mode_t mode)
{
switch (mode) {
case ECC_MODE_POINT_MUL:
REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 0);
break;
case ECC_MODE_VERIFY:
REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 2);
break;
case ECC_MODE_VERIFY_THEN_POINT_MUL:
REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 3);
break;
default:
HAL_ASSERT(false && "Unsupported mode");
break;
}
}
static inline void ecc_ll_set_curve(ecc_curve_t curve)
{
switch (curve) {
case ECC_CURVE_SECP256R1:
REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH);
break;
case ECC_CURVE_SECP192R1:
REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH);
break;
default:
HAL_ASSERT(false && "Unsupported curve");
return;
}
}
static inline void ecc_ll_write_param(ecc_ll_param_t param, const uint8_t *buf, uint16_t len)
{
uint32_t reg;
uint32_t word;
switch (param) {
case ECC_PARAM_PX:
reg = ECC_MULT_PX_MEM;
break;
case ECC_PARAM_PY:
reg = ECC_MULT_PY_MEM;
break;
case ECC_PARAM_K:
reg = ECC_MULT_K_MEM;
break;
default:
HAL_ASSERT(false && "Invalid parameter");
return;
}
for (int i = 0; i < len; i += 4) {
memcpy(&word, buf + i, 4);
REG_WRITE(reg + i, word);
}
}
static inline void ecc_ll_start_calc(void)
{
REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_START);
}
static inline int ecc_ll_is_calc_finished(void)
{
return REG_GET_FIELD(ECC_MULT_INT_RAW_REG, ECC_MULT_CALC_DONE_INT_RAW);
}
static inline ecc_mode_t ecc_ll_get_mode(void)
{
return (ecc_mode_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE));
}
static inline int ecc_ll_get_verification_result(void)
{
return REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_VERIFICATION_RESULT);
}
static inline ecc_curve_t ecc_ll_get_curve(void)
{
return (ecc_curve_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH));
}
static inline void ecc_ll_read_param(ecc_ll_param_t param, uint8_t *buf, uint16_t len)
{
uint32_t reg;
switch (param) {
case ECC_PARAM_PX:
reg = ECC_MULT_PX_MEM;
break;
case ECC_PARAM_PY:
reg = ECC_MULT_PY_MEM;
break;
case ECC_PARAM_K:
reg = ECC_MULT_K_MEM;
break;
default:
HAL_ASSERT(false && "Invalid parameter");
return;
}
memcpy(buf, (void *)reg, len);
}
static inline void ecc_ll_enable_constant_time_point_mul(bool enable)
{
// Not supported for ESP32-C6
(void) enable; //unused
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,212 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use it in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#include <string.h>
#include <stdbool.h>
#include "soc/system_reg.h"
#include "soc/hwcrypto_reg.h"
#include "soc/pcr_struct.h"
#include "esp_hal_security/hmac_types.h"
#define SHA256_BLOCK_SZ 64
#define SHA256_DIGEST_SZ 32
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG 6
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE 7
#define EFUSE_KEY_PURPOSE_HMAC_UP 8
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL 5
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the bus clock for HMAC peripheral module
*
* @param true to enable the module, false to disable the module
*/
static inline void hmac_ll_enable_bus_clock(bool enable)
{
PCR.hmac_conf.hmac_clk_en = enable;
}
/**
* @brief Reset the HMAC peripheral module
*/
static inline void hmac_ll_reset_register(void)
{
PCR.hmac_conf.hmac_rst_en = 1;
PCR.hmac_conf.hmac_rst_en = 0;
}
/**
* Makes the peripheral ready for use, after enabling it.
*/
static inline void hmac_ll_start(void)
{
REG_WRITE(HMAC_SET_START_REG, 1);
}
/**
* @brief Determine where the HMAC output should go.
*
* The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver
* the output directly to another peripheral instead, e.g. the Digital Signature peripheral.
*/
static inline void hmac_ll_config_output(hmac_hal_output_t config)
{
switch (config) {
case HMAC_OUTPUT_USER:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_UP);
break;
case HMAC_OUTPUT_DS:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
break;
case HMAC_OUTPUT_JTAG_ENABLE:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
break;
case HMAC_OUTPUT_ALL:
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL);
break;
default:
; // do nothing, error will be indicated by hmac_hal_config_error()
}
}
/**
* @brief Selects which hardware key should be used.
*/
static inline void hmac_ll_config_hw_key_id(uint32_t key_id)
{
REG_WRITE(HMAC_SET_PARA_KEY_REG, key_id);
}
/**
* @brief Apply and check configuration.
*
* Afterwards, the configuration can be checked for errors with hmac_hal_config_error().
*/
static inline void hmac_ll_config_finish(void)
{
REG_WRITE(HMAC_SET_PARA_FINISH_REG, 1);
}
/**
*
* @brief Query HMAC error state after configuration actions.
*
* @return
* - 1 or greater on error
* - 0 on success
*/
static inline uint32_t hmac_ll_config_error(void)
{
return REG_READ(HMAC_QUERY_ERROR_REG);
}
/**
* Wait until the HAL is ready for the next interaction.
*/
static inline void hmac_ll_wait_idle(void)
{
uint32_t query;
do {
query = REG_READ(HMAC_QUERY_BUSY_REG);
} while (query != 0);
}
/**
* @brief Write a message block of 512 bits to the HMAC peripheral.
*/
static inline void hmac_ll_write_block_512(const uint32_t *block)
{
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < SHA256_BLOCK_SZ / REG_WIDTH; i++) {
REG_WRITE(HMAC_WR_MESSAGE_MEM + (i * REG_WIDTH), block[i]);
}
REG_WRITE(HMAC_SET_MESSAGE_ONE_REG, 1);
}
/**
* @brief Read the 256 bit HMAC.
*/
static inline void hmac_ll_read_result_256(uint32_t *result)
{
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < SHA256_DIGEST_SZ / REG_WIDTH; i++) {
result[i] = REG_READ(HMAC_RD_RESULT_MEM + (i * REG_WIDTH));
}
}
/**
* @brief Clean the HMAC result provided to other hardware.
*/
static inline void hmac_ll_clean(void)
{
REG_WRITE(HMAC_SET_INVALIDATE_DS_REG, 1);
REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
}
/**
* @brief Signals that the following block will be the padded last block.
*/
static inline void hmac_ll_msg_padding(void)
{
REG_WRITE(HMAC_SET_MESSAGE_PAD_REG, 1);
}
/**
* @brief Signals that all blocks have been written and a padding block will automatically be applied by hardware.
*
* Only applies if the message length is a multiple of 512 bits.
* See the chip TRM HMAC chapter for more details.
*/
static inline void hmac_ll_msg_end(void)
{
REG_WRITE(HMAC_SET_MESSAGE_END_REG, 1);
}
/**
* @brief The message including padding fits into one block, so no further action needs to be taken.
*
* This is called after the one-block-message has been written.
*/
static inline void hmac_ll_msg_one_block(void)
{
REG_WRITE(HMAC_ONE_BLOCK_REG, 1);
}
/**
* @brief Indicate that more blocks will be written after the last block.
*/
static inline void hmac_ll_msg_continue(void)
{
REG_WRITE(HMAC_SET_MESSAGE_ING_REG, 1);
}
/**
* @brief Clear the HMAC result.
*
* Use this after reading the HMAC result or if aborting after any of the other steps above.
*/
static inline void hmac_ll_calc_finish(void)
{
REG_WRITE(HMAC_SET_RESULT_FINISH_REG, 2);
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,182 @@
/*
* SPDX-FileCopyrightText: 2023-2024 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 "esp_hal_security/mpi_types.h"
#include "soc/pcr_reg.h"
#include "soc/pcr_struct.h"
#include "soc/rsa_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)
{
PCR.rsa_conf.rsa_clk_en = enable;
}
/**
* @brief Reset the MPI peripheral module
*/
static inline void mpi_ll_reset_register(void)
{
PCR.rsa_conf.rsa_rst_en = 1;
PCR.rsa_conf.rsa_rst_en = 0;
// Clear reset on digital signature also, otherwise RSA is held in reset
PCR.ds_conf.ds_rst_en = 0;
}
static inline size_t mpi_ll_calculate_hardware_words(size_t words)
{
return words;
}
static inline void mpi_ll_power_up(void)
{
/* Power up the MPI peripheral */
REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_FORCE_PD);
}
static inline void mpi_ll_power_down(void)
{
/* Power down the MPI peripheral */
REG_CLR_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_FORCE_PU);
REG_SET_BIT(PCR_RSA_PD_CTRL_REG, PCR_RSA_MEM_PD);
}
static inline void mpi_ll_enable_interrupt(void)
{
REG_WRITE(RSA_INT_ENA_REG, 1);
}
static inline void mpi_ll_disable_interrupt(void)
{
REG_WRITE(RSA_INT_ENA_REG, 0);
}
static inline void mpi_ll_clear_interrupt(void)
{
REG_WRITE(RSA_INT_CLR_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_IDLE_REG) == 0;
}
/* Copy MPI bignum (p) to hardware memory block at 'mem_base' of mpi_param_t 'param'.
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_PRIME_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 */
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < num_words; i++) {
p[i] = REG_READ(mem_base + (i * REG_WIDTH));
}
/* 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_MODE_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_ENABLE_REG, 0);
}
static inline void mpi_ll_enable_search(void)
{
REG_WRITE(RSA_SEARCH_ENABLE_REG, 1);
}
static inline void mpi_ll_set_search_position(size_t pos)
{
REG_WRITE(RSA_SEARCH_POS_REG, pos);
}
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,175 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include "soc/hwcrypto_reg.h"
#include "soc/pcr_struct.h"
#include "esp_hal_security/sha_types.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)
{
PCR.sha_conf.sha_clk_en = enable;
}
/**
* @brief Reset the SHA peripheral module
*/
static inline void sha_ll_reset_register(void)
{
PCR.sha_conf.sha_rst_en = 1;
PCR.sha_conf.sha_rst_en = 0;
// Clear reset on digital signature and hmac also, otherwise SHA is held in reset
PCR.ds_conf.ds_rst_en = 0;
PCR.hmac_conf.hmac_rst_en = 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 ESP32C6
*
* @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_DMA_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 *data_words = (uint32_t *)input_text;
uint32_t *reg_addr_buf = (uint32_t *)(SHA_M_MEM);
for (int i = 0; i < block_word_len; i++) {
REG_WRITE(&reg_addr_buf[i], data_words[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;
const size_t REG_WIDTH = sizeof(uint32_t);
for (size_t i = 0; i < digest_word_len; i++) {
digest_state_words[i] = REG_READ(SHA_H_MEM + (i * REG_WIDTH));
}
}
/**
* @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_MEM);
for (int i = 0; i < digest_word_len; i++) {
REG_WRITE(&reg_addr_buf[i], digest_state_words[i]);
}
}
#ifdef __cplusplus
}
#endif