diff --git a/components/bootloader_support/src/flash_encryption/flash_encrypt.c b/components/bootloader_support/src/flash_encryption/flash_encrypt.c index 8bd1352b73..bf6f629648 100644 --- a/components/bootloader_support/src/flash_encryption/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encryption/flash_encrypt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,8 +16,8 @@ #include "esp_log.h" #include "hal/wdt_hal.h" -#if CONFIG_IDF_TARGET_ESP32P4 //TODO-IDF-7925 -#include "soc/keymng_reg.h" +#if SOC_KEY_MANAGER_SUPPORTED +#include "hal/key_mgr_hal.h" #endif #ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK @@ -214,12 +214,6 @@ static esp_err_t check_and_generate_encryption_keys(void) } ESP_LOGI(TAG, "Using pre-loaded flash encryption key in efuse"); } - -#if CONFIG_IDF_TARGET_ESP32P4 //TODO - IDF-7925 - // Force Key Manager to use eFuse key for XTS-AES operation - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 2); -#endif - return ESP_OK; } diff --git a/components/esp_hw_support/esp_key_mgr.c b/components/esp_hw_support/esp_key_mgr.c index 57930d9555..6b67decd90 100644 --- a/components/esp_hw_support/esp_key_mgr.c +++ b/components/esp_hw_support/esp_key_mgr.c @@ -1,25 +1,93 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ // The Hardware Support layer for Key manager -#include "hal/key_mgr_types.h" -#include "hal/key_mgr_hal.h" -#include "hal/huk_types.h" -#include "hal/huk_hal.h" +#include +#include +#include "assert.h" #include "esp_key_mgr.h" #include "esp_private/periph_ctrl.h" -#include "hal/key_mgr_ll.h" +#include "esp_crypto_lock.h" #include "esp_log.h" #include "esp_err.h" -#include "assert.h" -#include "string.h" +#include "esp_random.h" #include "esp_heap_caps.h" +#include "esp_rom_crc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "hal/key_mgr_types.h" +#include "hal/key_mgr_hal.h" +#include "hal/key_mgr_ll.h" +#include "hal/huk_types.h" +#include "hal/huk_hal.h" +#include "rom/key_mgr.h" + +#if CONFIG_LOG_DEFAULT_LEVEL_VERBOSE +#include "soc/huk_reg.h" +#include "soc/keymng_reg.h" +#endif + +static const char *TAG = "esp_key_mgr"; #define KEY_MANAGER_RCC_ATOMIC() PERIPH_RCC_ATOMIC() -static const char *TAG = "esp_key_mgr"; +static _lock_t s_key_mgr_ecdsa_key_lock; +static _lock_t s_key_mgr_xts_aes_key_lock; + +ESP_STATIC_ASSERT(sizeof(esp_key_mgr_key_recovery_info_t) == sizeof(struct huk_key_block), "Size of esp_key_mgr_key_recovery_info_t should match huk_key_block (from ROM)"); + +ESP_STATIC_ASSERT(sizeof(esp_key_mgr_key_info_t) == sizeof(struct key_info), "Size of esp_key_mgr_key_info_t should match key_info (from ROM)"); + +ESP_STATIC_ASSERT(sizeof(esp_key_mgr_huk_info_t) == sizeof(struct huk_info), "Size of esp_key_mgr_huk_info_t should match huk_info (from ROM)"); + +static void esp_key_mgr_acquire_key_lock(esp_key_mgr_key_type_t key_type) +{ + switch (key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + _lock_acquire(&s_key_mgr_ecdsa_key_lock); + break; + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + _lock_acquire(&s_key_mgr_xts_aes_key_lock); + break; + } +} + +static void esp_key_mgr_release_key_lock(esp_key_mgr_key_type_t key_type) +{ + switch (key_type) { + case ESP_KEY_MGR_ECDSA_KEY: + _lock_release(&s_key_mgr_xts_aes_key_lock); + break; + case ESP_KEY_MGR_XTS_AES_128_KEY: + case ESP_KEY_MGR_XTS_AES_256_KEY: + _lock_release(&s_key_mgr_ecdsa_key_lock); + break; + } +} + +static void esp_key_mgr_acquire_hardware(void) +{ + esp_crypto_key_manager_lock_acquire(); + // Reset the Key Manager Clock + KEY_MANAGER_RCC_ATOMIC() { + key_mgr_ll_enable_bus_clock(true); + key_mgr_ll_reset_register(); + } +} + +static void esp_key_mgr_release_hardware(void) +{ + esp_crypto_key_manager_lock_release(); + // Reset the Key Manager Clock + KEY_MANAGER_RCC_ATOMIC() { + key_mgr_ll_enable_bus_clock(false); + key_mgr_ll_reset_register(); + } +} + static void key_mgr_wait_for_state(esp_key_mgr_state_t state) { while (key_mgr_hal_get_state() != state) { @@ -27,220 +95,617 @@ static void key_mgr_wait_for_state(esp_key_mgr_state_t state) } } -esp_err_t esp_key_mgr_deploy_key_in_aes_mode(esp_key_mgr_aes_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info) +typedef struct aes_deploy { + esp_key_mgr_key_purpose_t key_purpose; + const uint8_t *k1_encrypted; + const esp_key_mgr_aes_key_config_t *key_config; + esp_key_mgr_key_recovery_info_t *key_info; +} aes_deploy_config_t; + +static void check_huk_risk_level(void) { - ESP_LOGI(TAG, "Key Deployment"); - // Reset the Key Manager Clock - KEY_MANAGER_RCC_ATOMIC() { - key_mgr_ll_enable_bus_clock(true); - key_mgr_ll_reset_register(); + uint8_t huk_risk_level = huk_hal_get_risk_level(); + if (huk_risk_level > KEY_MGR_HUK_RISK_ALERT_LEVEL) { + ESP_LOGE(TAG, "HUK Risk level too high (level %d)\n" + "It is recommended to immediately regenerate HUK in order" + "to avoid permenantly losing the deployed keys", huk_risk_level); + } else { + ESP_LOGI(TAG, "HUK Risk level - %d within acceptable limit (%d)", huk_risk_level, KEY_MGR_HUK_RISK_ALERT_LEVEL); } - key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); +} + +static bool check_huk_validity(const esp_key_mgr_huk_info_t *huk_info) +{ + uint32_t calc_crc = esp_rom_crc32_le(0, huk_info->info, KEY_MGR_HUK_INFO_SIZE); + if (calc_crc != huk_info->crc) { + ESP_LOGE(TAG, "Calculated CRC for HUK %lX does not match with %lX", calc_crc, huk_info->crc); + return false; + } + return true; +} + +static bool check_key_info_validity(const esp_key_mgr_key_info_t *key_info) +{ + uint32_t calc_crc = esp_rom_crc32_le(0, key_info->info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + if (calc_crc != key_info->crc) { + ESP_LOGE(TAG, "Calculated CRC for Key info %lX does not match with %lX", calc_crc, key_info->crc); + return false; + } + return true; +} + +typedef struct { + bool use_pre_generated_huk_info; + const esp_key_mgr_huk_info_t *pre_generated_huk_info; + esp_key_mgr_huk_info_t *huk_recovery_info; +} huk_deploy_config_t; + +static esp_err_t deploy_huk(huk_deploy_config_t *config) +{ + esp_err_t esp_ret = ESP_FAIL; uint8_t *huk_recovery_info = (uint8_t *) heap_caps_calloc(1, KEY_MGR_HUK_INFO_SIZE, MALLOC_CAP_INTERNAL); if (!huk_recovery_info) { return ESP_ERR_NO_MEM; } + + if (config->use_pre_generated_huk_info) { + // If HUK info is provided then recover the HUK from given info + check_huk_risk_level(); + if (!check_huk_validity(config->pre_generated_huk_info)) { + ESP_LOGE(TAG, "HUK info is not valid"); + heap_caps_free(huk_recovery_info); + return ESP_ERR_INVALID_ARG; + } + memcpy(huk_recovery_info, config->pre_generated_huk_info->info, KEY_MGR_HUK_INFO_SIZE); + ESP_LOGI(TAG, "Recovering key from given HUK recovery info"); + esp_ret = huk_hal_configure(ESP_HUK_MODE_RECOVERY, huk_recovery_info); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to recover HUK"); + heap_caps_free(huk_recovery_info); + return esp_ret; + } + // Copy the pre generated huk info in the output key recovery info + memcpy(config->huk_recovery_info->info, huk_recovery_info, KEY_MGR_HUK_INFO_SIZE); + config->huk_recovery_info->crc = config->pre_generated_huk_info->crc; + } else { + // Generate new HUK and corresponding HUK info + ESP_LOGI(TAG, "Generating new HUK"); + esp_ret = huk_hal_configure(ESP_HUK_MODE_GENERATION, huk_recovery_info); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to generate HUK"); + heap_caps_free(huk_recovery_info); + return esp_ret; + } + memcpy(config->huk_recovery_info->info, huk_recovery_info, KEY_MGR_HUK_INFO_SIZE); + config->huk_recovery_info->crc = esp_rom_crc32_le(0, huk_recovery_info, KEY_MGR_HUK_INFO_SIZE); + } + + if (!key_mgr_hal_is_huk_valid()) { + ESP_LOGE(TAG, "HUK is invalid"); + heap_caps_free(huk_recovery_info); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "HUK recovery/generation successfull"); + ESP_LOG_BUFFER_HEX_LEVEL("HUK INFO", huk_recovery_info, KEY_MGR_HUK_INFO_SIZE, ESP_LOG_DEBUG); + // Free the local buffer for huk recovery info + heap_caps_free(huk_recovery_info); + return ESP_OK; +} + +static esp_err_t key_mgr_deploy_key_aes_mode(aes_deploy_config_t *config) +{ + esp_err_t esp_ret = ESP_FAIL; + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); + if (!key_mgr_hal_is_huk_valid()) { + // For purpose ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2 this part shall be already executed + huk_deploy_config_t huk_deploy_config; + huk_deploy_config.use_pre_generated_huk_info = config->key_config->use_pre_generated_huk_info; + huk_deploy_config.pre_generated_huk_info = &config->key_config->huk_info; + huk_deploy_config.huk_recovery_info = &config->key_info->huk_info; + esp_ret = deploy_huk(&huk_deploy_config); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } + ESP_LOGI(TAG, "HUK deployed is Valid"); + + // STEP 1: Init Step + // Set mode + key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_AES); + uint8_t *key_recovery_info = (uint8_t *) heap_caps_calloc(1, KEY_MGR_KEY_RECOVERY_INFO_SIZE, MALLOC_CAP_INTERNAL); if (!key_recovery_info) { return ESP_ERR_NO_MEM; } + // Set key purpose (XTS/ECDSA) + ESP_LOGI(TAG, "purpose = %d", config->key_purpose); + key_mgr_hal_set_key_purpose(config->key_purpose); - if (key_config->huk_info && key_config->huk_info_size) { - if (key_config->huk_info_size != KEY_MGR_HUK_INFO_SIZE) { - ESP_LOGE(TAG, "Invalid HUK info given"); - return ESP_ERR_INVALID_ARG; - } - ESP_LOGI(TAG, "Recovering key from given HUK recovery info"); - // If HUK info is provided then recover the HUK from given info - huk_hal_configure(ESP_HUK_MODE_RECOVERY, key_config->huk_info); - } else { - // Generate new HUK and corresponding HUK info - ESP_LOGI(TAG, "Generating new HUK"); - huk_hal_configure(ESP_HUK_MODE_GENERATION, huk_recovery_info); + // Set key length for XTS-AES key + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) config->key_config->key_type; + + if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_256); + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_512); } - ESP_LOGI(TAG, "HUK generated successfully"); - // Configure deployment mode to AES - key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_AES); - - // Set key purpose (XTS/ECDSA) - key_mgr_hal_set_key_purpose(key_config->key_purpose); - - if (key_config->use_sw_init_key) { + if (config->key_config->use_pre_generated_sw_init_key) { key_mgr_hal_use_sw_init_key(); } key_mgr_hal_start(); key_mgr_hal_continue(); + // Step 2: Load phase key_mgr_wait_for_state(ESP_KEY_MGR_STATE_LOAD); - if (key_config->use_sw_init_key) { - assert(key_config->sw_init_key_size == KEY_MGR_SW_INIT_KEY_SIZE); - key_mgr_hal_write_sw_init_key(key_config->sw_init_key, key_config->sw_init_key_size); + if (config->key_config->use_pre_generated_sw_init_key) { + key_mgr_hal_write_sw_init_key(config->key_config->sw_init_key, KEY_MGR_SW_INIT_KEY_SIZE); } + ESP_LOG_BUFFER_HEX_LEVEL("SW_INIT_KEY", config->key_config->sw_init_key, KEY_MGR_SW_INIT_KEY_SIZE, ESP_LOG_DEBUG); + ESP_LOGI(TAG, "Writing Information into Key Manager Registers"); - key_mgr_hal_write_assist_info(key_config->k2_info, KEY_MGR_K2_INFO_SIZE); - key_mgr_hal_write_public_info(key_config->k1_encrypted, KEY_MGR_K1_ENCRYPTED_SIZE); + key_mgr_hal_write_assist_info(config->key_config->k2_info, KEY_MGR_K2_INFO_SIZE); + ESP_LOG_BUFFER_HEX_LEVEL("K2_INFO", config->key_config->k2_info, KEY_MGR_K2_INFO_SIZE, ESP_LOG_DEBUG); + key_mgr_hal_write_public_info(config->k1_encrypted, KEY_MGR_K1_ENCRYPTED_SIZE); + ESP_LOG_BUFFER_HEX_LEVEL("K1_ENCRYPTED", config->k1_encrypted, KEY_MGR_K1_ENCRYPTED_SIZE, ESP_LOG_INFO); key_mgr_hal_continue(); + // Step 3: Gain phase key_mgr_wait_for_state(ESP_KEY_MGR_STATE_GAIN); key_mgr_hal_read_public_info(key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); - ESP_LOG_BUFFER_HEX_LEVEL("HUK INFO", huk_recovery_info, KEY_MGR_HUK_INFO_SIZE, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEX_LEVEL("KEY_MGR KEY INFO", key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEX_LEVEL("KEY_RECOVERY_INFO", key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE, ESP_LOG_DEBUG); - //TODO - check if HUK is valid just after it is generated - if (!key_mgr_hal_is_huk_valid()) { - ESP_LOGE(TAG, "HUK is invalid"); - // TODO - define error code - return ESP_FAIL; + if (config->key_purpose != ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1) { + if (!key_mgr_hal_is_key_deployment_valid(config->key_config->key_type)) { + ESP_LOGE(TAG, "Key deployment is not valid"); + heap_caps_free(key_recovery_info); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Key deployment valid"); } - ESP_LOGI(TAG, "HUK deplpoyed is Valid"); - - if (!key_mgr_hal_is_key_deployment_valid(key_config->key_type)) { - ESP_LOGE(TAG, "Key deployment is not valid"); - // Todo - Define respective error code; - return ESP_FAIL; - } - ESP_LOGI(TAG, "Key deployment valid"); // Wait till Key Manager deployment is complete key_mgr_hal_continue(); key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); - //memcpy(&key_info->huk_recovery_info[0], huk_recovery_info, KEY_MGR_HUK_INFO_SIZE); - //memcpy(&key_info->key_recovery_info[0], key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); - key_info->key_purpose = key_config->key_purpose; + if (config->key_purpose == ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2) { + memcpy(config->key_info->key_info[1].info, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + config->key_info->key_info[1].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + + } else { + memcpy(config->key_info->key_info[0].info, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + config->key_info->key_info[0].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + } heap_caps_free(key_recovery_info); - heap_caps_free(huk_recovery_info); - key_mgr_hal_set_key_usage(ESP_KEY_MGR_XTS_KEY, ESP_KEY_MGR_USE_OWN_KEY); + + return ESP_OK; +} + +esp_err_t esp_key_mgr_deploy_key_in_aes_mode(const esp_key_mgr_aes_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_recovery_info) +{ + ESP_LOGI(TAG, "Key deployment in AES mode"); + + aes_deploy_config_t aes_deploy_config; + aes_deploy_config.key_config = key_config; + aes_deploy_config.key_info = key_recovery_info; + aes_deploy_config.k1_encrypted = key_config->k1_encrypted[0]; + + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) key_config->key_type; + if (key_type == ESP_KEY_MGR_ECDSA_KEY) { + aes_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_ECDSA; + } else if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + aes_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_128; + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + aes_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1; + } else { + ESP_LOGE(TAG, "Invalid key type"); + return ESP_ERR_INVALID_ARG; + } + + esp_key_mgr_acquire_hardware(); + + esp_err_t esp_ret = key_mgr_deploy_key_aes_mode(&aes_deploy_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Key deployment in AES mode failed"); + } + + if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + aes_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2; + aes_deploy_config.k1_encrypted = key_config->k1_encrypted[1]; + esp_ret = key_mgr_deploy_key_aes_mode(&aes_deploy_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Key deployment in AES mode failed"); + } + } + + // Set the Key Manager Static Register to use own key for the respective key type + key_mgr_hal_set_key_usage(key_type, ESP_KEY_MGR_USE_OWN_KEY); + KEY_MANAGER_RCC_ATOMIC() { key_mgr_ll_enable_bus_clock(false); key_mgr_ll_reset_register(); } - return ESP_OK; + return esp_ret; } -esp_err_t esp_key_mgr_recover_key(esp_key_mgr_key_recovery_info_t *key_recovery_info) +typedef struct key_recovery_config { + esp_key_mgr_key_purpose_t key_purpose; + esp_key_mgr_key_recovery_info_t *key_recovery_info; +} key_recovery_config_t; + +static esp_err_t key_mgr_recover_key(key_recovery_config_t *config) { - KEY_MANAGER_RCC_ATOMIC() { - key_mgr_ll_enable_bus_clock(true); - key_mgr_ll_reset_register(); + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); + if (!check_huk_validity(&config->key_recovery_info->huk_info)) { + ESP_LOGE(TAG, "HUK info is not valid"); + return ESP_ERR_INVALID_ARG; + } + ESP_LOGD(TAG, "HUK info valid"); + + if (!key_mgr_hal_is_huk_valid()) { + check_huk_risk_level(); + esp_err_t esp_ret = huk_hal_configure(ESP_HUK_MODE_RECOVERY, config->key_recovery_info->huk_info.info); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to recover HUK"); + return ESP_FAIL; + } + if (!key_mgr_hal_is_huk_valid()) { + ESP_LOGE(TAG, "HUK is invalid"); + // TODO - define error code + return ESP_FAIL; + } + ESP_LOGI(TAG, "HUK deployed is Valid"); + ESP_LOG_BUFFER_HEX_LEVEL("HUK INFO", config->key_recovery_info->huk_info.info, KEY_MGR_HUK_INFO_SIZE, ESP_LOG_DEBUG); } - key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); - huk_hal_configure(ESP_HUK_MODE_RECOVERY, key_recovery_info->huk_recovery_info); - if (key_mgr_hal_is_huk_valid()) { - ESP_LOGD(TAG, "HUK is invalid"); - // TODO - define error code - return ESP_FAIL; + key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_RECOVER); + + // Set AES-XTS key len + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) config->key_recovery_info->key_type; + if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_256); + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_512); } - ESP_LOGI(TAG, "purpose = %d", key_recovery_info->key_purpose); - key_mgr_hal_set_key_purpose(key_recovery_info->key_purpose); + + key_mgr_hal_set_key_purpose(config->key_purpose); key_mgr_hal_start(); key_mgr_hal_continue(); key_mgr_wait_for_state(ESP_KEY_MGR_STATE_LOAD); - key_mgr_hal_write_assist_info(key_recovery_info->huk_recovery_info, KEY_MGR_HUK_INFO_SIZE); + if (config->key_purpose == ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2) { + if (!check_key_info_validity(&config->key_recovery_info->key_info[1])) { + ESP_LOGE(TAG, "Key info not valid"); + return ESP_FAIL; + } + key_mgr_hal_write_assist_info(config->key_recovery_info->key_info[1].info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + } else { + if (!check_key_info_validity(&config->key_recovery_info->key_info[0])) { + ESP_LOGE(TAG, "Key info not valid"); + return ESP_FAIL; + } + key_mgr_hal_write_assist_info(config->key_recovery_info->key_info[0].info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + ESP_LOG_BUFFER_HEX_LEVEL("RECOVERY_INFO", config->key_recovery_info->key_info[0].info, KEY_MGR_KEY_RECOVERY_INFO_SIZE, ESP_LOG_INFO); + } + key_mgr_hal_continue(); key_mgr_wait_for_state(ESP_KEY_MGR_STATE_GAIN); - if (!key_mgr_hal_is_key_deployment_valid(key_recovery_info->key_type)) { - ESP_LOGD(TAG, "Key deployment is not valid"); - // Todo - Define respective error code; - return ESP_FAIL; + if (config->key_purpose != ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1) { + if (!key_mgr_hal_is_key_deployment_valid(config->key_recovery_info->key_type)) { + ESP_LOGD(TAG, "Key deployment is not valid"); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Key Recovery valid"); } - ESP_LOGI(TAG, "Key deployment valid"); key_mgr_hal_continue(); key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); - KEY_MANAGER_RCC_ATOMIC() { - key_mgr_ll_enable_bus_clock(false); - key_mgr_ll_reset_register(); - } return ESP_OK; } -esp_err_t esp_key_mgr_deploy_key_in_ecdh0_mode(esp_key_mgr_ecdh0_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info) +esp_err_t esp_key_mgr_activate_key(esp_key_mgr_key_recovery_info_t *key_recovery_info) { - ESP_LOGI(TAG, "Key Deployment"); - // Reset the Key Manager Clock - KEY_MANAGER_RCC_ATOMIC() { - key_mgr_ll_enable_bus_clock(true); - key_mgr_ll_reset_register(); + esp_key_mgr_key_purpose_t key_purpose; + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) key_recovery_info->key_type; + if (key_type == ESP_KEY_MGR_ECDSA_KEY) { + key_purpose = ESP_KEY_MGR_KEY_PURPOSE_ECDSA; + } else if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_128; + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1; + } else { + ESP_LOGE(TAG, "Invalid key type"); + return ESP_ERR_INVALID_ARG; + } + esp_err_t esp_ret = ESP_FAIL; + esp_key_mgr_acquire_key_lock(key_type); + key_recovery_config_t key_recovery_config; + key_recovery_config.key_recovery_info = key_recovery_info; + key_recovery_config.key_purpose = key_purpose; + + esp_key_mgr_acquire_hardware(); + + esp_ret = key_mgr_recover_key(&key_recovery_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to recover key"); + goto cleanup; } - key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); - uint8_t *huk_recovery_info = (uint8_t *) heap_caps_calloc(1, KEY_MGR_HUK_INFO_SIZE, MALLOC_CAP_INTERNAL); - if (!huk_recovery_info) { - return ESP_ERR_NO_MEM; + if (key_recovery_info->key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_recovery_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2; + esp_ret = key_mgr_recover_key(&key_recovery_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to recover key"); + goto cleanup; + } } + + // Set the Key Manager Static Register to use own key for the respective key type + key_mgr_hal_set_key_usage(key_recovery_info->key_type, ESP_KEY_MGR_USE_OWN_KEY); + +cleanup: + + esp_key_mgr_release_hardware(); + return esp_ret; +} + +esp_err_t esp_key_mgr_deactivate_key(esp_key_mgr_key_type_t key_type) +{ + esp_key_mgr_release_key_lock(key_type); + esp_key_mgr_acquire_hardware(); + esp_key_mgr_release_hardware(); + return ESP_OK; +} + +typedef struct ecdh0_config { + esp_key_mgr_key_purpose_t key_purpose; + const esp_key_mgr_ecdh0_key_config_t *key_config; + esp_key_mgr_key_recovery_info_t *key_info; + uint8_t *ecdh0_key_info; +} ecdh0_deploy_config_t; + +static esp_err_t key_mgr_deploy_key_ecdh0_mode(ecdh0_deploy_config_t *config) +{ + esp_err_t esp_ret = ESP_FAIL; + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); + + if (!key_mgr_hal_is_huk_valid()) { + // For purpose ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2 this part shall be already executed + huk_deploy_config_t huk_deploy_config; + huk_deploy_config.use_pre_generated_huk_info = config->key_config->use_pre_generated_huk_info; + huk_deploy_config.pre_generated_huk_info = &config->key_config->huk_info; + huk_deploy_config.huk_recovery_info = &config->key_info->huk_info; + esp_ret = deploy_huk(&huk_deploy_config); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } + ESP_LOGI(TAG, "HUK deployed is Valid"); + uint8_t *key_recovery_info = (uint8_t *) heap_caps_calloc(1, KEY_MGR_KEY_RECOVERY_INFO_SIZE, MALLOC_CAP_INTERNAL); if (!key_recovery_info) { return ESP_ERR_NO_MEM; } - if (key_config->huk_info && key_config->huk_info_size) { - if (key_config->huk_info_size != KEY_MGR_HUK_INFO_SIZE) { - ESP_LOGE(TAG, "Invalid HUK info given"); - return ESP_ERR_INVALID_ARG; - } - ESP_LOGI(TAG, "Recovering key from given HUK recovery info"); - // If HUK info is provided then recover the HUK from given info - huk_hal_configure(ESP_HUK_MODE_RECOVERY, key_config->huk_info); - } else { - // Generate new HUK and corresponding HUK info - ESP_LOGI(TAG, "Generating new HUK"); - huk_hal_configure(ESP_HUK_MODE_GENERATION, huk_recovery_info); - } + // Step 1 : Initialization + // Configure deployment mode to ECDH0 + key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_ECDH0); - ESP_LOGI(TAG, "HUK generated successfully"); - // Configure deployment mode to AES - key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_AES); + // Set AES-XTS key len + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) config->key_config->key_type; + if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_256); + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_512); + } // Set key purpose (XTS/ECDSA) - key_mgr_hal_set_key_purpose(key_config->key_purpose); + key_mgr_hal_set_key_purpose(config->key_purpose); + key_mgr_hal_start(); + key_mgr_hal_continue(); - if (key_config->use_sw_init_key) { - key_mgr_hal_use_sw_init_key(); + // Step 2: Load phase + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_LOAD); + ESP_LOGD(TAG, "Writing Information into Key Manager Registers"); + key_mgr_hal_write_public_info(config->key_config->k1_G, KEY_MGR_ECDH0_INFO_SIZE); + key_mgr_hal_continue(); + + // Step 3: Gain phase + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_GAIN); + key_mgr_hal_read_public_info(key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + key_mgr_hal_read_assist_info(config->ecdh0_key_info); + ESP_LOG_BUFFER_HEX_LEVEL("KEY_MGR KEY INFO", key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE, ESP_LOG_DEBUG); + + ESP_LOGI(TAG, "HUK deplpoyed is Valid"); + + if (config->key_purpose != ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1) { + if (!key_mgr_hal_is_key_deployment_valid(config->key_config->key_type)) { + ESP_LOGE(TAG, "Key deployment is not valid"); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Key deployment valid"); } + // Wait till Key Manager deployment is complete + key_mgr_hal_continue(); + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); + if (config->key_purpose == ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2) { + memcpy(config->key_info->key_info[1].info, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + config->key_info->key_info[1].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + + } else { + memcpy(config->key_info->key_info[0].info, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + config->key_info->key_info[0].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + } + + config->key_info->key_type = config->key_config->key_type; + heap_caps_free(key_recovery_info); + return ESP_OK; +} + +esp_err_t esp_key_mgr_deploy_key_in_ecdh0_mode(const esp_key_mgr_ecdh0_key_config_t *key_config, + esp_key_mgr_key_recovery_info_t *key_info, esp_key_mgr_ecdh0_info_t *ecdh0_key_info) +{ + ESP_LOGI(TAG, "Key Deployment in ECDH0 mode"); + esp_key_mgr_key_purpose_t key_purpose; + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) key_config->key_type; + + ecdh0_deploy_config_t ecdh0_deploy_config; + ecdh0_deploy_config.key_config = key_config; + ecdh0_deploy_config.key_info = key_info; + + if (key_type == ESP_KEY_MGR_ECDSA_KEY) { + ecdh0_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_ECDSA; + ecdh0_deploy_config.ecdh0_key_info = ecdh0_key_info->k2_G[0]; + } else if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + ecdh0_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_128; + ecdh0_deploy_config.ecdh0_key_info = ecdh0_key_info->k2_G[0]; + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + ecdh0_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1; + ecdh0_deploy_config.ecdh0_key_info = ecdh0_key_info->k2_G[0]; + } else { + ESP_LOGE(TAG, "Invalid key type"); + return ESP_ERR_INVALID_ARG; + } + + esp_key_mgr_acquire_hardware(); + + esp_err_t esp_ret = key_mgr_deploy_key_ecdh0_mode(&ecdh0_deploy_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to deploy key in ECDH0 mode"); + } + + if (key_config->key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2; + ecdh0_deploy_config.key_purpose = key_purpose; + ecdh0_deploy_config.ecdh0_key_info = ecdh0_key_info->k2_G[1]; + esp_ret = key_mgr_deploy_key_ecdh0_mode(&ecdh0_deploy_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to deploy key in ECDH0 mode"); + } + } + + // Set the Key Manager Static Register to use own key for the respective key type + key_mgr_hal_set_key_usage(key_type, ESP_KEY_MGR_USE_OWN_KEY); + + esp_key_mgr_release_hardware(); + + return ESP_OK; +} + +typedef struct random_deploy { + esp_key_mgr_key_purpose_t key_purpose; + const esp_key_mgr_random_key_config_t *key_config; + esp_key_mgr_key_recovery_info_t *key_info; +} random_deploy_config_t; + +static esp_err_t key_mgr_deploy_key_random_mode(random_deploy_config_t *config) +{ + esp_err_t esp_ret = ESP_FAIL; + key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); + if (!key_mgr_hal_is_huk_valid()) { + // For purpose ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2 this part shall be already executed + huk_deploy_config_t huk_deploy_config; + huk_deploy_config.use_pre_generated_huk_info = config->key_config->use_pre_generated_huk_info; + huk_deploy_config.pre_generated_huk_info = &config->key_config->huk_info; + huk_deploy_config.huk_recovery_info = &config->key_info->huk_info; + esp_ret = deploy_huk(&huk_deploy_config); + if (esp_ret != ESP_OK) { + return esp_ret; + } + } + ESP_LOGI(TAG, "HUK deployed is Valid"); + + // Configure deployment mode to RANDOM + key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_RANDOM); + + // Set AES-XTS key len + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) config->key_config->key_type; + if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_256); + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + key_mgr_hal_set_xts_aes_key_len(ESP_KEY_MGR_XTS_AES_LEN_512); + } + + uint8_t *key_recovery_info = (uint8_t *) heap_caps_calloc(1, KEY_MGR_KEY_RECOVERY_INFO_SIZE, MALLOC_CAP_INTERNAL); + if (!key_recovery_info) { + return ESP_ERR_NO_MEM; + } + + // Set key purpose (XTS/ECDSA) + key_mgr_hal_set_key_purpose(config->key_purpose); key_mgr_hal_start(); key_mgr_hal_continue(); key_mgr_wait_for_state(ESP_KEY_MGR_STATE_LOAD); - if (key_config->use_sw_init_key) { - assert(key_config->sw_init_key_size == KEY_MGR_SW_INIT_KEY_SIZE); - key_mgr_hal_write_sw_init_key(key_config->sw_init_key, key_config->sw_init_key_size); - } - ESP_LOGI(TAG, "Writing Information into Key Manager Registers"); - key_mgr_hal_write_public_info(key_config->k1_G, KEY_MGR_ECDH0_INFO_SIZE); key_mgr_hal_continue(); + // No configuration for Random deploy mode key_mgr_wait_for_state(ESP_KEY_MGR_STATE_GAIN); key_mgr_hal_read_public_info(key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); - key_mgr_hal_read_assist_info(key_config->k2_G); - ESP_LOG_BUFFER_HEX_LEVEL("HUK INFO", huk_recovery_info, KEY_MGR_HUK_INFO_SIZE, ESP_LOG_INFO); - ESP_LOG_BUFFER_HEX_LEVEL("KEY_MGR KEY INFO", key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE, ESP_LOG_INFO); + ESP_LOG_BUFFER_HEX_LEVEL("KEY_MGR KEY INFO", key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE, ESP_LOG_DEBUG); - //TODO - check if HUK is valid just after it is generated - if (!key_mgr_hal_is_huk_valid()) { - ESP_LOGE(TAG, "HUK is invalid"); - // TODO - define error code - return ESP_FAIL; + if (config->key_purpose != ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1) { + if (!key_mgr_hal_is_key_deployment_valid(config->key_config->key_type)) { + ESP_LOGE(TAG, "Key deployment is not valid"); + heap_caps_free(key_recovery_info); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Key deployment valid"); } - ESP_LOGI(TAG, "HUK deplpoyed is Valid"); - if (!key_mgr_hal_is_key_deployment_valid(key_config->key_type)) { - ESP_LOGE(TAG, "Key deployment is not valid"); - // Todo - Define respective error code; - return ESP_FAIL; - } - ESP_LOGI(TAG, "Key deployment valid"); // Wait till Key Manager deployment is complete key_mgr_hal_continue(); key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE); - //memcpy(&key_info->huk_recovery_info[0], huk_recovery_info, KEY_MGR_HUK_INFO_SIZE); - //memcpy(&key_info->key_recovery_info[0], key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); - key_info->key_purpose = key_config->key_purpose; - heap_caps_free(key_recovery_info); - heap_caps_free(huk_recovery_info); - ESP_LOGI(TAG, "\nKey deployment complete\n"); - //key_mgr_hal_set_key_usage(ESP_KEY_MGR_XTS_KEY, ESP_KEY_MGR_USE_OWN_KEY); - KEY_MANAGER_RCC_ATOMIC() { - key_mgr_ll_enable_bus_clock(false); - key_mgr_ll_reset_register(); + if (config->key_purpose == ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2) { + memcpy(config->key_info->key_info[1].info, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + config->key_info->key_info[1].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + + } else { + memcpy(config->key_info->key_info[0].info, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); + config->key_info->key_info[0].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE); } + heap_caps_free(key_recovery_info); + return ESP_OK; } + +esp_err_t esp_key_mgr_deploy_key_in_random_mode(const esp_key_mgr_random_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_recovery_info) +{ + ESP_LOGI(TAG, "Key deployment in Random mode"); + + random_deploy_config_t random_deploy_config; + random_deploy_config.key_config = key_config; + random_deploy_config.key_info = key_recovery_info; + esp_key_mgr_key_type_t key_type = (esp_key_mgr_key_type_t) key_config->key_type; + + if (key_type == ESP_KEY_MGR_ECDSA_KEY) { + random_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_ECDSA; + } else if (key_type == ESP_KEY_MGR_XTS_AES_128_KEY) { + random_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_128; + } else if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + random_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1; + } else { + ESP_LOGE(TAG, "Invalid key type"); + return ESP_ERR_INVALID_ARG; + } + + esp_key_mgr_acquire_hardware(); + + esp_err_t esp_ret = key_mgr_deploy_key_random_mode(&random_deploy_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Key deployment in Random mode failed"); + return ESP_FAIL; + } + + if (key_type == ESP_KEY_MGR_XTS_AES_256_KEY) { + random_deploy_config.key_purpose = ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2; + esp_ret = key_mgr_deploy_key_random_mode(&random_deploy_config); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Key deployment in Random mode failed"); + return ESP_FAIL; + } + } + + // Set the Key Manager Static Register to use own key for the respective key type + key_mgr_hal_set_key_usage(key_config->key_type, ESP_KEY_MGR_USE_OWN_KEY); + + esp_key_mgr_release_hardware(); + + return esp_ret; +} diff --git a/components/esp_hw_support/include/esp_key_mgr.h b/components/esp_hw_support/include/esp_key_mgr.h index 61fea463aa..8ed708358d 100644 --- a/components/esp_hw_support/include/esp_key_mgr.h +++ b/components/esp_hw_support/include/esp_key_mgr.h @@ -1,11 +1,14 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include "esp_err.h" +#include "soc/soc_caps.h" + +#if SOC_KEY_MANAGER_SUPPORTED #ifdef __cplusplus extern "C" { @@ -13,81 +16,113 @@ extern "C" { #include "hal/key_mgr_types.h" #include "hal/huk_types.h" +#include "esp_attr.h" #define KEY_MGR_SW_INIT_KEY_SIZE 32 #define KEY_MGR_ASSIST_INFO_SIZE 64 #define KEY_MGR_KEY_RECOVERY_INFO_SIZE 64 + #define KEY_MGR_HUK_INFO_SIZE HUK_INFO_SIZE +#define KEY_MGR_HUK_RISK_ALERT_LEVEL HUK_RISK_ALERT_LEVEL + /* AES deploy mode */ #define KEY_MGR_K2_INFO_SIZE 64 #define KEY_MGR_K1_ENCRYPTED_SIZE 32 #define KEY_MGR_ECDH0_INFO_SIZE 64 +#define KEY_MGR_ECDH0_INFO_SIZE 64 +#define KEY_MGR_PLAINTEXT_KEY_SIZE 32 typedef struct { - // TODO - Should we use fixed arrays here instead of pointers ? esp_key_mgr_key_type_t key_type; - uint8_t *huk_info; - size_t huk_info_size; - esp_key_mgr_key_purpose_t key_purpose; - bool use_sw_init_key; - uint8_t *sw_init_key; - size_t sw_init_key_size; - uint8_t k2_info[KEY_MGR_K2_INFO_SIZE]; - uint8_t k1_encrypted[KEY_MGR_K1_ENCRYPTED_SIZE]; + bool use_pre_generated_huk_info; + bool use_pre_generated_sw_init_key; + WORD_ALIGNED_ATTR esp_key_mgr_huk_info_t huk_info; + WORD_ALIGNED_ATTR uint8_t sw_init_key[KEY_MGR_SW_INIT_KEY_SIZE]; + WORD_ALIGNED_ATTR uint8_t k2_info[KEY_MGR_K2_INFO_SIZE]; + WORD_ALIGNED_ATTR uint8_t k1_encrypted[2][KEY_MGR_K1_ENCRYPTED_SIZE]; } esp_key_mgr_aes_key_config_t; typedef struct { - // TODO - Should we use fixed arrays here instead of pointers ? esp_key_mgr_key_type_t key_type; - uint8_t *huk_info; - size_t huk_info_size; - esp_key_mgr_key_purpose_t key_purpose; - bool use_sw_init_key; - uint8_t *sw_init_key; - size_t sw_init_key_size; - uint8_t k1_G[KEY_MGR_ECDH0_INFO_SIZE]; - uint8_t k2_G[KEY_MGR_ECDH0_INFO_SIZE]; + bool use_pre_generated_huk_info; + WORD_ALIGNED_ATTR esp_key_mgr_huk_info_t huk_info; + WORD_ALIGNED_ATTR uint8_t k1_G[KEY_MGR_ECDH0_INFO_SIZE]; } esp_key_mgr_ecdh0_key_config_t; typedef struct { - uint8_t huk_recovery_info[KEY_MGR_HUK_INFO_SIZE]; - uint8_t key_recovery_info[KEY_MGR_KEY_RECOVERY_INFO_SIZE]; esp_key_mgr_key_type_t key_type; - esp_key_mgr_key_purpose_t key_purpose; -} __attribute__((packed)) esp_key_mgr_key_recovery_info_t; + bool use_pre_generated_huk_info; + WORD_ALIGNED_ATTR esp_key_mgr_huk_info_t huk_info; +} esp_key_mgr_random_key_config_t; + +typedef struct { + esp_key_mgr_key_type_t key_type; + WORD_ALIGNED_ATTR uint8_t k2_G[2][KEY_MGR_ECDH0_INFO_SIZE]; +} esp_key_mgr_ecdh0_info_t; /** - * @brief Check if the deployed key is valid or not + * @brief Deploy key in AES deployment mode * @input * key_config(input) AES key configuration - * key_info(output) A writable struct of esp_key_mgr_key_info_t type. The recovery key info for the deplyed key shall be stored here + * key_info(output) A writable struct of esp_key_mgr_key_info_t type. + * The recovery information for the the deployed key shall be stored here * @return * ESP_OK for success * ESP_FAIL/relevant error code for failure */ -esp_err_t esp_key_mgr_deploy_key_in_aes_mode(esp_key_mgr_aes_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info); +esp_err_t esp_key_mgr_deploy_key_in_aes_mode(const esp_key_mgr_aes_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info); /** - * @brief Check if the deployed key is valid or not + * @brief Deploy key in ECDH0 deployment mode * @input - * key_config(input) AES key configuration - * key_info(output) A writable struct of esp_key_mgr_key_info_t type. The recovery key info for the deplyed key shall be stored here + * key_config(input) ECDH0 key configuration + * key_info(output) A writable struct of esp_key_mgr_key_info_t type. The recovery key info for the deployed key shall be stored here + * ecdh0_key_info A writable struct of esp_key_mgr_ecdh0_info_t. The ecdh0 info to recover the actual key shall be stored here. * @return * ESP_OK for success * ESP_FAIL/relevant error code for failure */ -esp_err_t esp_key_mgr_deploy_key_in_ecdh0_mode(esp_key_mgr_ecdh0_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info); +esp_err_t esp_key_mgr_deploy_key_in_ecdh0_mode(const esp_key_mgr_ecdh0_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info, esp_key_mgr_ecdh0_info_t *ecdh0_key_info); + +/** + * @brief Deploy key in Random deployment mode + * @input + * key_config(input) Random key configuration + * key_info(output) A writable struct of esp_key_mgr_key_info_t type. The recovery key info for the deployed key shall be stored here + * @return + * ESP_OK for success + * ESP_FAIL/relevant error code for failure + */ +esp_err_t esp_key_mgr_deploy_key_in_random_mode(const esp_key_mgr_random_key_config_t *key_config, esp_key_mgr_key_recovery_info_t *key_info); /* - * @brief Recover a key from the given key info + * @brief Recover and Activate a key from the given key info * + * @note + * Once a key of particular type is activated through Key Manager, + * then a different key of the same type cannot be activated at the same time. + * This key must be deactivated first through a call to esp_key_mgr_deactivate_key() + * before activating other key of the same type * @input * key_info The key info required to recover the key * @return * ESP_OK for success - * ESP_FAIL/revevant error code for failure + * ESP_FAIL/relevant error code for failure */ -esp_err_t esp_key_mgr_recover_key(esp_key_mgr_key_recovery_info_t *key_recovery_info); +esp_err_t esp_key_mgr_activate_key(esp_key_mgr_key_recovery_info_t *key_recovery_info); + +/* + * @brief De-activate a key from the given key info + * The key which is de-activated can no longer be used for any operation + * @input + * key_info The key info required to recover the key + * @return + * ESP_OK for success + * ESP_FAIL/relevant error code for failure + */ +esp_err_t esp_key_mgr_deactivate_key(esp_key_mgr_key_type_t key_type); + #ifdef __cplusplus } #endif +#endif diff --git a/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h b/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h index 6855caae23..495a0736ff 100644 --- a/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.h +++ b/components/esp_hw_support/include/soc/esp32p4/esp_crypto_lock.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 */ @@ -91,6 +91,18 @@ void esp_crypto_ecdsa_lock_acquire(void); */ void esp_crypto_ecdsa_lock_release(void); +/** + * @brief Acquire lock for Key Manager peripheral + * + */ +void esp_crypto_key_manager_lock_acquire(void); + +/** + * @brief Release lock for Key Manager peripheral + * + */ +void esp_crypto_key_manager_lock_release(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c b/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c index fbeee00aa9..fa663d2b1d 100644 --- a/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c +++ b/components/esp_hw_support/port/esp32p4/esp_crypto_lock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -36,6 +36,9 @@ static _lock_t s_crypto_ecc_lock; /* Lock for ECDSA peripheral */ static _lock_t s_crypto_ecdsa_lock; +/* Lock for Key Manager peripheral */ +static _lock_t s_crypto_key_manager_lock; + void esp_crypto_hmac_lock_acquire(void) { _lock_acquire(&s_crypto_hmac_lock); @@ -105,3 +108,17 @@ void esp_crypto_ecdsa_lock_release(void) esp_crypto_ecc_lock_release(); _lock_release(&s_crypto_ecdsa_lock); } + +void esp_crypto_key_manager_lock_acquire(void) +{ + _lock_acquire(&s_crypto_key_manager_lock); + esp_crypto_ecc_lock_acquire(); + esp_crypto_sha_aes_lock_acquire(); +} + +void esp_crypto_key_manager_lock_release(void) +{ + esp_crypto_sha_aes_lock_release(); + esp_crypto_ecc_lock_release(); + _lock_release(&s_crypto_key_manager_lock); +} diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt index 40a5a7555b..3ff1c7fabf 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt @@ -6,6 +6,7 @@ set(srcs "test_app_main.c" "test_ds.c" "test_hmac.c" "test_random.c" + "test_key_mgr.c" ) if(CONFIG_SOC_MULTI_USAGE_LDO_SUPPORTED) @@ -19,5 +20,5 @@ endif() # In order for the cases defined by `TEST_CASE` to be linked into the final elf, # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} - REQUIRES unity esp_driver_gpio esp_driver_gptimer esp_driver_uart test_utils efuse + REQUIRES unity esp_driver_gpio esp_driver_gptimer esp_driver_uart test_utils efuse spi_flash WHOLE_ARCHIVE) diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_key_mgr.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_key_mgr.c new file mode 100644 index 0000000000..fa34b53f6f --- /dev/null +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_key_mgr.c @@ -0,0 +1,140 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include "unity.h" + +#include "soc/soc_caps.h" +#if SOC_KEY_MANAGER_SUPPORTED +#include "esp_partition.h" +#include "esp_flash.h" +#include "esp_log.h" +#include "esp_err.h" +#if CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/efuse.h" +#endif +#include "soc/keymng_reg.h" +#include "esp_key_mgr.h" + +static const char *TAG = "key_mgr_test"; + +#define ENCRYPTED_DATA_SIZE 128 +static const uint8_t plaintext_data[ENCRYPTED_DATA_SIZE] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, +}; + +static const uint8_t expected_ciphertext[ENCRYPTED_DATA_SIZE] = { + 0x10, 0x5d, 0x20, 0x41, 0x87, 0xb7, 0x16, 0x09, 0x3f, 0x67, 0x32, 0x79, 0x06, 0x53, 0x97, 0x53, + 0x2b, 0x88, 0x1a, 0x22, 0xb2, 0xdc, 0x4e, 0x5e, 0xc2, 0xc8, 0x25, 0xe9, 0xf9, 0x6b, 0xfe, 0xd6, + 0x12, 0x2c, 0xfa, 0x2c, 0x67, 0x7f, 0x08, 0xae, 0xce, 0x50, 0x68, 0x00, 0x0c, 0xee, 0x27, 0x1a, + 0x54, 0x94, 0xc8, 0xea, 0xc3, 0xf3, 0x3e, 0xd9, 0xe6, 0x11, 0x76, 0x80, 0x3e, 0xa2, 0x16, 0xc0, + 0x66, 0xdc, 0xdf, 0xb1, 0x73, 0x59, 0xae, 0x3e, 0xfc, 0x64, 0x38, 0x60, 0xf6, 0xc8, 0xf8, 0x57, + 0xa8, 0x0c, 0x56, 0xd6, 0x2e, 0xdd, 0x06, 0xb6, 0xef, 0xf4, 0xb6, 0xba, 0xae, 0x5e, 0xcc, 0xe0, + 0x74, 0x7d, 0x76, 0x69, 0x34, 0x15, 0x6d, 0x6e, 0x0c, 0xbd, 0xae, 0xdf, 0xe5, 0x2a, 0xf0, 0xed, + 0x6d, 0xb0, 0xbd, 0x75, 0xda, 0xd6, 0x78, 0x08, 0x4b, 0xeb, 0xdd, 0xfe, 0x72, 0xd1, 0xd2, 0x26, +}; + +/* Big endian */ +uint8_t init_key[] = { + 0x4d, 0x21, 0x64, 0x21, 0x8f, 0xa2, 0xe3, 0xa0, 0xab, 0x74, 0xb5, 0xab, 0x17, 0x9a, 0x5d, 0x08, + 0x58, 0xf4, 0x22, 0x03, 0xbd, 0x52, 0xe7, 0x88, 0x3c, 0x22, 0x0f, 0x95, 0x89, 0x70, 0xe1, 0x93 +}; + +/* Big endian */ +uint8_t k2_info[] = { + 0xd8, 0xcd, 0x04, 0x45, 0xb4, 0x45, 0xc4, 0x15, 0xf6, 0x40, 0x1c, 0x7d, 0x90, 0x1b, 0x99, 0xa4, + 0x79, 0x6b, 0xfb, 0x5b, 0x2a, 0x40, 0x60, 0xe1, 0xc1, 0xe1, 0x48, 0xcd, 0x46, 0x6b, 0x9b, 0x48, + 0xda, 0x7a, 0x70, 0x0a, 0x78, 0x0b, 0x9d, 0xf9, 0x0e, 0xed, 0x91, 0xfc, 0xa5, 0xc2, 0x96, 0x05, + 0x91, 0x76, 0xdb, 0x68, 0x84, 0x5d, 0x5e, 0x5b, 0xa6, 0xe9, 0x6b, 0x3b, 0x12, 0x50, 0x05, 0xc3 +}; + +/* Big endian */ +uint8_t k1_ecdsa_encrypt[] = { + 0xeb, 0x83, 0x24, 0x7d, 0xf8, 0x40, 0xc9, 0x88, 0x5f, 0x5e, 0x58, 0x57, 0x25, 0xa9, 0x23, 0x4a, + 0xa4, 0xc4, 0x12, 0x17, 0xf3, 0x9e, 0x1f, 0xa0, 0xa0, 0xfa, 0xd5, 0xbf, 0xb6, 0x6c, 0xb5, 0x48 +}; + +uint8_t k1_xts_encrypt[] = { + 0xeb, 0x83, 0x24, 0x7d, 0xf8, 0x40, 0xc9, 0x88, 0x5f, 0x5e, 0x58, 0x57, 0x25, 0xa9, 0x23, 0x4a, + 0xa4, 0xc4, 0x12, 0x17, 0xf3, 0x9e, 0x1f, 0xa0, 0xa0, 0xfa, 0xd5, 0xbf, 0xb6, 0x6c, 0xb5, 0x48 +}; + +const esp_partition_t *get_test_storage_partition(void) +{ + /* This finds "storage" partition defined partition table */ + const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, + ESP_PARTITION_SUBTYPE_ANY, "storage"); + if (!result) { + /* means partition table set wrong */ + ESP_LOGE(TAG, "ERROR in obtaining storage partition"); + return NULL; + } + return result; +} + +static esp_err_t test_xts_aes_key(void) +{ + const esp_partition_t *partition = get_test_storage_partition(); + ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size)); + + uint32_t address = partition->address; + ESP_ERROR_CHECK(esp_flash_write_encrypted(NULL, address, plaintext_data, sizeof(plaintext_data))); + uint8_t read_data[ENCRYPTED_DATA_SIZE]; + ESP_ERROR_CHECK(esp_flash_read(NULL, read_data, address, sizeof(read_data))); + if (memcmp(read_data, expected_ciphertext, sizeof(expected_ciphertext)) != 0) { + ESP_LOGE(TAG, "Encrypted data does not match expected data"); + return ESP_FAIL; + } + return ESP_OK; +} + +TEST_CASE("Key Manager AES mode: XTS-AES key deployment", "[hw_crypto] [key_mgr]") +{ + static esp_key_mgr_aes_key_config_t key_config; + memcpy(key_config.k2_info, (uint8_t*) k2_info, KEY_MGR_K2_INFO_SIZE); + memcpy(key_config.k1_encrypted, (uint8_t*) k1_xts_encrypt, KEY_MGR_K1_ENCRYPTED_SIZE); + memcpy(key_config.sw_init_key, (uint8_t*) init_key, KEY_MGR_SW_INIT_KEY_SIZE); + key_config.use_pre_generated_sw_init_key = 1; + key_config.key_type = ESP_KEY_MGR_XTS_AES_128_KEY; + + static esp_key_mgr_key_recovery_info_t key_info; + esp_err_t esp_ret = ESP_FAIL; + esp_ret = esp_key_mgr_deploy_key_in_aes_mode(&key_config, &key_info); + TEST_ASSERT_EQUAL(ESP_OK, esp_ret); + esp_ret = test_xts_aes_key(); + TEST_ASSERT_EQUAL(ESP_OK, esp_ret); +} + +TEST_CASE("Key Manager random mode: XTS_AES_128 key deployment", "[hw_crypto] [key_mgr]") +{ + ESP_LOGI(TAG, "Key Manager Example Start"); + static esp_key_mgr_random_key_config_t key_config; + + key_config.key_type = ESP_KEY_MGR_XTS_AES_128_KEY; + + static esp_key_mgr_key_recovery_info_t key_info; + esp_err_t esp_ret = ESP_FAIL; + esp_ret = esp_key_mgr_deploy_key_in_random_mode(&key_config, &key_info); + TEST_ASSERT_EQUAL(ESP_OK, esp_ret); + +} + +TEST_CASE("Key Manager random mode: ECDSA key deployment", "[hw_crypto] [key_mgr]") +{ + static esp_key_mgr_random_key_config_t key_config; + static esp_key_mgr_key_recovery_info_t key_info; + esp_err_t esp_ret = ESP_FAIL; + key_config.key_type = ESP_KEY_MGR_ECDSA_KEY; + esp_ret = esp_key_mgr_deploy_key_in_random_mode(&key_config, &key_info); + TEST_ASSERT_EQUAL(ESP_OK, esp_ret); +} +#endif diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults index b71277ca37..cc85282c55 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/sdkconfig.defaults @@ -1,2 +1,8 @@ CONFIG_ESP_TASK_WDT_INIT=n CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192 +# set compiler optimization level +CONFIG_COMPILER_OPTIMIZATION_SIZE=y +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y + +# we can silent the assertion to save the binary footprint +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y diff --git a/components/esp_rom/include/esp32p4/rom/key_mgr.h b/components/esp_rom/include/esp32p4/rom/key_mgr.h index 2a5707fa80..eb0914f4b9 100644 --- a/components/esp_rom/include/esp32p4/rom/key_mgr.h +++ b/components/esp_rom/include/esp32p4/rom/key_mgr.h @@ -35,7 +35,8 @@ struct huk_key_block { #define KEY_HUK_SECTOR_MAGIC 0xDEA5CE5A uint32_t magic; uint32_t version; // for backward compatibility - uint8_t reserved[16]; + uint8_t key_type; + uint8_t reserved[15]; struct huk_info huk_info; struct key_info key_info[2]; // at most 2 key info (XTS-512_1 and XTS-512_2), at least use 1 } WORD_ALIGNED_ATTR PACKED_ATTR; diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index d0109db8e0..b55965aa2c 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -68,7 +68,10 @@ #elif CONFIG_IDF_TARGET_ESP32P4 #include "esp32p4/rtc.h" #include "soc/hp_sys_clkrst_reg.h" -#include "soc/keymng_reg.h" +#endif + +#if SOC_KEY_MANAGER_SUPPORTED +#include "hal/key_mgr_hal.h" #endif #include "esp_private/rtc_clk.h" @@ -305,11 +308,14 @@ static void start_other_core(void) if(REG_GET_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_CORE1_GLOBAL)){ REG_CLR_BIT(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_CORE1_GLOBAL); } +#endif + +#if SOC_KEY_MANAGER_SUPPORTED // 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 - // TODO-IDF 7925 (Move this under SOC_KEY_MANAGER_SUPPORTED) - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 3); + key_mgr_hal_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); + key_mgr_hal_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); #endif ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1); diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index a023f7cde0..2fddbea5ce 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -26,6 +26,11 @@ if(CONFIG_SOC_WDT_SUPPORTED AND NOT CONFIG_HAL_WDT_USE_ROM_IMPL) list(APPEND srcs "wdt_hal_iram.c") endif() +if(CONFIG_SOC_KEY_MANAGER_SUPPORTED) + list(APPEND srcs "key_mgr_hal.c") + list(APPEND srcs "huk_hal.c") +endif() + if(NOT CONFIG_APP_BUILD_TYPE_PURE_RAM_APP) if(CONFIG_SOC_MMU_PERIPH_NUM) list(APPEND srcs "mmu_hal.c") @@ -237,11 +242,6 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "ds_hal.c") endif() - if(CONFIG_SOC_KEY_MANAGER_SUPPORTED) - list(APPEND srcs "key_mgr_hal.c") - list(APPEND srcs "huk_hal.c") - endif() - if(CONFIG_SOC_USB_OTG_SUPPORTED) list(APPEND srcs "usb_dwc_hal.c" diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index 3737e793ba..b7e661ec31 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -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 */ @@ -10,7 +10,7 @@ #include "hal/efuse_hal.h" #ifdef SOC_KEY_MANAGER_SUPPORTED -#include "soc/keymng_reg.h" // TODO: IDF-7901 +#include "hal/key_mgr_hal.h" #endif #define ECDSA_HAL_P192_COMPONENT_LEN 24 @@ -18,13 +18,19 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) { -#ifdef SOC_KEY_MANAGER_SUPPORTED - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, 1); // TODO: IDF-7901 -#endif + if (conf->use_km_key == 0) { efuse_hal_set_ecdsa_key(conf->efuse_key_blk); +#if SOC_KEY_MANAGER_SUPPORTED + key_mgr_hal_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY); +#endif } +#if SOC_KEY_MANAGER_SUPPORTED + else { + key_mgr_hal_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_OWN_KEY); + } +#endif ecdsa_ll_set_mode(conf->mode); ecdsa_ll_set_curve(conf->curve); diff --git a/components/hal/esp32p4/include/hal/huk_ll.h b/components/hal/esp32p4/include/hal/huk_ll.h index 9c4d987749..6fa5b98f2a 100644 --- a/components/hal/esp32p4/include/hal/huk_ll.h +++ b/components/hal/esp32p4/include/hal/huk_ll.h @@ -12,6 +12,7 @@ #pragma once #include "soc/soc_caps.h" + #if SOC_KEY_MANAGER_SUPPORTED #include diff --git a/components/hal/esp32p4/include/hal/key_mgr_hal.h b/components/hal/esp32p4/include/hal/key_mgr_hal.h index 27e4a76e39..3bed3fa3fd 100644 --- a/components/hal/esp32p4/include/hal/key_mgr_hal.h +++ b/components/hal/esp32p4/include/hal/key_mgr_hal.h @@ -112,7 +112,7 @@ void key_mgr_hal_write_public_info(const uint8_t *public_info_buf, const size_t void key_mgr_hal_read_public_info(uint8_t *public_info_buf, const size_t read_len); /* @brief Set the AES-XTS key length for the Key Manager */ -void key_mgr_hal_set_aes_xts_key_len(const esp_key_mgr_xts_aes_key_len_t key_len); +void key_mgr_hal_set_xts_aes_key_len(const esp_key_mgr_xts_aes_key_len_t key_len); /* @brief Get the AES-XTS key length for the Key Manager */ esp_key_mgr_xts_aes_key_len_t key_mgr_hal_get_aes_xts_key_len(void); diff --git a/components/hal/esp32p4/include/hal/key_mgr_ll.h b/components/hal/esp32p4/include/hal/key_mgr_ll.h index 107b1d338c..1bcd5402bf 100644 --- a/components/hal/esp32p4/include/hal/key_mgr_ll.h +++ b/components/hal/esp32p4/include/hal/key_mgr_ll.h @@ -11,6 +11,7 @@ #pragma once #include "soc/soc_caps.h" + #if SOC_KEY_MANAGER_SUPPORTED #include #include @@ -118,14 +119,45 @@ static inline void key_mgr_ll_use_sw_init_key(void) */ 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) { - uint8_t read_value = ((0x03) & REG_GET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY)); - uint8_t reg_value = (read_value & (~((uint8_t)key_type))) | (uint8_t) (key_type * key_usage); - REG_SET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY, reg_value); + 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_XTS); + } else { + REG_CLR_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_XTS); + } + 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) { - return (esp_key_mgr_key_usage_t) (key_type & REG_GET_FIELD(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY)); + 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_XTS)); + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return ESP_KEY_MGR_USAGE_INVALID; + } + return ESP_KEY_MGR_USAGE_INVALID; } /** @@ -143,9 +175,17 @@ static inline void key_mgr_ll_lock_use_sw_init_key_reg(void) * After this lock has been set, * The Key manager configuration about whether to use a paricular key from efuse or key manager cannot be changed. */ -static inline void key_mgr_ll_lock_use_efuse_key_reg(void) +static inline void key_mgr_ll_lock_use_efuse_key_reg(esp_key_mgr_key_type_t key_type) { - REG_SET_BIT(KEYMNG_LOCK_REG, KEYMNG_USE_EFUSE_KEY_LOCK); + 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_XTS); + break; + } } /* @brief Configure the key purpose to be used by the Key Manager for key generator opearation */ @@ -180,15 +220,19 @@ static inline bool key_mgr_ll_is_result_success(void) 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_KEY: - return REG_GET_FIELD(KEYMNG_KEY_VLD_REG, KEYMNG_KEY_XTS_VLD); - break; - default: - HAL_ASSERT(false && "Unsupported mode"); - return 0; + + 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_XTS_VLD); + break; + + default: + HAL_ASSERT(false && "Unsupported mode"); + return 0; } } @@ -255,13 +299,13 @@ static inline bool key_mgr_ll_is_huk_valid(void) } /* @brief Set the AES-XTS key length for the Key Manager */ -static inline void key_mgr_ll_set_aes_xts_key_len(const esp_key_mgr_xts_aes_key_len_t key_len) +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_XTS_AES_KEY_LEN, key_len); } /* @brief Get the AES-XTS key length for the Key Manager */ -static inline esp_key_mgr_xts_aes_key_len_t key_mgr_ll_get_aes_xts_key_len(void) +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); } diff --git a/components/hal/include/hal/huk_types.h b/components/hal/include/hal/huk_types.h index 5b09f5c6f1..8812fe6f2f 100644 --- a/components/hal/include/hal/huk_types.h +++ b/components/hal/include/hal/huk_types.h @@ -17,6 +17,7 @@ extern "C" { #endif #define HUK_INFO_SIZE 384 +#define HUK_RISK_ALERT_LEVEL 4 /** * @brief Mode for Hardware Unique Key Process: recovery, generation diff --git a/components/hal/include/hal/key_mgr_types.h b/components/hal/include/hal/key_mgr_types.h index b7447f5155..82064e58d4 100644 --- a/components/hal/include/hal/key_mgr_types.h +++ b/components/hal/include/hal/key_mgr_types.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 */ @@ -11,6 +11,7 @@ #include #include #include +#include "esp_attr.h" #define KEY_MGR_ASSIST_INFO_LEN 64 @@ -23,25 +24,26 @@ extern "C" { */ typedef enum { ESP_KEY_MGR_STATE_IDLE = 0, /* Key Manager is idle */ - ESP_KEY_MGR_STATE_LOAD, /* Key Manager is read to recieve input */ - ESP_KEY_MGR_STATE_GAIN, /* Key Manager is ready to provide output */ - ESP_KEY_MGR_STATE_BUSY /* Key Manager is busy */ + ESP_KEY_MGR_STATE_LOAD = 1, /* Key Manager is ready to recieve 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 XTS AES key */ typedef enum { - ESP_KEY_MGR_XTS_AES_LEN_512 = 0, /* xts-aes key is 512 bit, please note that xts-aes algorithm is XTS_AES_256 */ - ESP_KEY_MGR_XTS_AES_LEN_256, /* xts-aes key is 256 bit, please note that xts-aes algorithm is XTS_AES_128*/ + ESP_KEY_MGR_XTS_AES_LEN_256 = 0, /* xts-aes key is 256 bit, please note that xts-aes algorithm is XTS_AES_128*/ + ESP_KEY_MGR_XTS_AES_LEN_512, /* xts-aes key is 512 bit, please note that xts-aes algorithm is XTS_AES_256 */ } esp_key_mgr_xts_aes_key_len_t; /** * @brief Type of the key: ECDSA, XTS */ typedef enum { - ESP_KEY_MGR_ECDSA_KEY = 1, /* ECDSA key */ - ESP_KEY_MGR_XTS_KEY, /* XTS AES key */ + ESP_KEY_MGR_ECDSA_KEY = 0, /* ECDSA key */ + ESP_KEY_MGR_XTS_AES_128_KEY, /* XTS-AES 128 key */ + ESP_KEY_MGR_XTS_AES_256_KEY, /* XTS-AES 256 key */ } esp_key_mgr_key_type_t; /* @@ -50,6 +52,7 @@ typedef enum { 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; /** @@ -57,9 +60,9 @@ typedef enum { */ typedef enum { ESP_KEY_MGR_KEY_PURPOSE_ECDSA = 1, - ESP_KEY_MGR_KEY_PURPOSE_XTS_256_1, /* First half of the XTS AES 256 bit key */ - ESP_KEY_MGR_KEY_PURPOSE_XTS_256_2, /* Second half of the XTS AES 256 bit key */ - ESP_KEY_MGR_KEY_PURPOSE_XTS_128 /* XTS AES 128 bit key */ + ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_1 = 2, /* First half of the XTS AES 256 bit key */ + ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_256_2 = 3, /* Second half of the XTS AES 256 bit key */ + ESP_KEY_MGR_KEY_PURPOSE_XTS_AES_128 = 4, /* XTS AES 128 bit key */ } esp_key_mgr_key_purpose_t; /** @@ -67,11 +70,11 @@ typedef enum { */ typedef enum { ESP_KEY_MGR_KEYGEN_MODE_RANDOM = 0, - ESP_KEY_MGR_KEYGEN_MODE_AES, - ESP_KEY_MGR_KEYGEN_MODE_ECDH0, - ESP_KEY_MGR_KEYGEN_MODE_ECDH1, - ESP_KEY_MGR_KEYGEN_MODE_RECOVER, - ESP_KEY_MGR_KEYGEN_MODE_EXPORT, + 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; /** @@ -84,6 +87,30 @@ typedef enum { ESP_KEY_MGR_INT_POST_DONE, } esp_key_mgr_interrupt_type_t; +// store huk info, occupy 96 words +typedef struct PACKED_ATTR { +#define HUK_INFO_LEN 384 + 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 reserved[15]; + 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 diff --git a/components/hal/key_mgr_hal.c b/components/hal/key_mgr_hal.c index 0db46c805b..3658371fd5 100644 --- a/components/hal/key_mgr_hal.c +++ b/components/hal/key_mgr_hal.c @@ -79,14 +79,14 @@ bool key_mgr_hal_is_huk_valid(void) return key_mgr_ll_is_huk_valid(); } -void key_mgr_hal_set_aes_xts_key_len(const esp_key_mgr_xts_aes_key_len_t key_len) +void key_mgr_hal_set_xts_aes_key_len(const esp_key_mgr_xts_aes_key_len_t key_len) { - key_mgr_ll_set_aes_xts_key_len(key_len); + key_mgr_ll_set_xts_aes_key_len(key_len); } -esp_key_mgr_xts_aes_key_len_t key_mgr_hal_get_aes_xts_key_len(void) +esp_key_mgr_xts_aes_key_len_t key_mgr_hal_get_xts_aes_key_len(void) { - return key_mgr_ll_get_aes_xts_key_len(); + return key_mgr_ll_get_xts_aes_key_len(); } void key_mgr_hal_continue(void) diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h index a8646979a7..e409bf1cb1 100644 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h @@ -29,7 +29,7 @@ typedef struct { #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY bool load_pubkey; /*!< Export ECDSA public key from the hardware */ #endif -} esp_ecdsa_pk_conf_t; //TODO: IDF-7925 (Add a config to select the ecdsa key from the key manager peripheral) +} esp_ecdsa_pk_conf_t; //TODO: IDF-9008 (Add a config to select the ecdsa key from the key manager peripheral) #if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || __DOXYGEN__ diff --git a/components/soc/esp32p4/include/soc/keymng_reg.h b/components/soc/esp32p4/include/soc/keymng_reg.h index d75565dbc8..a8f03edc6e 100644 --- a/components/soc/esp32p4/include/soc/keymng_reg.h +++ b/components/soc/esp32p4/include/soc/keymng_reg.h @@ -138,14 +138,21 @@ extern "C" { * Key Manager static configuration register */ #define KEYMNG_STATIC_REG (DR_REG_KEYMNG_BASE + 0x18) -/** KEYMNG_USE_EFUSE_KEY : R/W; bitpos: [1:0]; default: 0; - * Set each bit to choose efuse key instead of key manager deployed key. Each bit - * stands for a key type: bit 1 for xts_key; bit 0 for ecdsa_key - */ -#define KEYMNG_USE_EFUSE_KEY 0x00000003U -#define KEYMNG_USE_EFUSE_KEY_M (KEYMNG_USE_EFUSE_KEY_V << KEYMNG_USE_EFUSE_KEY_S) -#define KEYMNG_USE_EFUSE_KEY_V 0x00000003U -#define KEYMNG_USE_EFUSE_KEY_S 0 + +/* KEYMNG_USE_EFUSE_KEY_XTS : R/W ;bitpos:[1] ;default: 1'd0 ; */ +/*description: Set this bit to choose efuse key instead of key manager deployed key for xts_key.*/ +#define KEYMNG_USE_EFUSE_KEY_XTS (BIT(1)) +#define KEYMNG_USE_EFUSE_KEY_XTS_M ((KEYMNG_USE_EFUSE_KEY_XTS_V)<<(KEYMNG_USE_EFUSE_KEY_XTS_S)) +#define KEYMNG_USE_EFUSE_KEY_XTS_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_XTS_S 1 + +/* 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_key.*/ +#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_RND_SWITCH_CYCLE : R/W; bitpos: [8:4]; 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 @@ -174,14 +181,21 @@ extern "C" { * Key Manager static configuration locker register */ #define KEYMNG_LOCK_REG (DR_REG_KEYMNG_BASE + 0x1c) -/** KEYMNG_USE_EFUSE_KEY_LOCK : R/W1; bitpos: [1:0]; default: 0; - * Write 1 to lock reg_use_efuse_key. Each bit locks the corresponding bit of - * reg_use_efuse_key. - */ -#define KEYMNG_USE_EFUSE_KEY_LOCK 0x00000003U -#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 0x00000003U -#define KEYMNG_USE_EFUSE_KEY_LOCK_S 0 + +/* KEYMNG_USE_EFUSE_KEY_XTS : R/W ; bitpos:[1] ; default: 1'd0 ; */ +/* description: Set thus bit to choose efuse key instead of key manager deployed key for xts_key */ +#define KEYMNG_USE_EFUSE_KEY_LOCK_XTS (BIT(1)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_XTS_M ((KEYMNG_USE_EFUSE_KEY_LOCK_XTS_V)<<(KEYMNG_USE_EFUSE_KEY_LOCK_XTS_S)) +#define KEYMNG_USE_EFUSE_KEY_LOCK_XTS_V 0x1 +#define KEYMNG_USE_EFUSE_KEY_LOCK_XTS_S 1 + +/* KEYMNG_USE_EFUSE_KEY_LOCK_ECDSA : R/W ; bitpos:[0] ; default: 1'd0 ; */ +/* description: Write 1 to lock ecdsa-key */ +#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_RND_SWITCH_CYCLE_LOCK : R/W1; bitpos: [4]; default: 0; * Write 1 to lock reg_rnd_switch_cycle. */ diff --git a/examples/peripherals/README.md b/examples/peripherals/README.md index 363d8fcd27..eef44e9462 100644 --- a/examples/peripherals/README.md +++ b/examples/peripherals/README.md @@ -1,6 +1,3 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | - # Peripherals Examples This section provides examples how to configure and use ESP32’s internal peripherals like GPIO, UART, I2C, SPI, timers, counters, ADC / DAC, PWM, etc.