feat(esp_security): add ECDH1 deployment mode to Key Manager driver

This commit is contained in:
harshal.patil
2026-05-11 09:38:00 +05:30
parent 3e6273c9c4
commit 98bbe26aea
8 changed files with 583 additions and 39 deletions
+161 -12
View File
@@ -423,6 +423,10 @@ static esp_err_t key_mgr_deploy_key_aes_mode(aes_deploy_config_t *config)
key_mgr_hal_read_public_info(key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE);
// Wait till Key Manager deployment is complete
key_mgr_hal_continue();
key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE);
// Check if key deployment validation should be skipped for this purpose
// Primary purposes in multi-stage deployments skip validation after the first stage
// because the key is not yet completely deployed.
@@ -434,10 +438,6 @@ static esp_err_t key_mgr_deploy_key_aes_mode(aes_deploy_config_t *config)
}
ESP_LOGD(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);
config->key_info->key_info[key_recovery_info_index].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE);
config->key_info->key_type = key_type;
config->key_info->key_len = key_len;
@@ -709,6 +709,10 @@ static esp_err_t key_mgr_deploy_key_ecdh0_mode(ecdh0_deploy_config_t *config)
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);
// Wait till Key Manager deployment is complete
key_mgr_hal_continue();
key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE);
// Check if key deployment validation should be skipped for this purpose
// Primary purposes in multi-stage deployments skip validation after the first stage
// because the key is not yet completely deployed.
@@ -720,10 +724,6 @@ static esp_err_t key_mgr_deploy_key_ecdh0_mode(ecdh0_deploy_config_t *config)
}
ESP_LOGD(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);
config->key_info->key_info[key_recovery_info_index].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE);
config->key_info->key_type = key_type;
config->key_info->key_len = key_len;
@@ -789,6 +789,155 @@ cleanup:
return esp_ret;
}
typedef struct ecdh1_deploy {
esp_key_mgr_key_purpose_t key_purpose;
const uint8_t *k1_G;
const esp_key_mgr_ecdh1_key_config_t *key_config;
esp_key_mgr_key_recovery_info_t *key_info;
bool huk_deployed;
} ecdh1_deploy_config_t;
static esp_err_t key_mgr_deploy_key_ecdh1_mode(ecdh1_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()) || (!config->huk_deployed)) {
huk_deploy_config_t huk_deploy_config = {
.use_pre_generated_huk_info = config->key_config->use_pre_generated_huk_info,
.pre_generated_huk_info = &config->key_config->huk_info,
.huk_recovery_info = &config->key_info->huk_info,
};
esp_ret = deploy_huk(&huk_deploy_config);
if (esp_ret != ESP_OK) {
return esp_ret;
}
ESP_LOGD(TAG, "HUK deployed successfully");
}
uint8_t key_recovery_info_index = is_multi_stage_key_purpose(config->key_purpose) ? 0 : 1;
uint8_t *key_recovery_info = config->key_info->key_info[key_recovery_info_index].info;
// Step 1: Initialization
key_mgr_hal_set_key_generator_mode(ESP_KEY_MGR_KEYGEN_MODE_ECDH1);
key_mgr_hal_set_key_purpose(config->key_purpose);
esp_key_mgr_key_type_t key_type = config->key_config->key_type;
esp_key_mgr_key_len_t key_len = config->key_config->key_len;
if (key_type == ESP_KEY_MGR_FLASH_XTS_AES_KEY || key_type == ESP_KEY_MGR_PSRAM_XTS_AES_KEY) {
key_mgr_hal_set_xts_aes_key_len(key_type, key_len);
}
if (config->key_config->use_pre_generated_sw_init_key) {
key_mgr_hal_use_sw_init_key();
} else if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_KM_INIT_KEY, NULL)) {
ESP_LOGE(TAG, "Could not find key with purpose KM_INIT_KEY");
return ESP_FAIL;
}
key_mgr_hal_start();
// Step 2: Load phase
key_mgr_wait_for_state(ESP_KEY_MGR_STATE_LOAD);
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_LOGD(TAG, "Writing Information into Key Manager Registers");
key_mgr_hal_write_assist_info(config->key_config->k2_info, KEY_MGR_K2_INFO_SIZE);
key_mgr_hal_write_public_info(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);
// Wait till Key Manager deployment is complete
key_mgr_hal_continue();
key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE);
// Check if key deployment validation should be skipped for this purpose
// Primary purposes in multi-stage deployments skip validation after the first stage
// because the key is not yet completely deployed.
if (!is_multi_stage_key_purpose(config->key_purpose)) {
if (!key_mgr_hal_is_key_deployment_valid(key_type, key_len)) {
ESP_LOGE(TAG, "Key deployment is not valid");
return ESP_FAIL;
}
}
ESP_LOGD(TAG, "Key deployment valid");
config->key_info->key_info[key_recovery_info_index].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE);
config->key_info->key_type = key_type;
config->key_info->key_len = key_len;
config->key_info->key_deployment_mode = ESP_KEY_MGR_KEYGEN_MODE_ECDH1;
config->key_info->magic = KEY_HUK_SECTOR_MAGIC;
return ESP_OK;
}
esp_err_t esp_key_mgr_deploy_key_in_ecdh1_mode(const esp_key_mgr_ecdh1_key_config_t *key_config,
esp_key_mgr_key_recovery_info_t *key_info)
{
if (!key_mgr_ll_is_supported()) {
return ESP_ERR_NOT_SUPPORTED;
}
if (key_config == NULL || key_info == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_LOGD(TAG, "Key Deployment in ECDH1 mode");
ecdh1_deploy_config_t ecdh1_deploy_config = {
.key_config = key_config,
.key_info = key_info,
.k1_G = key_config->k1_G[0],
};
ecdh1_deploy_config.key_purpose = get_key_purpose(key_config->key_type, key_config->key_len);
if (ecdh1_deploy_config.key_purpose == ESP_KEY_MGR_KEY_PURPOSE_INVALID) {
ESP_LOGE(TAG, "Invalid key type");
return ESP_ERR_INVALID_ARG;
}
esp_key_mgr_acquire_hardware(true);
esp_err_t esp_ret = key_mgr_deploy_key_ecdh1_mode(&ecdh1_deploy_config);
if (esp_ret != ESP_OK) {
ESP_LOGE(TAG, "Key deployment in ECDH1 mode failed");
goto cleanup;
}
ecdh1_deploy_config.huk_deployed = true;
if (is_multi_stage_key_purpose(ecdh1_deploy_config.key_purpose)) {
ecdh1_deploy_config.key_purpose = get_secondary_key_purpose(ecdh1_deploy_config.key_purpose);
ecdh1_deploy_config.k1_G = key_config->k1_G[1];
esp_ret = key_mgr_deploy_key_ecdh1_mode(&ecdh1_deploy_config);
if (esp_ret != ESP_OK) {
ESP_LOGE(TAG, "Key deployment in ECDH1 mode failed");
goto cleanup;
}
}
// 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);
cleanup:
esp_key_mgr_release_hardware(true);
return esp_ret;
}
typedef struct random_deploy {
esp_key_mgr_key_purpose_t key_purpose;
const esp_key_mgr_random_key_config_t *key_config;
@@ -845,6 +994,10 @@ static esp_err_t key_mgr_deploy_key_random_mode(random_deploy_config_t *config)
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);
// Wait till Key Manager deployment is complete
key_mgr_hal_continue();
key_mgr_wait_for_state(ESP_KEY_MGR_STATE_IDLE);
// Check if key deployment validation should be skipped for this purpose
// Primary purposes in multi-stage deployments skip validation after the first stage
// because the key is not yet completely deployed.
@@ -856,10 +1009,6 @@ static esp_err_t key_mgr_deploy_key_random_mode(random_deploy_config_t *config)
}
ESP_LOGD(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);
config->key_info->key_info[key_recovery_info_index].crc = esp_rom_crc32_le(0, key_recovery_info, KEY_MGR_KEY_RECOVERY_INFO_SIZE);
config->key_info->key_type = key_type;
config->key_info->key_len = key_len;