refactor(hal): Created esp_hal_security for security code

This commit is contained in:
Aditya Patwardhan
2026-01-05 22:37:29 +05:30
parent 469ead652b
commit 5ee7af3afd
220 changed files with 4098 additions and 3766 deletions

View File

@@ -0,0 +1,162 @@
/*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* 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 <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "esp_hal_security/aes_types.h"
#if SOC_AES_SUPPORTED
#include "esp_hal_security/aes_ll.h"
#endif
#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);
#ifdef SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION
/**
* @brief Enable the pseudo-round function during AES operations
*
* @param enable true to enable, false to disable
* @param base basic number of pseudo rounds, zero if disable
* @param increment increment number of pseudo rounds, zero if disable
* @param key_rng_cnt update frequency of the pseudo-key, zero if disable
*/
void aes_hal_enable_pseudo_rounds(bool enable, uint8_t base, uint8_t increment, uint8_t key_rng_cnt);
#endif /* SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION */
#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 AES operation is done
*
* @param output pointer to inlink descriptor
*/
void aes_hal_wait_done(void);
/**
* @brief Starts an already configured AES DMA transform
*
* @param num_blocks Number of blocks to transform
*/
void aes_hal_transform_dma_start(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/ciphertext
*/
void aes_hal_gcm_init(size_t aad_num_blocks, size_t num_valid_bit);
/**
* @brief Starts a AES-GCM transform
*
* @param num_blocks Number of blocks to transform
*/
void aes_hal_transform_dma_gcm_start(size_t num_blocks);
/**
* @brief Sets the J0 value, for more information see the GCM subchapter in the TRM
*
* @note Only affects AES-GCM
*
* @param j0 J0 value
*/
#define aes_hal_gcm_set_j0(j0) aes_ll_gcm_set_j0(j0)
/**
* @brief Read the tag after a AES-GCM transform
*
* @param tag Pointer to where to store the result
* @param tag_length number of bytes to read into tag
*/
void aes_hal_gcm_read_tag(uint8_t *tag, size_t tag_len);
#endif //SOC_AES_SUPPORT_GCM
#endif //SOC_AES_SUPPORT_DMA
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* 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)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,390 @@
/*
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include "esp_err.h"
#include "soc/soc_caps.h"
#if SOC_APM_SUPPORTED
#include "esp_hal_security/apm_ll.h"
#include "esp_hal_security/apm_types.h"
#if SOC_IS(ESP32P4)
/**
* @brief DMA configurable region configuration data.
*/
typedef struct {
apm_ll_dma_master_t dma_master; /* DMA master whose access permission to be configured.*/
uint32_t pms_r_mask; /* Read permission mask. */
uint32_t pms_w_mask; /* Write permission mask. */
} apm_hal_dma_region_config_data_t;
/**
* @brief Configure HP peripherals access permission for the HP CPU0/1.
*
* @param master_id HP CPU0/1
* @param hp_peri HP peripheral whose access permission to be configured.
* @param enable Permission enable/disable
*/
void apm_hal_hp_peri_access_enable(apm_ll_master_id_t master_id, apm_ll_hp_peri_t hp_peri,
apm_ll_secure_mode_t sec_mode, bool enable);
/**
* @brief Configure LP peripherals access permission for the LP CPU.
*
* @param lp_peri LP peripheral whose access permission to be configured.
* @param enable Permission enable/disable
*/
void apm_hal_lp_peri_access_enable(apm_ll_lp_peri_t lp_peri, bool enable);
/**
* @brief Configure peripherals configurable address ranges.
*
* @param regn_num Configurable address range number.
* @param regn_low_addr Configurable address range start address.
* @param regn_high_addr Configurable address range end address.
*/
void apm_hal_peri_region_config(uint32_t regn_num, uint32_t regn_low_addr,
uint32_t regn_high_addr);
/**
* @brief Configure peripherals configurable address ranges.
*
* @param master_id LP CPU and HP CPU0/1
* @param sec_mode CPU privilege mode (Machine/User) which corresponds to (TEE/REE).
* @param regn_num Configurable address range number.
* @param regn_pms Configurable address range permission setting(2-bits field).
* Bit 0: Region 0 permission enable/disable.
* Bit 1: Region 1 permission enable/disable.
* @return Configuration performed successfully?
*/
int apm_hal_peri_region_pms(apm_ll_master_id_t master_id, apm_ll_secure_mode_t sec_mode,
uint32_t regn_num, uint32_t regn_pms);
/**
* @brief Configure APM controller clock gating.
*
* @param apm_ctrl APM controller (LP_PERI/HP_PERI/HP_DMA/LP2HP_PERI/HP2LP_PERI).
* @param enable Permission enable/disable.
* enable: Enable automatic clock gating.
* disable: Keep the clock always on.
* @return Clock gating set successfully?
*/
int apm_hal_apm_ctrl_clk_gating_enable(apm_ll_apm_ctrl_t apm_ctrl, bool enable);
/**
* @brief Configure DMA configurable address range low address.
*
* @param regn_num Configurable DMA address range number.
* @param regn_low_addr Configurable DMA address range start address.
* @param regn_high_addr Configurable DMA address range end address.
*/
void apm_hal_dma_region_config(uint32_t regn_num, uint32_t regn_low_addr, uint32_t regn_high_addr);
/**
* @brief Configure DMA configurable address range read permission.
*
* @param pms_data DMA configurable region configuration data.
* @param dma_master DMA master whose access permission to be configured.
* @param regn_mask 32-bits field, each bit for corresponding DMA configurable address range permission.
* 0: Disable read permission.
* 1: Enable read permission.
*/
void apm_hal_dma_region_pms(apm_hal_dma_region_config_data_t *pms_data);
#else
/**
* @brief Helper macro to create a region entry configuration
*
*/
#define APM_HAL_REGION_ENTRY_BASE(PATH,NUM, START, END, PMS) \
.path_id = (PATH), \
.regn_num = (NUM), \
.regn_start_addr = ((START) & ~0x03U), \
.regn_end_addr = (((END) - 1U) & ~0x03U), \
.regn_pms = (PMS), \
.filter_en = true
#if SOC_APM_SUPPORT_CTRL_CFG_LOCK
#define APM_HAL_REGION_ENTRY(PATH, NUM, START, END, PMS, LOCK) \
{ APM_HAL_REGION_ENTRY_BASE(PATH, NUM, START, END, PMS), .lock_en = LOCK }
#else
#define APM_HAL_REGION_ENTRY(PATH, NUM, START, END, PMS) \
{ APM_HAL_REGION_ENTRY_BASE(PATH, NUM, START, END, PMS) }
#endif
/**
* @brief Helper macro to create a security mode configuration
*
*/
#define APM_HAL_SEC_MODE_CFG(CTRL_MOD, MODE, REGNS) \
{ \
.ctrl_mod = (CTRL_MOD), \
.mode = (MODE), \
.regn_count = sizeof(REGNS) / sizeof((REGNS)[0]), \
.regions = (REGNS), \
}
/**
* @brief APM controller info structure
*/
typedef struct {
apm_ctrl_module_t ctrl_mod; /*!< APM controller module */
apm_ctrl_access_path_t path; /*!< Access path */
} apm_hal_ctrl_info_t;
/**
* @brief APM region configuration structure
*/
typedef struct {
apm_ctrl_access_path_t path_id; /*!< Path identifier */
uint32_t regn_num; /*!< Region number */
uint32_t regn_start_addr; /*!< Region start address */
uint32_t regn_end_addr; /*!< Region end address */
uint32_t regn_pms; /*!< Region permissions */
bool filter_en; /*!< Filter enable flag */
#if SOC_APM_SUPPORT_CTRL_CFG_LOCK
bool lock_en; /*!< Lock enable flag */
#endif
} apm_hal_ctrl_region_cfg_t;
/**
* @brief APM security mode configuration structure
*/
typedef struct {
apm_ctrl_module_t ctrl_mod; /*!< APM controller module */
apm_security_mode_t mode; /*!< Security mode */
uint32_t regn_count; /*!< Number of regions */
apm_hal_ctrl_region_cfg_t *regions; /*!< Array of region configurations */
} apm_hal_ctrl_sec_mode_cfg_t;
/**
* @brief Set security mode for specified masters
*
* @param master_mask Mask of masters to configure
* @param mode Security mode to set
*/
void apm_hal_set_master_sec_mode(uint32_t master_mask, apm_security_mode_t mode);
/**
* @brief Set security mode for all masters
*
* @param mode Security mode to set
*/
void apm_hal_set_master_sec_mode_all(apm_security_mode_t mode);
#if SOC_APM_SUPPORT_CTRL_CFG_LOCK
/**
* @brief Lock security mode for specified masters
*
* @param master_mask Mask of masters to configure
*/
void apm_hal_lock_master_sec_mode(uint32_t master_mask);
/**
* @brief Lock security mode for all masters
*
*/
void apm_hal_lock_master_sec_mode_all(void);
#endif
#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL
/**
* @brief Set access permissions for the specified peripherals in the given TEE ctrl module
*
* @param ctrl_mod TEE ctrl module
* @param periph_mask Peripheral mask
* @param mode Security mode
* @param pms Access permissions
*/
void apm_hal_tee_set_peri_access(apm_tee_ctrl_module_t ctrl_mod, uint64_t periph_mask, apm_security_mode_t mode, apm_perm_t pms);
/**
* @brief Set access permissions for all peripherals in the given TEE ctrl module
*
* @param ctrl_mod TEE ctrl module
* @param mode Security mode
* @param pms Access permissions
*/
void apm_hal_tee_set_peri_access_all(apm_tee_ctrl_module_t ctrl_mod, apm_security_mode_t mode, apm_perm_t pms);
#endif
/**
* @brief Enable/disable TEE clock gating for a APM controller module
*
* @param ctrl_mod TEE controller module
* @param enable True to enable, false to disable
*/
void apm_hal_tee_enable_clk_gating(apm_tee_ctrl_module_t ctrl_mod, bool enable);
/**
* @brief Enable/disable controller filter for specific path
*
* @param ctrl_mod APM controller module
* @param path Access path
* @param enable True to enable, false to disable
*/
void apm_hal_enable_ctrl_filter(apm_ctrl_module_t ctrl_mod, apm_ctrl_access_path_t path, bool enable);
/**
* @brief Enable/disable all controller filters
*
* @param enable True to enable, false to disable
*/
void apm_hal_enable_ctrl_filter_all(bool enable);
/**
* @brief Enable/disable region filter
*
* @param ctrl_mod APM controller module
* @param regn_num Region number
* @param enable True to enable, false to disable
*/
void apm_hal_enable_region_filter(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, bool enable);
/**
* @brief Set the start address for the given region
*
* @param ctrl_mod APM controller module
* @param regn_num Region number
* @param addr Address
*/
void apm_hal_set_region_start_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t addr);
/**
* @brief Set the end address for the given region
*
* @param ctrl_mod APM controller module
* @param regn_num Region number
* @param addr Address
*/
void apm_hal_set_region_end_addr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, uint32_t addr);
/**
* @brief Set the permissions for the specified security mode for the given region
*
* @param ctrl_mod APM controller module
* @param regn_num Region number
* @param mode Security mode
*/
void apm_hal_set_sec_mode_region_attr(apm_ctrl_module_t ctrl_mod, uint32_t regn_num, apm_security_mode_t mode, uint32_t regn_pms);
/**
* @brief Set region filter configuration
*
* @param ctrl_mod APM controller module
* @param mode Security mode
* @param regn_cfg Region configuration
*/
void apm_hal_set_region_filter_cfg(apm_ctrl_module_t ctrl_mod, apm_security_mode_t mode, const apm_hal_ctrl_region_cfg_t *regn_cfg);
#if SOC_APM_SUPPORT_CTRL_CFG_LOCK
/**
* @brief Lock region filter configuration
*
* @param ctrl_mod APM controller module
* @param regn_num Region number
*/
void apm_hal_lock_region_filter_cfg(apm_ctrl_module_t ctrl_mod, uint32_t regn_num);
#endif
/**
* @brief Set controller security mode configuration
*
* @param cfg Security mode configuration
*/
void apm_hal_set_ctrl_sec_mode_cfg(const apm_hal_ctrl_sec_mode_cfg_t *cfg);
/**
* @brief Get exception type
*
* @param ctrl_info Controller information
* @return Exception type
*/
uint32_t apm_hal_get_exception_type(apm_hal_ctrl_info_t *ctrl_info);
/**
* @brief Clear exception status
*
* @param ctrl_info Controller information
*/
void apm_hal_clear_exception_status(apm_hal_ctrl_info_t *ctrl_info);
/**
* @brief Get exception information
*
* @param ctrl_info Controller information
* @param excp_info Exception information structure to fill
*/
void apm_hal_get_exception_info(apm_hal_ctrl_info_t *ctrl_info, apm_ctrl_exception_info_t *excp_info);
/**
* @brief Enable/disable interrupt
*
* @param ctrl_info Controller information
* @param enable True to enable, false to disable
*/
void apm_hal_enable_intr(apm_hal_ctrl_info_t *ctrl_info, bool enable);
/**
* @brief Get interrupt source number
*
* @param ctrl_info Controller information
* @return Interrupt source number
*/
int apm_hal_get_intr_src_num(apm_hal_ctrl_info_t *ctrl_info);
/**
* @brief Enable/disable reset event bypass
*
* @param enable True to enable, false to disable
*/
void apm_hal_enable_reset_event_bypass(bool enable);
/**
* @brief Enable/disable controller clock gating
*
* @param ctrl_mod APM controller module
* @param enable True to enable, false to disable
*/
void apm_hal_enable_ctrl_clk_gating(apm_ctrl_module_t ctrl_mod, bool enable);
#endif //SOC_IS(ESP32P4)
#elif SOC_APM_CTRL_FILTER_SUPPORTED //!SOCKconfig_APM_SUPPORTED
#if SOC_IS(ESP32H4)
#include "soc/hp_apm_reg.h"
#define apm_hal_enable_ctrl_filter_all(en) \
REG_WRITE(HP_APM_FUNC_CTRL_REG, en ? 0xFFFFFFFF : 0);
#elif SOC_IS(ESP32S31)
#include "soc/hp_apm_reg.h"
#include "soc/hp_mem_apm_reg.h"
#define apm_hal_enable_ctrl_filter_all(en) \
REG_WRITE(HP_APM_FUNC_CTRL_REG, en ? 0xFFFFFFFF : 0); \
REG_WRITE(HP_MEM_APM_FUNC_CTRL_REG, en ? 0xFFFFFFFF : 0);
#else
#include "soc/hp_apm_reg.h"
#include "soc/lp_apm_reg.h"
#include "soc/lp_apm0_reg.h"
#define apm_hal_enable_ctrl_filter_all(en) \
REG_WRITE(LP_APM_FUNC_CTRL_REG, en ? 0xFFFFFFFF : 0); \
REG_WRITE(LP_APM0_FUNC_CTRL_REG, en ? 0xFFFFFFFF : 0); \
REG_WRITE(HP_APM_FUNC_CTRL_REG, en ? 0xFFFFFFFF : 0);
#endif
#endif //SOC_APM_CTRL_FILTER_SUPPORTED
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,122 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Master IDs for APM
*/
typedef enum {
APM_MASTER_HPCORE = 0, /*!< HP CPU */
#if SOC_LP_CORE_SUPPORTED
APM_MASTER_LPCORE = 1, /*!< LP CPU */
#endif /* SOC_LP_CORE_SUPPORTED */
APM_MASTER_REGDMA = 2,
#if SOC_SDIO_SLAVE_SUPPORTED
APM_MASTER_SDIOSLV = 3, /*!< SDIO slave */
#endif /* SOC_SDIO_SLAVE_SUPPORTED */
APM_MASTER_MODEM = 4, /*!< Modem */
APM_MASTER_MEM_MON = 5, /*!< Memory monitor */
APM_MASTER_TRACE = 6, /*!< Trace */
#if SOC_SPIRAM_SUPPORTED
APM_MASTER_PSRAM_MEM_MON = 8, /*!< PSRAM memory monitor */
#endif /* SOC_SPIRAM_SUPPORTED */
#if SOC_GPSPI_SUPPORTED && SOC_AHB_GDMA_VERSION == 1
APM_MASTER_GDMA_GPSPI = 16, /*!< GDMA for GPSPI/SPI2 */
#elif SOC_GPSPI_SUPPORTED && SOC_AHB_GDMA_VERSION == 2
APM_MASTER_GDMA_GPSPI = 17,
#endif /* SOC_GPSPI_SUPPORTED */
#if SOC_UHCI_SUPPORTED
APM_MASTER_GDMA_UHCI = 18, /*!< GDMA for UHCI */
#endif /* SOC_UHCI_SUPPORTED */
APM_MASTER_GDMA_I2S = 19, /*!< GDMA for I2S */
#if SOC_AES_SUPPORTED
APM_MASTER_GDMA_AES = 22, /*!< GDMA for AES */
#endif /* SOC_AES_SUPPORTED */
APM_MASTER_GDMA_SHA = 23, /*!< GDMA for SHA */
APM_MASTER_GDMA_ADC = 24, /*!< GDMA for ADC */
#if SOC_PARLIO_SUPPORTED
APM_MASTER_GDMA_PARLIO = 25, /*!< GDMA for PARLIO */
#endif /* SOC_PARLIO_SUPPORTED */
APM_MASTER_MAX = 32, /*!< Maximum master ID */
} apm_master_id_t;
/**
* @brief APM controller modules
*/
typedef enum {
APM_CTRL_HP_APM = 0, /*!< High-performance APM controller */
#if SOC_APM_LP_APM0_SUPPORTED
APM_CTRL_LP_APM0, /*!< Low-power APM0 controller */
#endif
APM_CTRL_LP_APM, /*!< Low-power APM controller */
#if SOC_APM_CPU_APM_SUPPORTED
APM_CTRL_CPU_APM, /*!< CPU APM controller */
#endif
} apm_ctrl_module_t;
/**
* @brief TEE controller modules
*/
typedef enum {
APM_TEE_CTRL_HP = 0, /*!< High-performance TEE controller */
#if SOC_APM_SUPPORT_LP_TEE_CTRL
APM_TEE_CTRL_LP = 1, /*!< Low-power TEE controller */
#endif
} apm_tee_ctrl_module_t;
/**
* @brief APM controller access paths
*/
typedef enum {
APM_CTRL_ACCESS_PATH_M0 = 0, /*!< Access path M0 */
APM_CTRL_ACCESS_PATH_M1 = 1, /*!< Access path M1 */
APM_CTRL_ACCESS_PATH_M2 = 2, /*!< Access path M2 */
APM_CTRL_ACCESS_PATH_M3 = 3, /*!< Access path M3 */
APM_CTRL_ACCESS_PATH_M4 = 4, /*!< Access path M4 */
} apm_ctrl_access_path_t;
/**
* @brief Security modes for APM
*/
typedef enum {
APM_SEC_MODE_TEE = 0, /*!< Trusted Execution Environment mode */
APM_SEC_MODE_REE0 = 1, /*!< Rich Execution Environment mode 0 */
APM_SEC_MODE_REE1 = 2, /*!< Rich Execution Environment mode 1 */
APM_SEC_MODE_REE2 = 3, /*!< Rich Execution Environment mode 2 */
} apm_security_mode_t;
/**
* @brief Access permission flags
*/
typedef enum {
APM_PERM_NONE = 0, /*!< No permissions */
APM_PERM_X = 1, /*!< Execute */
APM_PERM_W = 2, /*!< Write */
APM_PERM_R = 4, /*!< Read */
APM_PERM_ALL = 7, /*!< All access */
} apm_perm_t;
/**
* @brief APM controller exception info structure
*/
typedef struct {
uint32_t regn; /*!< Region number */
uint32_t mode; /*!< Security mode */
uint32_t id; /*!< Master ID */
uint32_t type; /*!< Exception type */
uint32_t addr; /*!< Exception address */
} apm_ctrl_exception_info_t;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,88 @@
/*
* SPDX-FileCopyrightText: 2020-2025 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 <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "esp_hal_security/ds_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Start the whole signing process after the input key is ready.
*
* Call this before using any of the functions below. The input key is ready must be ready at this point.
*/
void ds_hal_start(void);
/**
* @brief Finish the whole signing process. Call this after the signature is read or in case of an error.
*/
void ds_hal_finish(void);
/**
* @brief Write the initialization vector.
*/
void ds_hal_configure_iv(const uint32_t *iv);
#if SOC_KEY_MANAGER_DS_KEY_DEPLOY
/**
* @brief Set the DS key source.
*/
void ds_hal_set_key_source(ds_key_source_t key_source);
#endif
/**
* @brief Write the message which should be signed.
*
* @param msg Pointer to the message.
* @param size Length of signature result in bytes. It is the RSA signature length in bytes.
*/
void ds_hal_write_message(const uint8_t *msg, size_t size);
/**
* @brief Write the encrypted private key parameters.
*/
void ds_hal_write_private_key_params(const uint8_t *block);
/**
* @brief Begin signing procedure.
*/
void ds_hal_start_sign(void);
/**
* @brief Check whether the hardware is busy with an operation.
*
* @return True if the hardware has finished the signing procedure, otherwise false.
*/
bool ds_hal_busy(void);
/**
* @brief Check and read the signature from the hardware.
*
* @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.
*/
ds_signature_check_t ds_hal_read_result(uint8_t *result, size_t size);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "soc/soc_caps.h"
/**
* The result when checking whether the key to decrypt the RSA parameters is ready.
*/
typedef enum {
DS_KEY_INPUT_OK = 0, /**< The decryption key is ready. */
DS_NO_KEY_INPUT, /**< Dependent peripheral providing key hasn't been activated. */
DS_OTHER_WRONG, /**< Dependent peripheral running but problem receiving the key. */
} ds_key_check_t;
typedef enum {
DS_SIGNATURE_OK = 0, /**< Signature is valid and can be read. */
DS_SIGNATURE_PADDING_FAIL = 1, /**< Padding invalid, signature can be read if user wants it. */
DS_SIGNATURE_MD_FAIL = 2, /**< Message digest check failed, signature invalid. */
DS_SIGNATURE_PADDING_AND_MD_FAIL = 3, /**< Both padding and MD check failed. */
} ds_signature_check_t;
#if SOC_KEY_MANAGER_DS_KEY_DEPLOY
typedef enum {
DS_KEY_SOURCE_EFUSE = 0,
DS_KEY_SOURCE_KEY_MGR = 1,
} ds_key_source_t;
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,207 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The HAL is not public api, don't use in application code.
* See readme.md in soc/README.md
******************************************************************************/
#pragma once
#include "stdint.h"
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "esp_hal_security/ecc_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Set the work mode of the operation
*
* @param mode Mode of operation
*/
void ecc_hal_set_mode(ecc_mode_t mode);
/**
* @brief Set the ECC curve of operation
*
* @param curve Curve to use for operation
*/
void ecc_hal_set_curve(ecc_curve_t curve);
/**
* @brief Start calculation
*
*/
void ecc_hal_start_calc(void);
/**
* @brief Check whether the calculation has finished
*
* @return - 1 if the hardware has finished calculating
* - 0 otherwise
*/
int ecc_hal_is_calc_finished(void);
/**
* @brief Write parameters for point multiplication (K * (Px, Py))
*
* @param k Scalar value
* @param px X coordinate of the ECC point
* @param py Y coordinate of the ECC point
* @param len Length (in bytes) of the ECC point
* - 32 bytes for SECP256R1
* - 24 bytes for SECP192R1
*/
void ecc_hal_write_mul_param(const uint8_t *k, const uint8_t *px, const uint8_t *py, uint16_t len);
/**
* @brief Write parameters for point verification,
* i.e to check if the point lies on the curve
*
* @param px X coordinate of the ECC point
* @param py Y coordinate of the ECC point
* @param len Length (in bytes) of the ECC point
* - 32 for SECP256R1
* - 24 for SECP192R1
*/
void ecc_hal_write_verify_param(const uint8_t *px, const uint8_t *py, uint16_t len);
/**
* @brief Read point multiplication result
*
* @param rx X coordinate of the multiplication result
* @param ry Y coordinate of the multiplication result
* @param len Length (in bytes) of the ECC point
* - 32 for SECP256R1
* - 24 for SECP192R1
*
* @return - 0 if the operation was successful
* - -1 if the operation was not successful
*
* In case the operation is not successful, rx and ry will contain
* all zeros
*/
int ecc_hal_read_mul_result(uint8_t *rx, uint8_t *ry, uint16_t len);
/**
* @brief Read point verification result
*
* @return - 1 if point lies on curve
* - 0 otherwise
*/
int ecc_hal_read_verify_result(void);
#if SOC_ECC_EXTENDED_MODES_SUPPORTED
/**
* @brief Set the mod base value used in MOD operation
*
* @param base Identifier of the base to use
*/
void ecc_hal_set_mod_base(ecc_mod_base_t base);
/**
* @brief Write parameters for Jacobian verification
* i.e Check whether (Qx, Qy, Qz) is a point on selected curve
*
* @param qx X coordinate of the ECC point in jacobian form
* @param qy Y coordinate of the ECC point in jacobian form
* @param qz Z coordinate of the ECC point in jacobian form
* @param len Length (in bytes) of the ECC point
* - 32 bytes for SECP256R1
* - 24 bytes for SECP192R1
*/
void ecc_hal_write_jacob_verify_param(const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len);
/**
* @brief Read ECC point multiplication result in jacobian form
*
* @param rx X coordinate of the multiplication result
* @param ry Y coordinate of the multiplication result
* @param rz Z coordinate of the multiplication result
* @param len Length (in bytes) of the ECC point
* - 32 for SECP256R1
* - 24 for SECP192R1
*
* @return - 0 if the operation was successful
* - -1 if the operation was not successful
*
* In case the operation is not successful, rx, ry, and rz will contain
* all zeros
*/
int ecc_hal_read_jacob_mul_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_t len);
/**
* @brief Write parameters for ECC point addition ((Px, Py, 1) + (Qx, Qy, Qz))
*
* @param px X coordinate of the 1st addend ECC point
* @param py Y coordinate of the 1st addend ECC point
* @param qx X coordinate of the 2nd addend ECC point in jacobian form
* @param qy Y coordinate of the 2nd addend ECC point in jacobian form
* @param qz Z coordinate of the 2nd addend ECC point in jacobian form
* @param len Length (in bytes) of the ECC point
* - 32 bytes for SECP256R1
* - 24 bytes for SECP192R1
*/
void ecc_hal_write_point_add_param(const uint8_t *px, const uint8_t *py, const uint8_t *qx, const uint8_t *qy, const uint8_t *qz, uint16_t len);
/**
* @brief Read ECC point addition result
*
* @param rx X coordinate of the addition result
* @param ry Y coordinate of the addition result
* @param rz Z coordinate of the addition result
* @param len Length (in bytes) of the ECC point
* - 32 for SECP256R1
* - 24 for SECP192R1
* @param read_jacob Read the result in Jacobian form
*
* @return - 0 if the operation was successful
* - -1 otherwise
*/
int ecc_hal_read_point_add_result(uint8_t *rx, uint8_t *ry, uint8_t *rz, uint16_t len, bool read_jacob);
/**
* @brief Write parameters for mod operations
* i.e mod add, mod sub, mod mul, mod inverse mul (or mod division)
*
* @param a Value of operand 1
* @param b Value of operand 2
* @param len Length (in bytes) of the ECC point
* - 32 bytes for SECP256R1
* - 24 bytes for SECP192R1
*/
void ecc_hal_write_mod_op_param(const uint8_t *a, const uint8_t *b, uint16_t len);
/**
* @brief Read result of mod operations
* i.e mod add, mod sub, mod mul, mod inverse mul (or mod division)
*
* @param r Result of the mod operation
* @param len Length (in bytes) of the ECC point
* - 32 bytes for SECP256R1
* - 24 bytes for SECP192R1
*
* @return - 0 if operation successful
* - -1 otherwise
*/
int ecc_hal_read_mod_op_result(uint8_t *r, uint16_t len);
#endif /* SOC_ECC_EXTENDED_MODES_SUPPORTED */
/**
* @brief Enable constant time multiplication operations
*
* @param true: enable; false: disable
*/
void ecc_hal_enable_constant_time_point_mul(bool enable);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ECC_MODE_POINT_MUL = 0x0, // (Rx, Ry) = K * (Px, Py)
ECC_MODE_INVERSE_MUL, // R = K^(-1) * Py
ECC_MODE_VERIFY, // Check if (Px, Py) are points on the curve
ECC_MODE_VERIFY_THEN_POINT_MUL, // Verify and then perform point multiplication
ECC_MODE_JACOBIAN_POINT_MUL,
ECC_MODE_POINT_ADD,
ECC_MODE_JACOBIAN_POINT_VERIFY,
ECC_MODE_POINT_VERIFY_JACOBIAN_MUL,
ECC_MODE_MOD_ADD,
ECC_MODE_MOD_SUB,
ECC_MODE_MOD_MUL,
} ecc_mode_t;
typedef enum {
ECC_CURVE_SECP192R1 = 0x0,
ECC_CURVE_SECP256R1,
ECC_CURVE_SECP384R1,
ECC_CURVE_SM2,
} ecc_curve_t;
typedef enum {
ECC_MOD_N, // Order of the curve
ECC_MOD_P, // Prime modulus
} ecc_mod_base_t;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,125 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The HAL is not public api, don't use in application code.
* See readme.md in soc/README.md
******************************************************************************/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include "esp_hal_security/ecdsa_types.h"
#include "soc/soc_caps.h"
#include "hal/config.h"
#ifdef __cplusplus
extern "C" {
#endif
#if HAL_CONFIG(ECDSA_GEN_SIG_CM)
#define ECDSA_SIGN_MAX_DUMMY_OP_COUNT 0x7
/* This value defines the maximum dummy operation count for the ECDSA signature countermeasure.
Higher the number, better the countermeasure's effectiveness against attacks.
At the same time higher number leads to slower performance.
After the countermeasure is enabled, hardware ECDSA signature operation
shall take time approximately equal to original time multiplied by this number.
If you observe that the reduced performance is affecting your use-case then you may try reducing this time to the minimum. */
#endif /* HAL_CONFIG_ECDSA_GEN_SIG_CM */
/*
* ECDSA peripheral config structure
*/
typedef struct {
ecdsa_mode_t mode; /* Mode of operation */
ecdsa_curve_t curve; /* Curve to use for operation */
ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */
int efuse_key_blk; /*!< The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h */
bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */
ecdsa_sign_type_t sign_type; /* Type of signature generation */
uint16_t loop_number; /* Determines the loop number value in deterministic derivation algorithm to derive K.
* When using mbedtls APIs, this member of the config does not need any explicit
* initialisation as it is used and handled internally by the port layer (ECDSA_SIGN_ALT).
*/
} ecdsa_hal_config_t;
/**
* @brief Generate ECDSA signature
*
* @param conf Configuration for ECDSA operation, see ``ecdsa_hal_config_t``
* @param hash Hash that is to be signed
* @param r_out Buffer that will contain `R` component of ECDSA signature
* @param s_out Buffer that will contain `S` component of ECDSA signature
* @param len Length of the r_out and s_out buffer (32 bytes for SECP256R1, 24 for SECP192R1)
*/
void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash,
uint8_t *r_out, uint8_t *s_out, uint16_t len);
/**
* @brief Verify given ECDSA signature
*
* @param conf Configuration for ECDSA operation, see ``ecdsa_hal_config_t``
* @param hash Hash that was signed
* @param r `R` component of ECDSA signature
* @param s `S` component of ECDSA signature
* @param pub_x X coordinate of public key
* @param pub_y Y coordinate of public key
* @param len Length of r and s buffer (32 bytes for SECP256R1, 24 for SECP192R1)
*
* @return - 0, if the signature matches
* - -1, if verification fails
*/
int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, const uint8_t *r, const uint8_t *s,
const uint8_t *pub_x, const uint8_t *pub_y, uint16_t len);
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
/**
* @brief Export public key coordinates of an ECDSA private key
*
* @param conf Configuration for ECDSA operation, see ``ecdsa_hal_config_t``
* @param pub_x X coordinate of public key
* @param pub_y Y coordinate of public key
* @param len Length of pub_x and pub_y buffers (32 bytes for SECP256R1, 24 for SECP192R1)
*/
void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *pub_y, uint16_t len);
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
/**
* @brief Check if the ECDSA operation is successful
*
* @return - true, if the ECDSA operation is successful
* - false, if the ECDSA operation fails
*/
bool ecdsa_hal_get_operation_result(void);
#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
/**
* @brief Check if the K value derived by the peripheral during deterministic signature generation is valid
*
* @return true, if the derived K value is valid
* @return false, if the derived K value is invalid
*/
bool ecdsa_hal_det_signature_k_check(void);
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */
/**
* @brief Set the efuse block that should be used as ECDSA private key
*
* @note The efuse block must be burnt with key purpose ECDSA_KEY
*
* @param curve ECDSA curve type
* @param efuse_key_blk If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h
* Each efuse key block number (Must be in [EFUSE_BLK_KEY0...EFUSE_BLK_KEY_MAX - 1] range).
*/
void ecdsa_hal_set_efuse_key(ecdsa_curve_t curve, int efuse_key_blk);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ECDSA peripheral work modes
*/
typedef enum {
ECDSA_MODE_SIGN_VERIFY,
ECDSA_MODE_SIGN_GEN,
ECDSA_MODE_EXPORT_PUBKEY,
} ecdsa_mode_t;
/**
* @brief ECDSA curve options
*/
typedef enum {
ECDSA_CURVE_SECP192R1,
ECDSA_CURVE_SECP256R1,
ECDSA_CURVE_SECP384R1,
ECDSA_CURVE_SM2,
} ecdsa_curve_t;
/**
* @brief Source of SHA message that is to be signed/verified
*/
typedef enum {
ECDSA_Z_USE_SHA_PERI,
ECDSA_Z_USER_PROVIDED,
} ecdsa_sha_mode_t;
/**
* @brief ECDSA signature type
*/
typedef enum {
ECDSA_K_TYPE_TRNG,
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
ECDSA_K_TYPE_DETERMINISITIC,
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
} ecdsa_sign_type_t;
/**
* @brief Macro to combine two key blocks into a single integer
* @note Least significant 4 bits stores block number of the low key block, and the next 4 bits store the high key block number.
*/
#define HAL_ECDSA_COMBINE_KEY_BLOCKS(blk_high, blk_low) (((blk_high) << 4) | (blk_low))
/**
* @brief Macro to extract high and low key block numbers from a combined integer
* @note Extracts high block from bits 4-7 and low block from bits 0-3
*/
#define HAL_ECDSA_EXTRACT_KEY_BLOCKS(combined_blk, blk_high, blk_low) do { \
(blk_high) = ((combined_blk) >> 4) & 0xF; \
(blk_low) = (combined_blk) & 0xF; \
} while(0)
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2020-2022 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 <stdint.h>
#include <stdbool.h>
#include "esp_hal_security/hmac_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Make the peripheral ready for use.
*
* This triggers any further steps necessary after enabling the device
*/
void hmac_hal_start(void);
/**
* @brief Configure which hardware key slot should be used and configure the target of the HMAC output.
*
* @note Writing out-of-range values is undefined behavior. The user has to ensure that the parameters are in range.
*
* @param config The target of the HMAC. Possible targets are described in \c hmac_hal_output_t.
* See the TRM of your target chip for more details.
* @param key_id The ID of the hardware key slot to be used.
*
* @return 0 if the configuration was successful, non-zero if not.
* An unsuccessful configuration means that the purpose value in the eFuse of the corresponding key slot
* doesn't match to supplied value of \c config.
*/
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id);
/**
* @brief Write a padded single-block message of 512 bits to the HMAC peripheral.
*
* The message must not be longer than one block (512 bits) and the padding has to be applied by software before
* writing. The padding has to be able to fit into the block after the message.
* For more information on HMAC padding, see the TRM of your target chip.
*/
void hmac_hal_write_one_block_512(const void *block);
/**
* @brief Write a message block of 512 bits to the HMAC peripheral.
*
* This function must be used incombination with \c hmac_hal_next_block_normal() or \c hmac_hal_next_block_padding().
* The first message block is written without any prerequisite.
* All message blocks which are not the last one, need a call to \c hmac_hal_next_block_normal() before, indicating
* to the hardware that a "normal", i.e. non-padded block will follow. This is even the case for a block which begins
* padding already but where the padding doesn't fit in (remaining message size > (block size - padding size)).
* Before writing the last block which contains the padding, a call to \c hmac_hal_next_block_padding() is necessary
* to indicate to the hardware that a block with padding will be written.
*
* For more information on HMAC padding, see the TRM of your target chip for more details.
*/
void hmac_hal_write_block_512(const void *block);
/**
* @brief Indicate to the hardware that a normal block will be written.
*/
void hmac_hal_next_block_normal(void);
/**
* @brief Indicate to the hardware that a block with padding will be written.
*/
void hmac_hal_next_block_padding(void);
/**
* @brief Read the 256 bit HMAC result from the hardware.
*/
void hmac_hal_read_result_256(void *result);
/**
* @brief Clear (invalidate) the HMAC result provided to other hardware.
*/
void hmac_hal_clean(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,42 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* The possible efuse keys for the HMAC peripheral
*/
typedef enum {
HMAC_KEY0 = 0,
HMAC_KEY1,
HMAC_KEY2,
HMAC_KEY3,
HMAC_KEY4,
HMAC_KEY5,
#if SOC_KEY_MANAGER_HMAC_KEY_DEPLOY
HMAC_KEY_KM = 7,
#endif
HMAC_KEY_MAX = 8,
} hmac_key_id_t;
/**
* 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.
*/
typedef enum {
HMAC_OUTPUT_USER = 0, /**< Let user provide a message and read the HMAC result */
HMAC_OUTPUT_DS = 1, /**< HMAC is provided to the DS peripheral to decrypt DS private key parameters */
HMAC_OUTPUT_JTAG_ENABLE = 2, /**< HMAC is used to enable JTAG after soft-disabling it */
HMAC_OUTPUT_ALL = 3 /**< HMAC is used for both as DS input for or enabling JTAG */
} hmac_hal_output_t;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,64 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for Hardware Unique Key (HUK) Generator
#pragma once
#include "soc/soc_caps.h"
#if SOC_HUK_SUPPORTED
#include "esp_hal_security/huk_types.h"
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* @brief Configure HUK: Generate new HUK information or Recover key from recovery information
* Generation Mode: In this case the Generation mode of the HUK Generator is used. A new HUK is generated and the respective HUK information is copied to the given buffer. This info can be again used to recover the same HUK.
* Recovery Mode: In this case the Recovery mode of the HUK Generator is used. The HUK is recovered from the given HUK information. This is the HUK information generated previously when HUK info was generated with a previous call to huk_hal_configure.
*
* @input
* huk_info_buf(I/O) Pointer to the buffer for the HUK info, size of the given buffer must equal to HUK_INFO_SIZE
* In Generation Mode the buffer shall be populated with the huk_info_buf
* In recovery mode the huk_info stored in the buffer shall be consumed for HUK recovery
*
* @return
* ESP_OK on success
* ESP_FAIL on failure
*/
esp_err_t huk_hal_configure(const esp_huk_mode_t huk_mode, uint8_t *huk_info_buf);
/**
* @brief Read state of Hardware Unique Key Generator
*
* @return esp_huk_state_t
*/
esp_huk_state_t huk_hal_get_state(void);
/**
* @brief Get the HUK generation status: esp_huk_gen_status_t
*/
uint8_t huk_hal_get_risk_level(void);
/**
* @brief Read the HUK date information
*/
uint32_t huk_hal_get_date_info(void);
#if SOC_HUK_MEM_NEEDS_RECHARGE
/**
* @brief Recharge HUK memory
*/
void huk_hal_recharge_huk_memory(void);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#if SOC_KEY_MANAGER_SUPPORTED
#include "esp_assert.h"
#include "rom/km.h"
#include "rom/key_mgr.h"
#ifdef __cplusplus
extern "C" {
#endif
#define HUK_RISK_ALERT_LEVEL 4
/**
* @brief Mode for Hardware Unique Key Process: recovery, generation
*/
typedef enum {
ESP_HUK_MODE_RECOVERY = 0, /* HUK recovery mode */
ESP_HUK_MODE_GENERATION, /* HUK generation mode */
} esp_huk_mode_t;
ESP_STATIC_ASSERT(sizeof(esp_huk_mode_t) == sizeof(huk_mode_t), "Size of esp_huk_mode_t should match huk_mode_t (from ROM)");
/**
* @brief State of Hardware Unique Key Generator: idle, load, gain or busy.
*
*/
typedef enum {
ESP_HUK_STATE_IDLE = 0, /* Key Manager is idle */
ESP_HUK_STATE_LOAD, /* Key Manager is read to receive input */
ESP_HUK_STATE_GAIN, /* Key Manager is ready to provide output */
ESP_HUK_STATE_BUSY /* Key Manager is busy */
} esp_huk_state_t;
/**
* @brief Status of the Hardware Unique Key Generation:
* not generated, generated and valid, generated and invalid
*/
typedef enum {
ESP_HUK_STATUS_NOT_GENERATED = 0, /* HUK is not generated */
ESP_HUK_STATUS_GENERATED_AND_VALID, /* HUK is generated and valid */
ESP_HUK_STATUS_GENERATED_AND_INVALID /* HUK is generated and is invalid */
} esp_huk_gen_status_t;
/**
* @brief
* HUK interrupt types
*/
typedef enum {
ESP_HUK_INT_PREP_DONE = 0x01,
ESP_HUK_INT_PROC_DONE,
ESP_HUK_INT_POST_DONE,
} esp_huk_interrupt_type_t;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,141 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for Key Manager
#pragma once
#include "soc/soc_caps.h"
#if SOC_KEY_MANAGER_SUPPORTED
#include "esp_hal_security/key_mgr_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* @brief Start the key manager at IDLE state */
void key_mgr_hal_start(void);
/* @brief Continue the key manager operation */
void key_mgr_hal_continue(void);
/**
* @brief Set the key manager to use the software provided init key
*/
void key_mgr_hal_use_sw_init_key(void);
/**
* @brief Configure the key manager key usage policy for a particular key type
*/
void key_mgr_hal_set_key_usage(const esp_key_mgr_key_type_t key_type, const esp_key_mgr_key_usage_t key_usage);
/*
* @brief Get the configured key usage for a given key type
*/
esp_key_mgr_key_usage_t key_mgr_hal_get_key_usage(const esp_key_mgr_key_type_t key_type);
/* @brief Configure the key purpose to be used by the Key Manager for key generator operation */
void key_mgr_hal_set_key_purpose(const esp_key_mgr_key_purpose_t key_purpose);
/**
* @bfief Configure the mode which is used by the Key Manager for the generator key deployment process
*/
void key_mgr_hal_set_key_generator_mode(const esp_key_mgr_key_generator_mode_t mode);
/**
* @brief Read the key manager process result
* @return 1 for Success
* 0 for failure
*/
bool key_mgr_hal_is_result_success(void);
/**
* @brief Check if the deployed key is valid or not
* @return 1 for Success
* 0 for failure
*/
bool key_mgr_hal_is_key_deployment_valid(const esp_key_mgr_key_type_t key_type, const esp_key_mgr_key_len_t key_len);
/**
* @brief Check if the HUK is valid or not
* @return 1 for Success
* 0 for failure
*/
bool key_mgr_hal_is_huk_valid(void);
/*
* @brief Write the SW init key in the key manager registers
*
* @input
* sw_init_key_buf Init key buffer, this should be a readable buffer of data_len size which should contain the sw init key. The buffer must be 32 bit aligned
* data_len Length of the init key buffer
*/
void key_mgr_hal_write_sw_init_key(const uint8_t *sw_init_key_buf, const size_t data_len);
/*
* @brief Write the Assist info in the key manager registers
*
* @input
* assist_info_buf Assist info buffer, this should be a readable buffer of data_len size which should contain the assist info. The buffer must be 32 bit aligned
* data_len Length of the assist info buffer
*/
void key_mgr_hal_write_assist_info(const uint8_t *assist_info_buf, const size_t data_len);
/*
* @brief Read the Assist info from the key manager registers
*
* @input
* assist_info_buf Assist info buffer, this should be a writable buffer of size KEY_MGR_ASSIST_INFO_LEN. The buffer must be 32 bit aligned
* data_len Length of the assist info buffer
*/
void key_mgr_hal_read_assist_info(uint8_t *assist_info_buf);
/*
* @brief Write the Public info in the key manager registers
*
* @input
* public_info_buf Public info buffer, this should be a readable buffer of data_len size which should contain the public info. The buffer must be 32 bit aligned
* data_len Length of the public info buffer
*/
void key_mgr_hal_write_public_info(const uint8_t *public_info_buf, const size_t data_len);
/*
* @brief Read the Public info in the key manager registers
*
* @input
* public_info_buf Public info buffer, this should be a writable buffer of read_len, The buffer must be 32 bit aligned
* read_len Length of the public info buffer
*/
void key_mgr_hal_read_public_info(uint8_t *public_info_buf, const size_t read_len);
/* @brief Set the XTS-AES key length for the Key Manager */
void key_mgr_hal_set_xts_aes_key_len(const esp_key_mgr_key_type_t key_type, const esp_key_mgr_key_len_t key_len);
/* @brief Get the XTS-AES key length for the Key Manager */
esp_key_mgr_key_len_t key_mgr_hal_get_xts_aes_key_len(const esp_key_mgr_key_type_t key_type);
/**
* @brief Read state of Key Manager
*
* @return esp_key_mgr_state_t
*/
esp_key_mgr_state_t key_mgr_hal_get_state(void);
/**
* @brief Read the Key Manager date information
*/
uint32_t key_mgr_hal_get_date_info(void);
/**
* @brief Set the Key Manager date information
* Only the least significant 28 bits shall be considered
*/
void key_mgr_hal_set_date_info(const uint32_t date_info);
#ifdef __cplusplus
}
#endif
#endif /* SOC_KEY_MANAGER_SUPPORTED */

View File

@@ -0,0 +1,143 @@
/*
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "esp_attr.h"
#define KEY_MGR_ASSIST_INFO_LEN 64
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief State of Key Manager: idle, load, gain or busy.
*/
typedef enum {
ESP_KEY_MGR_STATE_IDLE = 0, /* Key Manager is idle */
ESP_KEY_MGR_STATE_LOAD = 1, /* Key Manager is ready to receive input */
ESP_KEY_MGR_STATE_GAIN = 2, /* Key Manager is ready to provide output */
ESP_KEY_MGR_STATE_BUSY = 3, /* Key Manager is busy */
} esp_key_mgr_state_t;
/**
* @brief Length of the deployed key (XTS-AES, ECDSA)
*/
typedef enum {
ESP_KEY_MGR_ECDSA_LEN_192 = 0, /* ecdsa key is 192 bit */
ESP_KEY_MGR_ECDSA_LEN_256, /* ecdsa key is 256 bit */
ESP_KEY_MGR_ECDSA_LEN_384, /* ecdsa key is 384 bit */
ESP_KEY_MGR_XTS_AES_LEN_128, /* xts-aes key is 128 bit */
ESP_KEY_MGR_XTS_AES_LEN_256, /* xts-aes key is 512 bit, please note that xts-aes algorithm is XTS_AES_256 */
} esp_key_mgr_key_len_t;
/**
* @brief Type of the key
*/
typedef enum {
ESP_KEY_MGR_ECDSA_KEY = 0, /* ECDSA key */
ESP_KEY_MGR_FLASH_XTS_AES_KEY, /* XTS-AES key */
ESP_KEY_MGR_HMAC_KEY, /* HMAC key */
ESP_KEY_MGR_DS_KEY, /* Digital signature key */
ESP_KEY_MGR_PSRAM_XTS_AES_KEY, /* PSRAM XTS-AES key */
} esp_key_mgr_key_type_t;
/*
* @brief Key Manager key usage type
*/
typedef enum {
ESP_KEY_MGR_USE_OWN_KEY = 0, /* Use key from the key manager */
ESP_KEY_MGR_USE_EFUSE_KEY, /* Use key from the eFuse */
ESP_KEY_MGR_USAGE_INVALID,
} esp_key_mgr_key_usage_t;
/**
* @brief Key Purpose to be set for a particular key in the Key Manager
*/
typedef enum {
ESP_KEY_MGR_KEY_PURPOSE_INVALID = 0,
ESP_KEY_MGR_KEY_PURPOSE_ECDSA_192 = 1, /* ECDSA 192-bit key */
ESP_KEY_MGR_KEY_PURPOSE_ECDSA_256 = 2, /* ECDSA 256-bit key */
ESP_KEY_MGR_KEY_PURPOSE_FLASH_256_1 = 3, /* First half of flash 256-bit key */
ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1 = ESP_KEY_MGR_KEY_PURPOSE_FLASH_256_1,
ESP_KEY_MGR_KEY_PURPOSE_FLASH_256_2 = 4, /* Second half of flash 256-bit key */
ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2 = ESP_KEY_MGR_KEY_PURPOSE_FLASH_256_2,
ESP_KEY_MGR_KEY_PURPOSE_FLASH_128 = 5, /* Flash 128-bit key */
ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_128 = ESP_KEY_MGR_KEY_PURPOSE_FLASH_128,
ESP_KEY_MGR_KEY_PURPOSE_HMAC = 6, /* HMAC key */
ESP_KEY_MGR_KEY_PURPOSE_DS = 7, /* Digital signature key */
ESP_KEY_MGR_KEY_PURPOSE_PSRAM_256_1 = 8, /* First half of PSRAM 256-bit key */
ESP_KEY_MGR_KEY_PURPOSE_PSRAM_256_2 = 9, /* Second half of PSRAM 256-bit key */
ESP_KEY_MGR_KEY_PURPOSE_PSRAM_128 = 10, /* PSRAM 128-bit key */
ESP_KEY_MGR_KEY_PURPOSE_ECDSA_384_L = 11, /* Lower half of ECDSA 384-bit key */
ESP_KEY_MGR_KEY_PURPOSE_ECDSA_384_H = 12, /* Higher half of ECDSA 384-bit key */
} esp_key_mgr_key_purpose_t;
/**
* @brief Key Manager Generator mode
*/
typedef enum {
ESP_KEY_MGR_KEYGEN_MODE_RANDOM = 0,
ESP_KEY_MGR_KEYGEN_MODE_AES = 1,
ESP_KEY_MGR_KEYGEN_MODE_ECDH0 = 2,
ESP_KEY_MGR_KEYGEN_MODE_ECDH1 = 3,
ESP_KEY_MGR_KEYGEN_MODE_RECOVER = 4,
ESP_KEY_MGR_KEYGEN_MODE_EXPORT = 5,
} esp_key_mgr_key_generator_mode_t;
/**
* @brief
* Key Manager interrupt types
*/
typedef enum {
ESP_KEY_MGR_INT_PREP_DONE = 0x01,
ESP_KEY_MGR_INT_PROC_DONE,
ESP_KEY_MGR_INT_POST_DONE,
} esp_key_mgr_interrupt_type_t;
/**
* @brief Force use key manager key type
* @note This is used to force the key manager to use a specific key type.
*/
typedef enum {
ESP_KEY_MGR_FORCE_USE_KM_ECDSA_KEY = 0,
ESP_KEY_MGR_FORCE_USE_KM_XTS_AES_KEY = 1,
ESP_KEY_MGR_FORCE_USE_KM_HMAC_KEY = 2,
ESP_KEY_MGR_FORCE_USE_KM_DS_KEY = 3,
} esp_key_mgr_force_use_km_key_t;
// store huk info, occupy 96 words
typedef struct PACKED_ATTR {
#define HUK_INFO_LEN 660
uint8_t info[HUK_INFO_LEN];
uint32_t crc;
} esp_key_mgr_huk_info_t;
// store key info, occupy 512 bits
typedef struct PACKED_ATTR {
#define KEY_INFO_LEN 64
uint8_t info[KEY_INFO_LEN];
uint32_t crc;
} esp_key_mgr_key_info_t;
typedef struct WORD_ALIGNED_ATTR PACKED_ATTR {
#define KEY_HUK_SECTOR_MAGIC 0xDEA5CE5A
uint32_t magic;
uint32_t version; // for backward compatibility
uint8_t key_type;
uint8_t key_len;
uint8_t key_deployment_mode;
uint8_t reserved[13];
esp_key_mgr_huk_info_t huk_info;
esp_key_mgr_key_info_t key_info[2]; // at most 2 key info (XTS-512_1 and XTS-512_2), at least use 1
} esp_key_mgr_key_recovery_info_t;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,146 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* NOTICE
* The HAL is not public api, don't use in application code.
* See readme.md in soc/README.md
******************************************************************************/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <sys/param.h>
#include "esp_hal_security/mpi_types.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Calculate the number of words needed to represent the input word in hardware.
*
* @param words The number of words to be represented.
* @return size_t Number of words required.
*/
size_t mpi_hal_calc_hardware_words(size_t words);
/**
* @brief Clear the MPI power control bit and initialise the MPI hardware.
*
*/
void mpi_hal_enable_hardware_hw_op(void);
/**
* @brief Set the MPI power control bit to disable the MPI hardware.
*
*/
void mpi_hal_disable_hardware_hw_op(void);
/**
* @brief Enable/disables MPI operation complete interrupt.
*
* @param enable true: enable, false: disable.
*/
void mpi_hal_interrupt_enable(bool enable);
/**
* @brief Clears the MPI operation complete interrupt status.
*
*/
void mpi_hal_clear_interrupt(void);
/**
* @brief Configure RSA length.
*
* @param num_words Number of words representing the RSA length.
*/
void mpi_hal_set_mode(size_t num_words);
/**
* @brief Copy the large number (array of words) representation of the parameter 'param' to hardware memory block.
*
* @param param Type of parameter (enum).
* @param offset Offset to copy in the memory from the base address of the parameter.
* @param p Pointer to large number (array of words) representation of the parameter.
* @param n Number of words needed to represent the large number as an array of words.
* @param num_words Maximum hardware words needed.
*/
void mpi_hal_write_to_mem_block(mpi_param_t param, size_t offset, const uint32_t* p, size_t n, size_t num_words);
/**
* @brief Write a word-sized value to hardware memory block of a parameter.
*
* @param param Type of parameter (enum).
* @param offset Offset to copy in the memory from the base address of the parameter.
* @param value Value to be written in the memory.
*/
void mpi_hal_write_at_offset(mpi_param_t param, int offset, uint32_t value);
/**
* @brief Write the modular multiplicative inverse of M.
*
* @param Mprime Modular multiplicative inverse of M.
*/
void mpi_hal_write_m_prime(uint32_t Mprime);
/**
* @brief Write first word of the parameter Rinv.
*
* @param rinv Value of first word of rinv.
*/
void mpi_hal_write_rinv(uint32_t rinv);
#if !SOC_IS(ESP32)
/**
* @brief Enable/Disable constant time acceleration option.
*
* @param enable true: enable, false: disable.
*/
void mpi_hal_enable_constant_time(bool enable);
/**
* @brief Enable/Disable search time acceleration option.
*
* @param enable
*/
void mpi_hal_enable_search(bool enable);
/**
* @brief Configures the starting address to start search.
*
* @param position Address to start search.
*/
void mpi_hal_set_search_position(size_t position);
#endif /* !SOC_IS(ESP32) */
/**
* @brief Begin an MPI operation.
*
* @param op Operation type (enum).
*/
void mpi_hal_start_op(mpi_op_t op);
/**
* @brief Wait for an MPI operation to complete.
*
*/
void mpi_hal_wait_op_complete(void);
/**
* @brief Wait for an MPI operation to complete and Read result from last MPI operation into parameter Z.
*
* @param p Pointer to large number (array of words) representation of the parameter.
* @param n Number of words needed to represent the large number as an array of words.
* @param z_words Calculated number of words of parameter Z.
*/
void mpi_hal_read_result_hw_op(uint32_t* p, size_t n, size_t z_words);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
MPI_MULT = 0x0, // (X * Y)
MPI_MODMULT, // (X * Y) Mod M
MPI_MODEXP, // (X ^ Y) Mod M
} mpi_op_t;
typedef enum {
MPI_PARAM_X = 0x0,
MPI_PARAM_Y,
MPI_PARAM_Z,
MPI_PARAM_M,
} mpi_param_t;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_err.h"
#include "esp_hal_security/mpu_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Specify the type of access allowed on a memory region.
*
* @param id index to the region table; on targets not SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED,
* the region divisions is predefined in hardware which is likely reflected in LL implementation.
* @param access type of access allowed
*/
void mpu_hal_set_region_access(int id, mpu_access_t access);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
typedef void** mpu_region_table_t;
#endif
typedef enum {
MPU_REGION_ILLEGAL,
#if SOC_MPU_REGION_RO_SUPPORTED
MPU_REGION_RO, // read-only
#endif
#if SOC_MPU_REGION_WO_SUPPORTED
MPU_REGION_WO, // write-only
#endif
MPU_REGION_RW, // read-write
MPU_REGION_X, // executable
MPU_REGION_RWX // read-write-executable
} mpu_access_t;
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,88 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*******************************************************************************
* 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/soc_caps.h"
#include "soc/lldesc.h"
#include "esp_hal_security/sha_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Load the mode for the SHA engine
*
* @param sha_type The SHA algorithm type
*/
void sha_hal_set_mode(esp_sha_type sha_type);
/**
* @brief Hashes a single message block
*
* @param sha_type SHA algorithm to hash with
* @param data_block Input message to be hashed
* @param block_word_len Length of the input message
* @param first_block Is this the first block in a message or a continuation?
*/
void sha_hal_hash_block(esp_sha_type sha_type, const void *data_block, size_t block_word_len, bool first_block);
/**
* @brief Polls and waits until the SHA engine is idle
*
*/
void sha_hal_wait_idle(void);
/**
* @brief Reads the current message digest from the SHA engine
*
* @param sha_type SHA algorithm used
* @param digest_state Output buffer to which to read message digest to
*/
void sha_hal_read_digest(esp_sha_type sha_type, void *digest_state);
#if SOC_SHA_SUPPORT_RESUME
/**
* @brief Writes 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
*/
void sha_hal_write_digest(esp_sha_type sha_type, void *digest_state);
#endif
#if SOC_SHA_SUPPORT_DMA
/**
* @brief Hashes a number of message blocks using DMA
*
* @param num_blocks Number of blocks to hash
* @param first_block Is this the first block in a message or a continuation?
*/
void sha_hal_hash_dma(size_t num_blocks, bool first_block);
#endif
#if SOC_SHA_SUPPORT_SHA512_T
/**
* @brief Calculates and sets the initial digiest for SHA512_t
*
* @param t_string
* @param t_len
*/
void sha_hal_sha512_init_hash(uint32_t t_string, uint8_t t_len);
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "rom/sha.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef SHA_TYPE esp_sha_type;
#ifdef __cplusplus
}
#endif