From e5d246ef27477fb7ad3e1cfd4e0abdc41f256277 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 1 Oct 2024 14:20:20 +0530 Subject: [PATCH 1/3] feat(hal): esp32c5: Add hal layer for key manager --- .../esp_rom/esp32c5/include/esp32c5/rom/km.h | 63 ++++ components/hal/esp32c5/include/hal/huk_ll.h | 118 ++++++ .../hal/esp32c5/include/hal/key_mgr_ll.h | 356 ++++++++++++++++++ .../include/hal/mspi_timing_tuning_ll.h | 8 + .../hal/{esp32p4 => }/include/hal/huk_hal.h | 2 +- .../{esp32p4 => }/include/hal/key_mgr_hal.h | 10 +- .../esp32c5/include/soc/Kconfig.soc_caps.in | 8 + components/soc/esp32c5/include/soc/soc_caps.h | 4 + .../soc/esp32c5/register/soc/keymng_reg.h | 33 ++ 9 files changed, 596 insertions(+), 6 deletions(-) create mode 100644 components/esp_rom/esp32c5/include/esp32c5/rom/km.h create mode 100644 components/hal/esp32c5/include/hal/huk_ll.h create mode 100644 components/hal/esp32c5/include/hal/key_mgr_ll.h rename components/hal/{esp32p4 => }/include/hal/huk_hal.h (96%) rename components/hal/{esp32p4 => }/include/hal/key_mgr_hal.h (94%) diff --git a/components/esp_rom/esp32c5/include/esp32c5/rom/km.h b/components/esp_rom/esp32c5/include/esp32c5/rom/km.h new file mode 100644 index 0000000000..2fe74e77a5 --- /dev/null +++ b/components/esp_rom/esp32c5/include/esp32c5/rom/km.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _KM_H +#define _KM_H + +#include "soc/soc_caps.h" +#if SOC_KEY_MANAGER_SUPPORTED + +#include +#include "soc/soc.h" +#include "ets_sys.h" + +#if __cplusplus +extern "C" { +#endif + +/* huk mode type */ +typedef enum { + HUK_MODE_RECOVER = 0, + HUK_MODE_GEN = 1, +} huk_mode_t; + +/** + * @brief Recover efuse key or key manager key if flash encryption is enabled + * + * @param do_log : if km process print log + * + * @return ETS_OK when key is recovered, ETS_FAILED when key not recovered + */ +ETS_STATUS esp_rom_check_recover_key(int do_log); + +/** + * @brief Configure huk mode + * + * @param mode : HUK_MODE_RECOVER or HUK_MODE_GEN + * + * @param huk_info : uint8_t pointer to the buffer which will feed the huk info or + * gain the huk info + * + * @return ETS_OK when huk configuration is done, else ETS_FAILED + */ +ETS_STATUS esp_rom_km_huk_conf(huk_mode_t mode, uint8_t *huk_info); + +/** + * @brief Get huk risk. The risk level of HUK is 0-6: the higher the risk level is, + * the more error bits there are in the PUF SRAM. 7: Error level, HUK is invalid + * + * @param None + * + * @return The huk risk + */ +int esp_rom_km_huk_risk(void); + +#ifdef __cplusplus +} +#endif +#endif /* SOC_KEY_MANAGER_SUPPORTED */ + +#endif /* _KM_H */ diff --git a/components/hal/esp32c5/include/hal/huk_ll.h b/components/hal/esp32c5/include/hal/huk_ll.h new file mode 100644 index 0000000000..37215ae35e --- /dev/null +++ b/components/hal/esp32c5/include/hal/huk_ll.h @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use it in application code. + ******************************************************************************/ + +#pragma once + +#include "soc/soc_caps.h" + +#if SOC_KEY_MANAGER_SUPPORTED + +#include +#include +#include + +#include "hal/huk_types.h" +#include "soc/huk_reg.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* @brief Configure the HUK mode */ +static inline void huk_ll_configure_mode(const esp_huk_mode_t huk_mode) +{ + REG_SET_FIELD(HUK_CONF_REG, HUK_MODE, huk_mode); +} + +static inline void huk_ll_write_info(const uint8_t *buffer, const size_t size) +{ + memcpy((uint8_t *)HUK_INFO_MEM, buffer, size); +} + +static inline void huk_ll_read_info(uint8_t *buffer, const size_t size) +{ + memcpy(buffer, (uint8_t *)HUK_INFO_MEM, size); +} + +/* @brief Start the HUK at IDLE state */ +static inline void huk_ll_start(void) +{ + REG_SET_FIELD(HUK_START_REG, HUK_START, 1); +} + +/* @brief Continue HUK operation at LOAD/GAIN state */ +static inline void huk_ll_continue(void) +{ + REG_SET_FIELD(HUK_START_REG, HUK_CONTINUE, 1); +} + +/* @bried Enable or Disable the HUK interrupts */ +static inline void huk_ll_configure_interrupt(const esp_huk_interrupt_type_t intr, const bool en) +{ + switch(intr) { + case ESP_HUK_INT_PREP_DONE: + REG_SET_FIELD(HUK_INT_ENA_REG, HUK_PREP_DONE_INT_ENA, en); + case ESP_HUK_INT_PROC_DONE: + REG_SET_FIELD(HUK_INT_ENA_REG, HUK_PROC_DONE_INT_ENA, en); + case ESP_HUK_INT_POST_DONE: + REG_SET_FIELD(HUK_INT_ENA_REG, HUK_POST_DONE_INT_ENA, en); + default: + return; + } +} + +/* @bried Clear the HUK interrupts */ +static inline void huk_ll_clear_int(const esp_huk_interrupt_type_t intr) +{ + switch(intr) { + case ESP_HUK_INT_PREP_DONE: + REG_SET_FIELD(HUK_INT_CLR_REG, HUK_PREP_DONE_INT_CLR, 1); + case ESP_HUK_INT_PROC_DONE: + REG_SET_FIELD(HUK_INT_CLR_REG, HUK_PROC_DONE_INT_CLR, 1); + case ESP_HUK_INT_POST_DONE: + REG_SET_FIELD(HUK_INT_CLR_REG, HUK_POST_DONE_INT_CLR, 1); + default: + return; + } +} + +/** + * @brief Read state of Hardware Unique Key Generator + * + * @return esp_huk_state_t + */ +static inline esp_huk_state_t huk_ll_get_state(void) +{ + return (esp_huk_state_t) REG_GET_FIELD(HUK_STATE_REG, HUK_STATE); +} + +/** + * @brief Get the HUK generation status + */ +static inline esp_huk_gen_status_t huk_ll_get_gen_status(void) +{ + return (esp_huk_gen_status_t) REG_GET_FIELD(HUK_STATUS_REG, HUK_STATUS); +} + +/** + * @brief Read the HUK date information + */ +static inline uint32_t huk_ll_get_date_info(void) +{ + // Only the least significant 28 bits have desired information + return (uint32_t)(0x0FFFFFFF & REG_READ(HUK_DATE_REG)); +} + +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/hal/esp32c5/include/hal/key_mgr_ll.h b/components/hal/esp32c5/include/hal/key_mgr_ll.h new file mode 100644 index 0000000000..1076555f02 --- /dev/null +++ b/components/hal/esp32c5/include/hal/key_mgr_ll.h @@ -0,0 +1,356 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The hal is not public api, don't use it in application code. + ******************************************************************************/ + +#pragma once + +#include +#include +#include + +#include "hal/assert.h" +#include "hal/key_mgr_types.h" +#include "soc/keymng_reg.h" +#include "soc/pcr_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Read state of Key Manager + * + * @return esp_key_mgr_state_t + */ +static inline esp_key_mgr_state_t key_mgr_ll_get_state(void) +{ + return (esp_key_mgr_state_t) REG_GET_FIELD(KEYMNG_STATE_REG, KEYMNG_STATE); +} + +/** + * @brief Enable the bus clock for Key Manager peripheral + * Note: Please use key_mgr_ll_enable_bus_clock which requires the critical section + * and do not use _key_mgr_ll_enable_bus_clock + * @param true to enable, false to disable + */ +static inline void _key_mgr_ll_enable_bus_clock(bool enable) +{ + // Set the force power down bit to 0 to enable key manager + PCR.km_pd_ctrl.km_mem_force_pd = 0; + // Enable key manager clock + PCR.km_conf.km_clk_en = 1; +} + +/// 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 key_mgr_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Enable the peripheral clock for Key Manager + * + * Note: Please use key_mgr_ll_enable_peripheral_clock which requires the critical section + * and do not use _key_mgr_ll_enable_peripheral_clock + * @param true to enable, false to disable + */ +static inline void _key_mgr_ll_enable_peripheral_clock(bool enable) +{ + ; /* Nothing to do here, Kept for compatibility with other SoC */ +} + +#define key_mgr_ll_enable_peripheral_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_peripheral_clock(__VA_ARGS__) + +/** + * @brief Reset the Key Manager peripheral */ +static inline void _key_mgr_ll_reset_register(void) +{ + PCR.km_conf.km_rst_en = 1; + PCR.km_conf.km_rst_en = 0; + // Wait for key manager to be ready + while (!PCR.km_conf.km_ready) { + }; + + while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { + }; + +} + +/// 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 key_mgr_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_reset_register(__VA_ARGS__) + +/* @brief Start the key manager at IDLE state */ +static inline void key_mgr_ll_start(void) +{ + REG_SET_BIT(KEYMNG_START_REG, KEYMNG_START); +} + +/* @brief Continue key manager operation at LOAD/GAIN state */ +static inline void key_mgr_ll_continue(void) +{ + REG_SET_BIT(KEYMNG_START_REG, KEYMNG_CONTINUE); +} + +/* @brief Enable or Disable the KEY_MGR interrupts */ +static inline void key_mgr_ll_configure_interrupt(const esp_key_mgr_interrupt_type_t intr, bool en) +{ + switch(intr) { + case ESP_KEY_MGR_INT_PREP_DONE: + REG_SET_FIELD(KEYMNG_INT_ENA_REG, KEYMNG_PREP_DONE_INT_ENA, en); + break; + case ESP_KEY_MGR_INT_PROC_DONE: + REG_SET_FIELD(KEYMNG_INT_ENA_REG, KEYMNG_PROC_DONE_INT_ENA, en); + break; + case ESP_KEY_MGR_INT_POST_DONE: + REG_SET_FIELD(KEYMNG_INT_ENA_REG, KEYMNG_POST_DONE_INT_ENA, en); + break; + default: + return; + } +} + +/* @brief Clear the KEY_MGR interrupts */ +static inline void key_mgr_ll_clear_int(const esp_key_mgr_interrupt_type_t intr) +{ + switch(intr) { + case ESP_KEY_MGR_INT_PREP_DONE: + REG_SET_FIELD(KEYMNG_INT_CLR_REG, KEYMNG_PREP_DONE_INT_CLR, 1); + break; + case ESP_KEY_MGR_INT_PROC_DONE: + REG_SET_FIELD(KEYMNG_INT_CLR_REG, KEYMNG_PROC_DONE_INT_CLR, 1); + break; + case ESP_KEY_MGR_INT_POST_DONE: + REG_SET_FIELD(KEYMNG_INT_CLR_REG, KEYMNG_POST_DONE_INT_CLR, 1); + break; + default: + return; + } +} + +/** + * @brief Set the key manager to use the software provided init key + */ +static inline void key_mgr_ll_use_sw_init_key(void) +{ + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_SW_INIT_KEY); +} + +/** + * @brief Configure the key manager key usage policy for a particular key type + * + */ +static inline void key_mgr_ll_set_key_usage(const esp_key_mgr_key_type_t key_type, const esp_key_mgr_key_usage_t key_usage) +{ + switch (key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + if (key_usage == ESP_KEY_MGR_USE_EFUSE_KEY) { + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_ECDSA); + } else { + REG_CLR_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_ECDSA); + } + break; + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + if (key_usage == ESP_KEY_MGR_USE_EFUSE_KEY) { + REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH); + } else { + REG_CLR_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH); + } + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return; + } +} + +static inline esp_key_mgr_key_usage_t key_mgr_ll_get_key_usage(esp_key_mgr_key_type_t key_type) +{ + switch (key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + return (esp_key_mgr_key_usage_t) (REG_GET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_ECDSA)); + break; + + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + return (esp_key_mgr_key_usage_t) (REG_GET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH)); + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return ESP_KEY_MGR_USAGE_INVALID; + } + return ESP_KEY_MGR_USAGE_INVALID; +} + +/** + * @brief Set the lock for the use_sw_init_key_reg + * After this lock has been set, + * The Key manager configuration about the use of software init key cannot be changed + */ +static inline void key_mgr_ll_lock_use_sw_init_key_reg(void) +{ + REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_SW_INIT_KEY_LOCK); +} + +/** + * @brief Set the lock for the use_sw_init_key_reg + * After this lock has been set, + * The Key manager configuration about whether to use a particular key from efuse or key manager cannot be changed. + */ +static inline void key_mgr_ll_lock_use_efuse_key_reg(esp_key_mgr_key_type_t key_type) +{ + switch(key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA); + break; + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_EFUSE_KEY_LOCK_FLASH); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + return; + } +} + +/* @brief Configure the key purpose to be used by the Key Manager for key generator operation */ +static inline void key_mgr_ll_set_key_purpose(const esp_key_mgr_key_purpose_t key_purpose) +{ + REG_SET_FIELD(KEYMNG_CONF_REG, KEYMNG_KEY_PURPOSE, key_purpose); +} + +/** + * @brief Configure the mode which is used by the Key Manager for the generator key deployment process + */ +static inline void key_mgr_ll_set_key_generator_mode(const esp_key_mgr_key_generator_mode_t mode) +{ + REG_SET_FIELD(KEYMNG_CONF_REG, KEYMNG_KGEN_MODE, mode); +} + +/** + * @brief Read the key manager process result + * @return 1 for Success + * 0 for failure + */ +static inline bool key_mgr_ll_is_result_success(void) +{ + return REG_GET_FIELD(KEYMNG_RESULT_REG, KEYMNG_PROC_RESULT); +} + +/** + * @brief Check if the deployed key is valid or not + * @return 1 for Success + * 0 for failure + */ +static inline bool key_mgr_ll_is_key_deployment_valid(const esp_key_mgr_key_type_t key_type) +{ + switch (key_type) { + + case ESP_KEY_MGR_ECDSA_KEY: + return REG_GET_FIELD(KEYMNG_KEY_VLD_REG, KEYMNG_KEY_ECDSA_VLD); + break; + + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + return REG_GET_FIELD(KEYMNG_KEY_VLD_REG, KEYMNG_KEY_FLASH_VLD); + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return 0; + } +} + +/* + * @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 + */ +static inline void key_mgr_ll_write_sw_init_key(const uint8_t *sw_init_key_buf, const size_t data_len) +{ + memcpy((uint8_t *)KEYMNG_SW_INIT_KEY_MEM, sw_init_key_buf, 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 + */ +static inline void key_mgr_ll_write_assist_info(const uint8_t *assist_info_buf, const size_t data_len) +{ + memcpy((uint8_t *)KEYMNG_ASSIST_INFO_MEM, assist_info_buf, 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 + */ +static inline void key_mgr_ll_read_assist_info( uint8_t *assist_info_buf) +{ + memcpy(assist_info_buf, (uint8_t *)KEYMNG_ASSIST_INFO_MEM, KEY_MGR_ASSIST_INFO_LEN); +} + +/* + * @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 + */ +static inline void key_mgr_ll_write_public_info(const uint8_t *public_info_buf, const size_t data_len) +{ + memcpy((uint8_t *)KEYMNG_PUBLIC_INFO_MEM, public_info_buf, 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 + */ +static inline void key_mgr_ll_read_public_info(uint8_t *public_info_buf, const size_t read_len) +{ + memcpy(public_info_buf, (uint8_t *)KEYMNG_PUBLIC_INFO_MEM, read_len); +} + +static inline bool key_mgr_ll_is_huk_valid(void) +{ + return REG_GET_FIELD(KEYMNG_HUK_VLD_REG, KEYMNG_HUK_VALID); +} + +/* @brief Set the XTS-AES (Flash Encryption) key length for the Key Manager */ +static inline void key_mgr_ll_set_xts_aes_key_len(const esp_key_mgr_xts_aes_key_len_t key_len) +{ + REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_FLASH_KEY_LEN, key_len); +} + +/* @brief Get the XTS-AES (Flash Encryption) key length for the Key Manager */ +static inline esp_key_mgr_xts_aes_key_len_t key_mgr_ll_get_xts_aes_key_len(void) +{ + return (esp_key_mgr_xts_aes_key_len_t) REG_GET_FIELD(KEYMNG_STATIC_REG, KEYMNG_FLASH_KEY_LEN); +} + +/** + * @brief Read the Key Manager date information + */ +static inline uint32_t key_mgr_ll_get_date_info(void) +{ + // Only the least significant 28 bits have desired information + return (uint32_t)(0x0FFFFFFF & REG_READ(KEYMNG_DATE_REG)); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h index 9a01d99830..c94ca97466 100644 --- a/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h +++ b/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h @@ -63,6 +63,14 @@ static inline __attribute__((always_inline)) void mspi_ll_enable_bus_clock(bool PCR.mspi_conf.mspi_clk_en = enable; } +/** + * Reset the MSPI clock + */ +static inline __attribute__((always_inline)) void _mspi_timing_ll_reset_mspi(void) +{ + PCR.mspi_conf.mspi_rst_en = 1; + PCR.mspi_conf.mspi_rst_en = 0; +} #ifdef __cplusplus } diff --git a/components/hal/esp32p4/include/hal/huk_hal.h b/components/hal/include/hal/huk_hal.h similarity index 96% rename from components/hal/esp32p4/include/hal/huk_hal.h rename to components/hal/include/hal/huk_hal.h index 796f2b8f94..e158f1fc66 100644 --- a/components/hal/esp32p4/include/hal/huk_hal.h +++ b/components/hal/include/hal/huk_hal.h @@ -3,7 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -// The HAL layer for Hardware Unique Key (HUK) Genarator +// The HAL layer for Hardware Unique Key (HUK) Generator #pragma once diff --git a/components/hal/esp32p4/include/hal/key_mgr_hal.h b/components/hal/include/hal/key_mgr_hal.h similarity index 94% rename from components/hal/esp32p4/include/hal/key_mgr_hal.h rename to components/hal/include/hal/key_mgr_hal.h index 3bed3fa3fd..8a3ca092dc 100644 --- a/components/hal/esp32p4/include/hal/key_mgr_hal.h +++ b/components/hal/include/hal/key_mgr_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,11 +37,11 @@ void key_mgr_hal_set_key_usage(const esp_key_mgr_key_type_t key_type, const esp_ */ 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 opearation */ +/* @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 deployement process + * @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); @@ -131,11 +131,11 @@ uint32_t key_mgr_hal_get_date_info(void); /** * @brief Set the Key Manager date information - * Only the least siginificant 28 bits shall be considered + * 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 +#endif /* SOC_KEY_MANAGER_SUPPORTED */ diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index e7456fe647..70fab9c675 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -1179,6 +1179,14 @@ config SOC_EFUSE_ECDSA_KEY bool default y +config SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY + bool + default y + +config SOC_KEY_MANAGER_FE_KEY_DEPLOY + bool + default y + config SOC_SECURE_BOOT_V2_ECC bool default y diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index bf0f144012..edafca6279 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -499,6 +499,10 @@ // #define SOC_EFUSE_DIS_ICACHE 1 #define SOC_EFUSE_ECDSA_KEY 1 +/*-------------------------- Key Manager CAPS----------------------------*/ +#define SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY 1 /*!< Key manager responsible to deploy ECDSA key */ +#define SOC_KEY_MANAGER_FE_KEY_DEPLOY 1 /*!< Key manager responsible to deploy Flash Encryption key */ + /*-------------------------- Secure Boot CAPS----------------------------*/ #define SOC_SECURE_BOOT_V2_ECC 1 #define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 diff --git a/components/soc/esp32c5/register/soc/keymng_reg.h b/components/soc/esp32c5/register/soc/keymng_reg.h index 48324b814c..66ab390373 100644 --- a/components/soc/esp32c5/register/soc/keymng_reg.h +++ b/components/soc/esp32c5/register/soc/keymng_reg.h @@ -147,6 +147,22 @@ extern "C" { #define KEYMNG_USE_EFUSE_KEY_M (KEYMNG_USE_EFUSE_KEY_V << KEYMNG_USE_EFUSE_KEY_S) #define KEYMNG_USE_EFUSE_KEY_V 0x0000001FU #define KEYMNG_USE_EFUSE_KEY_S 0 + +/* KEYMNG_USE_EFUSE_KEY_ECDSA : R/W ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Set this bit to choose efuse key instead of key manager deployed key for ecdsa.*/ +#define KEYMNG_USE_EFUSE_KEY_ECDSA (BIT(0)) +#define KEYMNG_USE_EFUSE_KEY_ECDSA_M ((KEYMNG_USE_EFUSE_KEY_ECDSA_V)<<(KEYMNG_USE_EFUSE_KEY_ECDSA_S)) +#define KEYMNG_USE_EFUSE_KEY_ECDSA_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_ECDSA_S 0 + +/* KEYMNG_USE_EFUSE_KEY_FLASH : R/W ;bitpos:[1] ;default: 1'd0 ; */ +/*description: Set this bit to choose efuse key instead of key manager deployed key for flash.*/ +#define KEYMNG_USE_EFUSE_KEY_FLASH (BIT(1)) +#define KEYMNG_USE_EFUSE_KEY_FLASH_M ((KEYMNG_USE_EFUSE_KEY_FLASH_V)<<(KEYMNG_USE_EFUSE_KEY_FLASH_S)) +#define KEYMNG_USE_EFUSE_KEY_FLASH_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_FLASH_S 1 + + /** KEYMNG_RND_SWITCH_CYCLE : R/W; bitpos: [9:5]; default: 15; * The core clock cycle number to sample one rng input data. Please set it bigger than * the clock cycle ratio: T_rng/T_km @@ -191,6 +207,23 @@ extern "C" { #define KEYMNG_USE_EFUSE_KEY_LOCK_M (KEYMNG_USE_EFUSE_KEY_LOCK_V << KEYMNG_USE_EFUSE_KEY_LOCK_S) #define KEYMNG_USE_EFUSE_KEY_LOCK_V 0x0000001FU #define KEYMNG_USE_EFUSE_KEY_LOCK_S 0 + +/* KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA : R/W1 ;bitpos:[0] ;default: 1'd0 ; */ +/*description: Write 1 to lock reg_use_efuse_key for esdsa*/ + +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA (BIT(0)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_M ((KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_V)<<(KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_S)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA_S 0 + +/* KEYMNG_USE_EFUSE_KEY_LOCK_FLASH : R/W1 ;bitpos:[1] ;default: 1'd0 ; */ +/*description: Write 1 to lock reg_use_efuse_key for FLASH*/ + +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH (BIT(1)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_M ((KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_V)<<(KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_S)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_LOCK_FLASH_S 1 + /** KEYMNG_RND_SWITCH_CYCLE_LOCK : R/W1; bitpos: [5]; default: 0; * Write 1 to lock reg_rnd_switch_cycle. */ From 82db0feab2d6e51556f0f76a46cffb677ed6017e Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 1 Oct 2024 22:10:57 +0530 Subject: [PATCH 2/3] fix(security): Update key manager specific initializations for esp32c5 --- .../include/esp_flash_encrypt.h | 2 ++ .../flash_encryption_secure_features.c | 34 +++++++------------ .../src/flash_encryption/flash_encrypt.c | 3 +- components/esp_security/src/init.c | 12 ++----- components/hal/ecdsa_hal.c | 12 +------ .../hal/esp32c5/include/hal/key_mgr_ll.h | 5 ++- .../include/hal/mspi_timing_tuning_ll.h | 7 ++-- 7 files changed, 27 insertions(+), 48 deletions(-) diff --git a/components/bootloader_support/include/esp_flash_encrypt.h b/components/bootloader_support/include/esp_flash_encrypt.h index e942d7f54d..efc061edf5 100644 --- a/components/bootloader_support/include/esp_flash_encrypt.h +++ b/components/bootloader_support/include/esp_flash_encrypt.h @@ -184,12 +184,14 @@ void esp_flash_encryption_init_checks(void); */ esp_err_t esp_flash_encryption_enable_secure_features(void); +#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY /** @brief Enable the key manager for flash encryption * * @return * - ESP_OK - On success */ esp_err_t esp_flash_encryption_enable_key_mgr(void); +#endif // CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY #endif /* BOOTLOADER_BUILD && CONFIG_SECURE_FLASH_ENC_ENABLED */ diff --git a/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c b/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c index 03af18a1db..ad90f306c0 100644 --- a/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c +++ b/components/bootloader_support/src/esp32c5/flash_encryption_secure_features.c @@ -11,9 +11,8 @@ #include "esp_efuse_table.h" #include "esp_log.h" #include "sdkconfig.h" -#include "soc/keymng_reg.h" -#include "soc/pcr_reg.h" -#include "soc/pcr_struct.h" +#include "hal/key_mgr_ll.h" +#include "hal/mspi_timing_tuning_ll.h" static __attribute__((unused)) const char *TAG = "flash_encrypt"; @@ -62,30 +61,21 @@ esp_err_t esp_flash_encryption_enable_secure_features(void) return ESP_OK; } -// TODO: Update to use LL APIs once key manager support added in IDF-8621 esp_err_t esp_flash_encryption_enable_key_mgr(void) { - // Set the force power down bit to 0 to enable key manager - PCR.km_pd_ctrl.km_mem_force_pd = 0; - // Reset the key manager - PCR.km_conf.km_clk_en = 1; - PCR.km_conf.km_rst_en = 1; - PCR.km_conf.km_rst_en = 0; + // Enable and reset key manager + // To suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV + int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused)); + key_mgr_ll_enable_bus_clock(true); + key_mgr_ll_enable_peripheral_clock(true); + key_mgr_ll_reset_register(); - // Wait for key manager to be ready - while (!PCR.km_conf.km_ready) { + while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { }; - // Wait for key manager state machine to be idle - while (REG_READ(KEYMNG_STATE_REG) != 0) { - }; - - // Set the key manager to use efuse key - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 2); - - // Reset MSPI to re-load the flash encryption key - REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); - REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); + // Force Key Manager to use eFuse key for XTS-AES operation + key_mgr_ll_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); + _mspi_timing_ll_reset_mspi(); return ESP_OK; } diff --git a/components/bootloader_support/src/flash_encryption/flash_encrypt.c b/components/bootloader_support/src/flash_encryption/flash_encrypt.c index 92bc72b21f..810cd36c2d 100644 --- a/components/bootloader_support/src/flash_encryption/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encryption/flash_encrypt.c @@ -258,8 +258,7 @@ esp_err_t esp_flash_encrypt_contents(void) REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1); #endif -// TODO: Remove C5 target config after key manager LL support- see IDF-8621 -#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY || CONFIG_IDF_TARGET_ESP32C5 +#if CONFIG_SOC_KEY_MANAGER_FE_KEY_DEPLOY esp_flash_encryption_enable_key_mgr(); #endif diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index d00d0e9647..d12e1fe326 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -20,23 +20,15 @@ __attribute__((unused)) static const char *TAG = "esp_security"; static void esp_key_mgr_init(void) { - // The following operation makes the Key Manager to use eFuse key for ECDSA and XTS-AES operation by default - // This is to keep the default behavior same as the other chips - // If the Key Manager configuration is already locked then following operation does not have any effect + // The following code initializes the key manager. #if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY || SOC_KEY_MANAGER_FE_KEY_DEPLOY // Enable key manager clock // Using ll APIs which do not require critical section _key_mgr_ll_enable_bus_clock(true); _key_mgr_ll_enable_peripheral_clock(true); - + _key_mgr_ll_reset_register(); while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { }; -#if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY - key_mgr_ll_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); -#endif -#if SOC_KEY_MANAGER_FE_KEY_DEPLOY - key_mgr_ll_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); -#endif #endif /* SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY || SOC_KEY_MANAGER_FE_KEY_DEPLOY */ } diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index 237a461f6d..bec830e391 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -14,13 +14,8 @@ #include "esp_random.h" #endif -// Need to remove in IDF-8621 -#if CONFIG_IDF_TARGET_ESP32C5 -#include "soc/keymng_reg.h" -#endif - #ifdef SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY -#include "hal/key_mgr_hal.h" +#include "hal/key_mgr_ll.h" #endif #define ECDSA_HAL_P192_COMPONENT_LEN 24 @@ -32,11 +27,6 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) if (conf->use_km_key == 0) { efuse_hal_set_ecdsa_key(conf->efuse_key_blk); -// Need to remove in IDF-8621 -#if CONFIG_IDF_TARGET_ESP32C5 - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 1); -#endif - #if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY // Force Key Manager to use eFuse key for XTS-AES operation key_mgr_ll_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); diff --git a/components/hal/esp32c5/include/hal/key_mgr_ll.h b/components/hal/esp32c5/include/hal/key_mgr_ll.h index 1076555f02..f46c7c2e4c 100644 --- a/components/hal/esp32c5/include/hal/key_mgr_ll.h +++ b/components/hal/esp32c5/include/hal/key_mgr_ll.h @@ -67,7 +67,10 @@ static inline void _key_mgr_ll_enable_peripheral_clock(bool enable) #define key_mgr_ll_enable_peripheral_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_peripheral_clock(__VA_ARGS__) /** - * @brief Reset the Key Manager peripheral */ + * @brief Reset the Key Manager peripheral + * Note: Please use key_mgr_ll_reset_register which requires the critical section + * and do not use _key_mgr_ll_reset_register + */ static inline void _key_mgr_ll_reset_register(void) { PCR.km_conf.km_rst_en = 1; diff --git a/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h b/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h index c94ca97466..2d4416657f 100644 --- a/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h +++ b/components/hal/esp32c5/include/hal/mspi_timing_tuning_ll.h @@ -68,8 +68,11 @@ static inline __attribute__((always_inline)) void mspi_ll_enable_bus_clock(bool */ static inline __attribute__((always_inline)) void _mspi_timing_ll_reset_mspi(void) { - PCR.mspi_conf.mspi_rst_en = 1; - PCR.mspi_conf.mspi_rst_en = 0; + PCR.mspi_clk_conf.mspi_axi_rst_en = 1; + PCR.mspi_clk_conf.mspi_axi_rst_en = 0; + // Wait for mspi to be ready + while (!PCR.mspi_conf.mspi_ready) { + }; } #ifdef __cplusplus From b0664a6f2ee54594505f2624a82deb3b66a099b5 Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Tue, 1 Oct 2024 23:03:07 +0530 Subject: [PATCH 3/3] fix(hal): Fix key_mgr_ll_reset_register API the key_mgr_ll_reset_register API now waits till key manager state is IDLE --- .../hal/esp32p4/include/hal/key_mgr_ll.h | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/components/hal/esp32p4/include/hal/key_mgr_ll.h b/components/hal/esp32p4/include/hal/key_mgr_ll.h index 15923a67ff..3aa13bc363 100644 --- a/components/hal/esp32p4/include/hal/key_mgr_ll.h +++ b/components/hal/esp32p4/include/hal/key_mgr_ll.h @@ -54,19 +54,35 @@ static inline void _key_mgr_ll_enable_peripheral_clock(bool enable) #define key_mgr_ll_enable_peripheral_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_enable_peripheral_clock(__VA_ARGS__) /** - * @brief Reset the Key Manager peripheral */ -static inline void key_mgr_ll_reset_register(void) + * @brief Read state of Key Manager + * + * @return esp_key_mgr_state_t + */ +static inline esp_key_mgr_state_t key_mgr_ll_get_state(void) +{ + return (esp_key_mgr_state_t) REG_GET_FIELD(KEYMNG_STATE_REG, KEYMNG_STATE); +} + +/** + * @brief Reset the Key Manager peripheral + * Note: Please use key_mgr_ll_reset_register which requires the critical section + * and do not use _key_mgr_ll_reset_register + */ +static inline void _key_mgr_ll_reset_register(void) { HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_km = 1; HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_km = 0; // Clear reset on parent crypto, otherwise Key Manager is held in reset HP_SYS_CLKRST.hp_rst_en2.reg_rst_en_crypto = 0; + + while (key_mgr_ll_get_state() != ESP_KEY_MGR_STATE_IDLE) { + }; } /// 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 key_mgr_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; key_mgr_ll_reset_register(__VA_ARGS__) +#define key_mgr_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; _key_mgr_ll_reset_register(__VA_ARGS__) /* @brief Start the key manager at IDLE state */ static inline void key_mgr_ll_start(void) @@ -323,16 +339,6 @@ static inline esp_key_mgr_xts_aes_key_len_t key_mgr_ll_get_xts_aes_key_len(void) return (esp_key_mgr_xts_aes_key_len_t) REG_GET_FIELD(KEYMNG_STATIC_REG, KEYMNG_XTS_AES_KEY_LEN); } -/** - * @brief Read state of Key Manager - * - * @return esp_key_mgr_state_t - */ -static inline esp_key_mgr_state_t key_mgr_ll_get_state(void) -{ - return (esp_key_mgr_state_t) REG_GET_FIELD(KEYMNG_STATE_REG, KEYMNG_STATE); -} - /** * @brief Read the Key Manager date information */