diff --git a/components/esp_hal_security/esp32s31/include/hal/aes_ll.h b/components/esp_hal_security/esp32s31/include/hal/aes_ll.h new file mode 100644 index 00000000000..0178472f198 --- /dev/null +++ b/components/esp_hal_security/esp32s31/include/hal/aes_ll.h @@ -0,0 +1,290 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "hal/aes_types.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/hwcrypto_reg.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) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_aes_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define aes_ll_enable_bus_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _aes_ll_enable_bus_clock(__VA_ARGS__); \ + } while(0) + +/** + * @brief Reset the AES peripheral module + */ +static inline void aes_ll_reset_register(void) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_aes_rst_en = 1; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_aes_rst_en = 0; + + // Clear reset on digital signature and parent crypto, otherwise AES is held in reset + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ds_rst_en = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define aes_ll_reset_register(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + aes_ll_reset_register(__VA_ARGS__); \ + } while(0) + +/** + * @brief Write the encryption/decryption key to hardware + * + * @param key Key to be written to the AES hardware + * @param key_word_len Number of words in the key + * + * @return Number of bytes written to hardware, used for fault injection check + */ +static inline uint8_t aes_ll_write_key(const uint8_t *key, size_t key_word_len) +{ + /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ + volatile uint8_t key_in_hardware = 0; + /* Memcpy to avoid potential unaligned access */ + uint32_t key_word; + for (int i = 0; i < key_word_len; i++) { + memcpy(&key_word, key + 4 * i, 4); + REG_WRITE(AES_KEY_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(®_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); +} + +/** + * @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 + */ +static inline void aes_ll_enable_pseudo_rounds(bool enable, uint8_t base, uint8_t increment, uint8_t key_rng_cnt) +{ + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_EN, enable); + + if (enable) { + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_BASE, base); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_INC, increment); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_RNG_CNT, key_rng_cnt); + } else { + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_BASE, 0); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_INC, 0); + REG_SET_FIELD(AES_PSEUDO_REG, AES_PSEUDO_RNG_CNT, 0); + } +} + +/** + * @brief Check if the pseudo round function is supported + */ +static inline bool aes_ll_is_pseudo_rounds_function_supported(void) +{ + return true; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_security/esp32s31/include/hal/ecc_ll.h b/components/esp_hal_security/esp32s31/include/hal/ecc_ll.h new file mode 100644 index 00000000000..c23094a77bd --- /dev/null +++ b/components/esp_hal_security/esp32s31/include/hal/ecc_ll.h @@ -0,0 +1,264 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "hal/assert.h" +#include "hal/ecc_types.h" +#include "soc/ecc_mult_reg.h" +#include "soc/hp_sys_clkrst_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ECC_PARAM_PX = 0x0, + ECC_PARAM_PY, + ECC_PARAM_K, + ECC_PARAM_QX, + ECC_PARAM_QY, + ECC_PARAM_QZ, +} 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) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ecc_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define ecc_ll_enable_bus_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _ecc_ll_enable_bus_clock(__VA_ARGS__); \ + } while(0) + +/** + * @brief Reset the ECC peripheral module + */ +static inline void ecc_ll_reset_register(void) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ecc_rst_en = 1; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ecc_rst_en = 0; + + // Clear reset on ECDSA and parent crypto, otherwise ECC is held in reset + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ecdsa_rst_en = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define ecc_ll_reset_register(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + ecc_ll_reset_register(__VA_ARGS__); \ + } while(0) + +static inline void ecc_ll_power_up(void) {} +static inline void ecc_ll_power_down(void) {} + +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; + case ECC_MODE_JACOBIAN_POINT_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 4); + break; + case ECC_MODE_POINT_ADD: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 5); + break; + case ECC_MODE_JACOBIAN_POINT_VERIFY: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 6); + break; + case ECC_MODE_POINT_VERIFY_JACOBIAN_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 7); + break; + case ECC_MODE_MOD_ADD: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 8); + break; + case ECC_MODE_MOD_SUB: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 9); + break; + case ECC_MODE_MOD_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 10); + break; + case ECC_MODE_INVERSE_MUL: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_WORK_MODE, 11); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + break; + } +} + +static inline void ecc_ll_set_curve(ecc_curve_t curve) +{ + switch (curve) { + case ECC_CURVE_SECP192R1: + case ECC_CURVE_SECP256R1: + case ECC_CURVE_SECP384R1: + case ECC_CURVE_SM2: + REG_SET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_KEY_LENGTH, curve); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + } +} + +static inline void ecc_ll_set_mod_base(ecc_mod_base_t base) +{ + switch (base) { + case ECC_MOD_N: + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); + break; + case ECC_MOD_P: + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE); + 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; + case ECC_PARAM_QX: + reg = ECC_MULT_QX_MEM; + break; + case ECC_PARAM_QY: + reg = ECC_MULT_QY_MEM; + break; + case ECC_PARAM_QZ: + reg = ECC_MULT_QZ_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 ecc_mod_base_t ecc_ll_get_mod_base(void) +{ + return (ecc_mod_base_t)(REG_GET_FIELD(ECC_MULT_CONF_REG, ECC_MULT_MOD_BASE)); +} + +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; + case ECC_PARAM_QX: + reg = ECC_MULT_QX_MEM; + break; + case ECC_PARAM_QY: + reg = ECC_MULT_QY_MEM; + break; + case ECC_PARAM_QZ: + reg = ECC_MULT_QZ_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + memcpy(buf, (void *)reg, len); +} + +static inline bool ecc_ll_is_p384_curve_operations_supported(void) +{ + return true; +} + +static inline void ecc_ll_enable_constant_time_point_mul(bool enable) +{ + if (enable) { + REG_SET_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE); + } else { + REG_CLR_BIT(ECC_MULT_CONF_REG, ECC_MULT_SECURITY_MODE); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_security/esp32s31/include/hal/mpi_ll.h b/components/esp_hal_security/esp32s31/include/hal/mpi_ll.h new file mode 100644 index 00000000000..7f03454720a --- /dev/null +++ b/components/esp_hal_security/esp32s31/include/hal/mpi_ll.h @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include +#include "hal/assert.h" +#include "hal/mpi_types.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/mpi_periph.h" +#include "soc/rsa_reg.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) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rsa_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define mpi_ll_enable_bus_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _mpi_ll_enable_bus_clock(__VA_ARGS__); \ + } while(0) + +/** + * @brief Reset the MPI peripheral module + */ +static inline void mpi_ll_reset_register(void) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rsa_rst_en = 1; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rsa_rst_en = 0; + + // Clear reset on digital signature, ECDSA and parent crypto, otherwise RSA is held in reset + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ds_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ecdsa_rst_en = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define mpi_ll_reset_register(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + mpi_ll_reset_register(__VA_ARGS__); \ + } while(0) + +static inline size_t mpi_ll_calculate_hardware_words(size_t words) +{ + return words; +} + +// No need to initialize Power Control Registers in case of ESP32-S31 +static inline void mpi_ll_power_up(void) +{ +} + +static inline void mpi_ll_power_down(void) +{ +} + +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 diff --git a/components/esp_hal_security/esp32s31/include/hal/sha_ll.h b/components/esp_hal_security/esp32s31/include/hal/sha_ll.h new file mode 100644 index 00000000000..ca6151d9e5f --- /dev/null +++ b/components/esp_hal_security/esp32s31/include/hal/sha_ll.h @@ -0,0 +1,216 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include "hal/sha_types.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "soc/hwcrypto_reg.h" + +/* ESP32-S31 SHA register header uses SHA_2_SM_3_H_MEM/M_MEM naming + * instead of SHA_H_MEM/M_MEM. Define compatibility macros. */ +#define SHA_H_MEM SHA_2_SM_3_H_MEM +#define SHA_M_MEM SHA_2_SM_3_M_MEM + +#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) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_sha_clk_en = enable; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define sha_ll_enable_bus_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _sha_ll_enable_bus_clock(__VA_ARGS__); \ + } while(0) + +/** + * @brief Reset the SHA peripheral module + */ +static inline void sha_ll_reset_register(void) +{ + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_sha_rst_en = 1; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_sha_rst_en = 0; + + // Clear reset on digital signature, hmac, ecdsa and parent crypto, otherwise SHA is held in reset + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ds_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_hmac_rst_en = 0; + HP_SYS_CLKRST.crypto_ctrl0.reg_crypto_ecdsa_rst_en = 0; +} + +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define sha_ll_reset_register(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + sha_ll_reset_register(__VA_ARGS__); \ + } while(0) + +/** + * @brief Load the mode for the SHA engine + * + * @param sha_type The SHA algorithm type + */ +static inline void sha_ll_set_mode(esp_sha_type sha_type) +{ + REG_WRITE(SHA_MODE_REG, sha_type); +} + +/** + * @brief Start a new SHA block conversions (no initial hash in HW) + * + * @param sha_type The SHA algorithm type + */ +static inline void sha_ll_start_block(esp_sha_type sha_type) +{ + (void) sha_type; + REG_WRITE(SHA_START_REG, 1); +} + +/** + * @brief Continue a SHA block conversion (initial hash in HW) + * + * @param sha_type The SHA algorithm type + */ +static inline void sha_ll_continue_block(esp_sha_type sha_type) +{ + (void) sha_type; + REG_WRITE(SHA_CONTINUE_REG, 1); +} + +/** + * @brief Start a new SHA message conversion using DMA (no initial hash in HW) + */ +static inline void sha_ll_start_dma(void) +{ + REG_WRITE(SHA_DMA_START_REG, 1); +} + +/** + * @brief Continue a SHA message conversion using DMA (initial hash in HW) + */ +static inline void sha_ll_continue_dma(void) +{ + REG_WRITE(SHA_DMA_CONTINUE_REG, 1); +} + +/** + * @brief Load the current hash digest to digest register + * + * @note Happens automatically on ESP32S31 + * + * @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(®_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(®_addr_buf[i], digest_state_words[i]); + } +} + +/** + * @brief Sets SHA512_t T_string parameter + * + * @param t_string T_string parameter + */ +static inline void sha_ll_t_string_set(uint32_t t_string) +{ + REG_WRITE(SHA_T_STRING_REG, t_string); +} + +/** + * @brief Sets SHA512_t T_string parameter's length + * + * @param t_len T_string parameter length + */ +static inline void sha_ll_t_len_set(uint8_t t_len) +{ + REG_WRITE(SHA_T_LENGTH_REG, t_len); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_rom/esp32s31/include/esp32s31/rom/aes.h b/components/esp_rom/esp32s31/include/esp32s31/rom/aes.h new file mode 100644 index 00000000000..f49125276d8 --- /dev/null +++ b/components/esp_rom/esp32s31/include/esp32s31/rom/aes.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _ROM_AES_H_ +#define _ROM_AES_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum AES_TYPE { + AES_ENC, + AES_DEC, +}; + +enum AES_BITS { + AES128, + AES256 = 2, /* skipping enum value 1 to keep compatibility with chips that support AES-192 */ +}; + +void ets_aes_enable(void); + +void ets_aes_disable(void); + +int ets_aes_setkey(enum AES_TYPE type, const void *key, enum AES_BITS bits); + +int ets_aes_setkey_enc(const void *key, enum AES_BITS bits); + +int ets_aes_setkey_dec(const void *key, enum AES_BITS bits); + +void ets_aes_block(const void *input, void *output); + +#ifdef __cplusplus +} +#endif + +#endif /* _ROM_AES_H_ */ diff --git a/components/esp_security/src/esp32s31/esp_crypto_clk.h b/components/esp_security/src/esp32s31/esp_crypto_clk.h index 77e24f772ae..f18deb1cb0a 100644 --- a/components/esp_security/src/esp32s31/esp_crypto_clk.h +++ b/components/esp_security/src/esp32s31/esp_crypto_clk.h @@ -11,6 +11,5 @@ static inline void esp_crypto_clk_init(void) { // Set crypto clock (`clk_sec`) to use 240M PLL clock - // TODO: ["ESP32S31"] IDF-14629 - // REG_SET_FIELD(HP_SYS_CLKRST_CRYPTO_CTRL0_REG, HP_SYS_CLKRST_REG_CRYPTO_CLK_SRC_SEL, 0x2); + REG_SET_FIELD(HP_SYS_CLKRST_CRYPTO_CTRL0_REG, HP_SYS_CLKRST_REG_CRYPTO_CLK_SRC_SEL, 0x2); } diff --git a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in index b07cbe31f3e..348b966141f 100644 --- a/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s31/include/soc/Kconfig.soc_caps.in @@ -87,6 +87,26 @@ config SOC_SYSTIMER_SUPPORTED bool default y +config SOC_AES_SUPPORTED + bool + default y + +config SOC_MPI_SUPPORTED + bool + default y + +config SOC_SHA_SUPPORTED + bool + default y + +config SOC_ECC_SUPPORTED + bool + default y + +config SOC_ECC_EXTENDED_MODES_SUPPORTED + bool + default y + config SOC_PAU_SUPPORTED bool default y @@ -507,6 +527,94 @@ config SOC_MWDT_SUPPORT_XTAL bool default y +config SOC_AES_GDMA + bool + default y + +config SOC_AES_SUPPORT_DMA + bool + default y + +config SOC_AES_SUPPORT_AES_128 + bool + default y + +config SOC_AES_SUPPORT_AES_256 + bool + default y + +config SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION + bool + default y + +config SOC_SHA_GDMA + bool + default y + +config SOC_SHA_DMA_MAX_BUFFER_SIZE + int + default 3968 + +config SOC_SHA_SUPPORT_DMA + bool + default y + +config SOC_SHA_SUPPORT_RESUME + bool + default y + +config SOC_SHA_SUPPORT_SHA1 + bool + default y + +config SOC_SHA_SUPPORT_SHA224 + bool + default y + +config SOC_SHA_SUPPORT_SHA256 + bool + default y + +config SOC_SHA_SUPPORT_SHA384 + bool + default y + +config SOC_SHA_SUPPORT_SHA512 + bool + default y + +config SOC_SHA_SUPPORT_SHA512_224 + bool + default y + +config SOC_SHA_SUPPORT_SHA512_256 + bool + default y + +config SOC_SHA_SUPPORT_SHA512_T + bool + default y + +config SOC_MPI_MEM_BLOCKS_NUM + int + default 4 + +config SOC_MPI_OPERATIONS_NUM + int + default 3 + +config SOC_RSA_MAX_BIT_LEN + int + default 4096 + +config SOC_ECC_CONSTANT_TIME_POINT_MUL + bool + default y + +config SOC_ECC_SUPPORT_CURVE_P384 + bool + default y + config SOC_EFUSE_DIS_PAD_JTAG bool default y diff --git a/components/soc/esp32s31/include/soc/soc_caps.h b/components/soc/esp32s31/include/soc/soc_caps.h index 2449699a9f5..8cfeb48e98d 100644 --- a/components/soc/esp32s31/include/soc/soc_caps.h +++ b/components/soc/esp32s31/include/soc/soc_caps.h @@ -62,13 +62,13 @@ // #define SOC_ISP_SUPPORTED 1 // TODO: [ESP32S31] IDF-14769 // #define SOC_I2C_SUPPORTED 1 // TODO: [ESP32S31] IDF-14726 #define SOC_SYSTIMER_SUPPORTED 1 // TODO: [ESP32S31] IDF-14693 -// #define SOC_AES_SUPPORTED 1 // TODO: [ESP32S31] IDF-14633 -// #define SOC_MPI_SUPPORTED 1 // TODO: [ESP32S31] IDF-14633 -// #define SOC_SHA_SUPPORTED 1 // TODO: [ESP32S31] IDF-14630 +#define SOC_AES_SUPPORTED 1 +#define SOC_MPI_SUPPORTED 1 +#define SOC_SHA_SUPPORTED 1 // #define SOC_HMAC_SUPPORTED 1 // TODO: [ESP32S31] IDF-14621 // #define SOC_DIG_SIGN_SUPPORTED 1 // TODO: [ESP32S31] IDF-14624 -// #define SOC_ECC_SUPPORTED 1 // TODO: [ESP32S31] IDF-14631 -// #define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 // TODO: [ESP32S31] IDF-14631 +#define SOC_ECC_SUPPORTED 1 +#define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 // #define SOC_FLASH_ENC_SUPPORTED 1 // TODO: [ESP32S31] IDF-14628 // #define SOC_SECURE_BOOT_SUPPORTED 1 // TODO: [ESP32S31] IDF-14629 // #define SOC_BOD_SUPPORTED 1 // TODO: [ESP32S31] IDF-14658 @@ -267,6 +267,37 @@ #define SOC_MWDT_SUPPORT_XTAL (1) // #define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1) +/*-------------------------- AES CAPS ----------------------------------------*/ +#define SOC_AES_GDMA (1) +#define SOC_AES_SUPPORT_DMA (1) +#define SOC_AES_SUPPORT_AES_128 (1) +#define SOC_AES_SUPPORT_AES_256 (1) +// TODO: [ESP32S31] IDF-14633 SOC_AES_SUPPORT_GCM not enabled: GCM control registers (AAD_BLOCK_NUM, REMAINDER_BIT_NUM, CONTINUE) non-functional on v0.0 silicon +#define SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION (1) + +/*-------------------------- SHA CAPS ----------------------------------------*/ +#define SOC_SHA_GDMA (1) +#define SOC_SHA_DMA_MAX_BUFFER_SIZE (3968) +#define SOC_SHA_SUPPORT_DMA (1) +#define SOC_SHA_SUPPORT_RESUME (1) +#define SOC_SHA_SUPPORT_SHA1 (1) +#define SOC_SHA_SUPPORT_SHA224 (1) +#define SOC_SHA_SUPPORT_SHA256 (1) +#define SOC_SHA_SUPPORT_SHA384 (1) +#define SOC_SHA_SUPPORT_SHA512 (1) +#define SOC_SHA_SUPPORT_SHA512_224 (1) +#define SOC_SHA_SUPPORT_SHA512_256 (1) +#define SOC_SHA_SUPPORT_SHA512_T (1) + +/*-------------------------- MPI/RSA CAPS ----------------------------------------*/ +#define SOC_MPI_MEM_BLOCKS_NUM (4) +#define SOC_MPI_OPERATIONS_NUM (3) +#define SOC_RSA_MAX_BIT_LEN (4096) + +/*-------------------------- ECC CAPS ----------------------------------------*/ +#define SOC_ECC_CONSTANT_TIME_POINT_MUL 1 +#define SOC_ECC_SUPPORT_CURVE_P384 (1) + /*-------------------------- eFuse CAPS----------------------------*/ // TODO: [ESP32S31] IDF-14688 #define SOC_EFUSE_DIS_PAD_JTAG 1 diff --git a/components/soc/esp32s31/mpi_periph.c b/components/soc/esp32s31/mpi_periph.c new file mode 100644 index 00000000000..8d8152a1907 --- /dev/null +++ b/components/soc/esp32s31/mpi_periph.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + */ + +#include "soc/rsa_reg.h" +#include "soc/mpi_periph.h" + +const uint32_t MPI_BLOCK_BASES[SOC_MPI_MEM_BLOCKS_NUM] = { + RSA_X_MEM, + RSA_Y_MEM, + RSA_Z_MEM, + RSA_M_MEM, +}; + +const uint32_t MPI_OPERATIONS_REG[SOC_MPI_OPERATIONS_NUM] = { + RSA_SET_START_MULT_REG, + RSA_SET_START_MODMULT_REG, + RSA_SET_START_MODEXP_REG, +}; diff --git a/components/soc/esp32s31/register/soc/sha_reg.h b/components/soc/esp32s31/register/soc/sha_reg.h index 9da2017ce24..f661d3c8ac2 100644 --- a/components/soc/esp32s31/register/soc/sha_reg.h +++ b/components/soc/esp32s31/register/soc/sha_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -37,6 +37,36 @@ extern "C" { #define SHA_MODE_V 0x0000000FU #define SHA_MODE_S 0 +/** SHA_T_STRING_REG register + * SHA 512/t configuration register 0. + * This register is only for internal debugging purposes. Do not use it in + * applications. + */ +#define SHA_T_STRING_REG (DR_REG_SHA_BASE + 0x4) +/** SHA_T_STRING : R/W; bitpos: [31:0]; default: 0; + * Sha t_string (used if and only if mode == SHA_512/t). + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SHA_T_STRING 0xFFFFFFFFU +#define SHA_T_STRING_M (SHA_T_STRING_V << SHA_T_STRING_S) +#define SHA_T_STRING_V 0xFFFFFFFFU +#define SHA_T_STRING_S 0 + +/** SHA_T_LENGTH_REG register + * SHA 512/t configuration register 1. + * This register is only for internal debugging purposes. Do not use it in + * applications. + */ +#define SHA_T_LENGTH_REG (DR_REG_SHA_BASE + 0x8) +/** SHA_T_LENGTH : R/W; bitpos: [6:0]; default: 0; + * Sha t_length (used if and only if mode == SHA_512/t). + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SHA_T_LENGTH 0x0000007FU +#define SHA_T_LENGTH_M (SHA_T_LENGTH_V << SHA_T_LENGTH_S) +#define SHA_T_LENGTH_V 0x0000007FU +#define SHA_T_LENGTH_S 0 + /** SHA_DMA_BLOCK_NUM_REG register * Block number register (only effective for DMA-SHA) */