mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
secure_boot: Checks secure boot efuses
ESP32 V1 and V2 - protection bits. ESP32xx V2: revoke bits, protection bits - refactor efuse component - adds some APIs for esp32 chips as well as for esp32xx chips
This commit is contained in:
parent
b92c290e56
commit
90f2d3199a
@ -692,6 +692,16 @@ menu "Security features"
|
|||||||
key digest, causing an immediate denial of service and possibly allowing an additional fault
|
key digest, causing an immediate denial of service and possibly allowing an additional fault
|
||||||
injection attack to bypass the signature protection.
|
injection attack to bypass the signature protection.
|
||||||
|
|
||||||
|
config SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS
|
||||||
|
bool "Leave unused digest slots available (not revoke)"
|
||||||
|
depends on SECURE_BOOT_INSECURE && !IDF_TARGET_ESP32
|
||||||
|
default N
|
||||||
|
help
|
||||||
|
If not set (default), during startup in the app all unused digest slots will be revoked.
|
||||||
|
To revoke unused slot will be called esp_efuse_set_digest_revoke(num_digest) for each digest.
|
||||||
|
Revoking unused digest slots makes ensures that no trusted keys can be added later by an attacker.
|
||||||
|
If set, it means that you have a plan to use unused digests slots later.
|
||||||
|
|
||||||
config SECURE_INSECURE_ALLOW_DL_MODE
|
config SECURE_INSECURE_ALLOW_DL_MODE
|
||||||
bool "Don't automatically restrict UART download mode"
|
bool "Don't automatically restrict UART download mode"
|
||||||
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
|
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
|
||||||
|
@ -9,6 +9,7 @@ set(srcs
|
|||||||
"src/bootloader_utility.c"
|
"src/bootloader_utility.c"
|
||||||
"src/esp_image_format.c"
|
"src/esp_image_format.c"
|
||||||
"src/flash_encrypt.c"
|
"src/flash_encrypt.c"
|
||||||
|
"src/secure_boot.c"
|
||||||
"src/flash_partitions.c"
|
"src/flash_partitions.c"
|
||||||
"src/flash_qio_mode.c"
|
"src/flash_qio_mode.c"
|
||||||
"src/bootloader_flash_config_${IDF_TARGET}.c"
|
"src/bootloader_flash_config_${IDF_TARGET}.c"
|
||||||
|
@ -214,6 +214,17 @@ typedef struct {
|
|||||||
uint8_t digest[64];
|
uint8_t digest[64];
|
||||||
} esp_secure_boot_iv_digest_t;
|
} esp_secure_boot_iv_digest_t;
|
||||||
|
|
||||||
|
/** @brief Check the secure boot V2 during startup
|
||||||
|
*
|
||||||
|
* @note This function is called automatically during app startup,
|
||||||
|
* it doesn't need to be called from the app.
|
||||||
|
*
|
||||||
|
* Verifies the secure boot config during startup:
|
||||||
|
*
|
||||||
|
* - Correct any insecure secure boot settings
|
||||||
|
*/
|
||||||
|
void esp_secure_boot_init_checks(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
169
components/bootloader_support/src/secure_boot.c
Normal file
169
components/bootloader_support/src/secure_boot.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
#include "esp_efuse_table.h"
|
||||||
|
#include "esp_secure_boot.h"
|
||||||
|
|
||||||
|
#ifndef BOOTLOADER_BUILD
|
||||||
|
static __attribute__((unused)) const char *TAG = "secure_boot";
|
||||||
|
|
||||||
|
#ifdef CONFIG_SECURE_BOOT
|
||||||
|
static void efuse_batch_write_begin(bool *need_fix)
|
||||||
|
{
|
||||||
|
if (*need_fix == false) {
|
||||||
|
esp_efuse_batch_write_begin();
|
||||||
|
}
|
||||||
|
*need_fix = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_efuses(bool need_fix, esp_err_t err)
|
||||||
|
{
|
||||||
|
if (need_fix) {
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Can not be fixed (err=0x%x).", err);
|
||||||
|
esp_efuse_batch_write_cancel();
|
||||||
|
} else {
|
||||||
|
err = esp_efuse_batch_write_commit();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error programming eFuses (err=0x%x)", err);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ESP_LOGI(TAG, "Fixed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||||
|
static esp_err_t secure_boot_v1_check(bool *need_fix)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
esp_efuse_block_t block = EFUSE_BLK_SECURE_BOOT;
|
||||||
|
if (!esp_efuse_get_key_dis_read(block)) {
|
||||||
|
efuse_batch_write_begin(need_fix);
|
||||||
|
ESP_LOGW(TAG, "eFuse BLOCK%d should not be readable. Fixing..", block);
|
||||||
|
err = esp_efuse_set_key_dis_read(block);
|
||||||
|
}
|
||||||
|
if (!esp_efuse_get_key_dis_write(block)) {
|
||||||
|
efuse_batch_write_begin(need_fix);
|
||||||
|
ESP_LOGW(TAG, "eFuse BLOCK%d should not be writeable. Fixing..", block);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
err = esp_efuse_set_key_dis_write(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1 && CONFIG_SECURE_BOOT_V2_ENABLED
|
||||||
|
static esp_err_t secure_boot_v2_check(bool *need_fix)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
esp_efuse_block_t block = EFUSE_BLK_SECURE_BOOT;
|
||||||
|
if (esp_efuse_get_key_dis_read(block)) {
|
||||||
|
ESP_LOGE(TAG, "eFuse BLOCK%d should be readable", block);
|
||||||
|
abort();
|
||||||
|
// This code is not achievable because the bootloader will not boot an app in this state.
|
||||||
|
// But we keep it here just in case (any unexpected behavior).
|
||||||
|
}
|
||||||
|
if (esp_efuse_block_is_empty(block)) {
|
||||||
|
ESP_LOGE(TAG, "eFuse BLOCK%d should not be empty", block);
|
||||||
|
abort();
|
||||||
|
// This code is not achievable because the bootloader will not boot an app in this state.
|
||||||
|
// But we keep it here just in case (any unexpected behavior).
|
||||||
|
}
|
||||||
|
if (!esp_efuse_get_key_dis_write(block)) {
|
||||||
|
efuse_batch_write_begin(need_fix);
|
||||||
|
ESP_LOGW(TAG, "eFuse BLOCK%d should not be writeable. Fixing..", block);
|
||||||
|
err = esp_efuse_set_key_dis_write(block);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1 && CONFIG_SECURE_BOOT_V2_ENABLED
|
||||||
|
static esp_err_t secure_boot_v2_check(bool *need_fix)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
esp_efuse_purpose_t purpose[SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS] = {
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS; ++i) {
|
||||||
|
esp_efuse_block_t block;
|
||||||
|
if (esp_efuse_find_purpose(purpose[i], &block)) {
|
||||||
|
if (!esp_efuse_get_digest_revoke(i)) {
|
||||||
|
if (esp_efuse_get_key_dis_read(block)) {
|
||||||
|
ESP_LOGE(TAG, "eFuse BLOCK%d should be readable", block);
|
||||||
|
abort();
|
||||||
|
// This state is not expected unless the eFuses have been manually misconfigured.
|
||||||
|
}
|
||||||
|
if (esp_efuse_block_is_empty(block)) {
|
||||||
|
ESP_LOGE(TAG, "eFuse BLOCK%d should not be empty", block);
|
||||||
|
abort();
|
||||||
|
// This state is not expected unless the eFuses have been manually misconfigured.
|
||||||
|
}
|
||||||
|
if (!esp_efuse_get_key_dis_write(block)) {
|
||||||
|
efuse_batch_write_begin(need_fix);
|
||||||
|
ESP_LOGW(TAG, "eFuse BLOCK%d should not be writeable. Fixing..", block);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
err = esp_efuse_set_key_dis_write(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!esp_efuse_get_keypurpose_dis_write(block)) {
|
||||||
|
efuse_batch_write_begin(need_fix);
|
||||||
|
ESP_LOGW(TAG, "The KEY_PURPOSE_SECURE_BOOT_DIGEST%d should be write-protected. Fixing..", block);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
err = esp_efuse_set_keypurpose_dis_write(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!esp_efuse_get_digest_revoke(i)) {
|
||||||
|
#ifndef CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS
|
||||||
|
efuse_batch_write_begin(need_fix);
|
||||||
|
ESP_LOGW(TAG, "Unused SECURE_BOOT_DIGEST%d should be revoked. Fixing..", i);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
err = esp_efuse_set_digest_revoke(i);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
ESP_LOGW(TAG, "Unused SECURE_BOOT_DIGEST%d should be revoked. It will not be fixed due to the config", i);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif // CONFIG_SECURE_BOOT
|
||||||
|
|
||||||
|
void esp_secure_boot_init_checks(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SECURE_BOOT
|
||||||
|
|
||||||
|
if (esp_secure_boot_enabled()) {
|
||||||
|
bool need_fix = false;
|
||||||
|
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||||
|
esp_err_t err = secure_boot_v1_check(&need_fix);
|
||||||
|
#else
|
||||||
|
esp_err_t err = secure_boot_v2_check(&need_fix);
|
||||||
|
#endif
|
||||||
|
update_efuses(need_fix, err);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Mismatch in secure boot settings: the app config is enabled but eFuse not");
|
||||||
|
}
|
||||||
|
#endif // CONFIG_SECURE_BOOT
|
||||||
|
}
|
||||||
|
#endif // not BOOTLOADER_BUILD
|
@ -31,7 +31,7 @@
|
|||||||
#include "hal/adc_types.h"
|
#include "hal/adc_types.h"
|
||||||
#include "hal/adc_hal.h"
|
#include "hal/adc_hal.h"
|
||||||
#include "hal/dma_types.h"
|
#include "hal/dma_types.h"
|
||||||
#include "esp32c3/esp_efuse_rtc_calib.h"
|
#include "esp_efuse_rtc_calib.h"
|
||||||
#include "esp_private/gdma.h"
|
#include "esp_private/gdma.h"
|
||||||
|
|
||||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "driver/rtc_cntl.h"
|
#include "driver/rtc_cntl.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/adc.h"
|
#include "driver/adc.h"
|
||||||
#include "esp32s2/esp_efuse_rtc_table.h"
|
#include "esp_efuse_rtc_table.h"
|
||||||
|
|
||||||
#include "hal/adc_types.h"
|
#include "hal/adc_types.h"
|
||||||
#include "hal/adc_hal.h"
|
#include "hal/adc_hal.h"
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include "driver/temp_sensor.h"
|
#include "driver/temp_sensor.h"
|
||||||
#include "regi2c_ctrl.h"
|
#include "regi2c_ctrl.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp32s2/esp_efuse_rtc_table.h"
|
#include "esp_efuse_rtc_table.h"
|
||||||
|
|
||||||
static const char *TAG = "tsens";
|
static const char *TAG = "tsens";
|
||||||
|
|
||||||
|
@ -4,26 +4,23 @@ if(EXISTS "${COMPONENT_DIR}/${target}")
|
|||||||
include(${COMPONENT_DIR}/${target}/sources.cmake)
|
include(${COMPONENT_DIR}/${target}/sources.cmake)
|
||||||
spaces2list(EFUSE_SOC_SRCS)
|
spaces2list(EFUSE_SOC_SRCS)
|
||||||
set(include_dirs include ${target}/include)
|
set(include_dirs include ${target}/include)
|
||||||
|
set(private_include private_include ${target}/private_include)
|
||||||
add_prefix(srcs "${target}/" ${EFUSE_SOC_SRCS})
|
add_prefix(srcs "${target}/" ${EFUSE_SOC_SRCS})
|
||||||
list(APPEND srcs "src/${target}/esp_efuse_api.c"
|
|
||||||
"src/${target}/esp_efuse_fields.c"
|
|
||||||
"src/${target}/esp_efuse_utility.c")
|
|
||||||
if("esp32s2" STREQUAL "${target}")
|
|
||||||
list(APPEND srcs "src/${target}/esp_efuse_rtc_table.c")
|
|
||||||
endif()
|
|
||||||
if("esp32c3" STREQUAL "${target}")
|
|
||||||
list(APPEND srcs "src/${target}/esp_efuse_rtc_calib.c")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND srcs "src/esp_efuse_api.c"
|
list(APPEND srcs "src/esp_efuse_api.c"
|
||||||
"src/esp_efuse_fields.c"
|
"src/esp_efuse_fields.c"
|
||||||
"src/esp_efuse_utility.c")
|
"src/esp_efuse_utility.c")
|
||||||
|
if("esp32" STREQUAL "${target}")
|
||||||
|
list(APPEND srcs "src/esp_efuse_api_key_esp32.c")
|
||||||
|
else()
|
||||||
|
list(APPEND srcs "src/esp_efuse_api_key_esp32xx.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
PRIV_REQUIRES bootloader_support soc spi_flash
|
PRIV_REQUIRES bootloader_support soc spi_flash
|
||||||
INCLUDE_DIRS "${include_dirs}"
|
INCLUDE_DIRS "${include_dirs}"
|
||||||
PRIV_INCLUDE_DIRS private_include)
|
PRIV_INCLUDE_DIRS "${private_include}")
|
||||||
|
|
||||||
if(target)
|
if(target)
|
||||||
set(TOOL_TARGET -t ${target})
|
set(TOOL_TARGET -t ${target})
|
||||||
|
@ -3,8 +3,12 @@
|
|||||||
# currently the only SoC supported; to be moved into Kconfig
|
# currently the only SoC supported; to be moved into Kconfig
|
||||||
TARGET := $(IDF_TARGET)
|
TARGET := $(IDF_TARGET)
|
||||||
|
|
||||||
COMPONENT_SRCDIRS := $(TARGET) src src/$(TARGET)
|
COMPONENT_SRCDIRS := $(TARGET) src
|
||||||
COMPONENT_PRIV_INCLUDEDIRS := private_include
|
ifdef CONFIG_IDF_TARGET_ESP32
|
||||||
COMPONENT_ADD_INCLUDEDIRS := $(TARGET)/include include
|
COMPONENT_OBJEXCLUDE := src/esp_efuse_api_key_esp32xx.o
|
||||||
|
else
|
||||||
|
COMPONENT_OBJEXCLUDE := src/esp_efuse_api_key_esp32.o
|
||||||
|
endif
|
||||||
|
|
||||||
-include $(COMPONENT_PATH)/$(TARGET)/component.mk
|
COMPONENT_PRIV_INCLUDEDIRS := private_include $(TARGET)/private_include
|
||||||
|
COMPONENT_ADD_INCLUDEDIRS := include $(TARGET)/include
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
54
components/efuse/esp32/include/esp_efuse.h
Normal file
54
components/efuse/esp32/include/esp_efuse.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of eFuse blocks for ESP32
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
EFUSE_BLK0 = 0, /**< Number of eFuse block. Reserved. */
|
||||||
|
|
||||||
|
EFUSE_BLK1 = 1, /**< Number of eFuse block. Used for Flash Encryption. If not using that Flash Encryption feature, they can be used for another purpose. */
|
||||||
|
EFUSE_BLK_KEY0 = 1, /**< Number of eFuse block. Used for Flash Encryption. If not using that Flash Encryption feature, they can be used for another purpose. */
|
||||||
|
EFUSE_BLK_ENCRYPT_FLASH = 1, /**< Number of eFuse block. Used for Flash Encryption. If not using that Flash Encryption feature, they can be used for another purpose. */
|
||||||
|
|
||||||
|
EFUSE_BLK2 = 2, /**< Number of eFuse block. Used for Secure Boot. If not using that Secure Boot feature, they can be used for another purpose. */
|
||||||
|
EFUSE_BLK_KEY1 = 2, /**< Number of eFuse block. Used for Secure Boot. If not using that Secure Boot feature, they can be used for another purpose. */
|
||||||
|
EFUSE_BLK_SECURE_BOOT = 2, /**< Number of eFuse block. Used for Secure Boot. If not using that Secure Boot feature, they can be used for another purpose. */
|
||||||
|
|
||||||
|
EFUSE_BLK3 = 3, /**< Number of eFuse block. Uses for the purpose of the user. */
|
||||||
|
EFUSE_BLK_KEY2 = 3, /**< Number of eFuse block. Uses for the purpose of the user. */
|
||||||
|
EFUSE_BLK_KEY_MAX = 4,
|
||||||
|
|
||||||
|
EFUSE_BLK_MAX = 4,
|
||||||
|
} esp_efuse_block_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of coding scheme
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
EFUSE_CODING_SCHEME_NONE = 0, /**< None */
|
||||||
|
EFUSE_CODING_SCHEME_3_4 = 1, /**< 3/4 coding */
|
||||||
|
EFUSE_CODING_SCHEME_REPEAT = 2, /**< Repeat coding */
|
||||||
|
} esp_efuse_coding_scheme_t;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
@ -1 +1,3 @@
|
|||||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c")
|
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
|
||||||
|
"esp_efuse_fields.c"
|
||||||
|
"esp_efuse_utility.c")
|
||||||
|
@ -1 +1,4 @@
|
|||||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c")
|
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
|
||||||
|
"esp_efuse_fields.c"
|
||||||
|
"esp_efuse_rtc_calib.c"
|
||||||
|
"esp_efuse_utility.c")
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "esp32s2/esp_efuse_rtc_table.h"
|
#include "esp_efuse_rtc_table.h"
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "esp_efuse_table.h"
|
#include "esp_efuse_table.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
@ -1 +1,4 @@
|
|||||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c")
|
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
|
||||||
|
"esp_efuse_fields.c"
|
||||||
|
"esp_efuse_rtc_table.c"
|
||||||
|
"esp_efuse_utility.c")
|
||||||
|
@ -1 +1,3 @@
|
|||||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c")
|
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
|
||||||
|
"esp_efuse_fields.c"
|
||||||
|
"esp_efuse_utility.c")
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type of eFuse blocks for ESP32
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
EFUSE_BLK0 = 0, /**< Number of eFuse block. Reserved. */
|
|
||||||
EFUSE_BLK1 = 1, /**< Number of eFuse block. Used for Flash Encryption. If not using that Flash Encryption feature, they can be used for another purpose. */
|
|
||||||
EFUSE_BLK2 = 2, /**< Number of eFuse block. Used for Secure Boot. If not using that Secure Boot feature, they can be used for another purpose. */
|
|
||||||
EFUSE_BLK3 = 3, /**< Number of eFuse block. Uses for the purpose of the user. */
|
|
||||||
EFUSE_BLK_MAX
|
|
||||||
} esp_efuse_block_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type of coding scheme
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
EFUSE_CODING_SCHEME_NONE = 0, /**< None */
|
|
||||||
EFUSE_CODING_SCHEME_3_4 = 1, /**< 3/4 coding */
|
|
||||||
EFUSE_CODING_SCHEME_REPEAT = 2, /**< Repeat coding */
|
|
||||||
} esp_efuse_coding_scheme_t;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -23,15 +23,7 @@ extern "C" {
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#include_next "esp_efuse.h"
|
||||||
#include "esp32/esp_efuse.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#include "esp32s2/esp_efuse.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
#include "esp32s3/esp_efuse.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
#include "esp32c3/esp_efuse.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */
|
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */
|
||||||
#define ESP_OK_EFUSE_CNT (ESP_ERR_EFUSE + 0x01) /*!< OK the required number of bits is set. */
|
#define ESP_OK_EFUSE_CNT (ESP_ERR_EFUSE + 0x01) /*!< OK the required number of bits is set. */
|
||||||
@ -496,48 +488,14 @@ esp_err_t esp_efuse_batch_write_cancel(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_efuse_batch_write_commit(void);
|
esp_err_t esp_efuse_batch_write_commit(void);
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Type of key purpose
|
* @brief Checks that the given block is empty.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - True: The block is empty.
|
||||||
|
* - False: The block is not empty or was an error.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
bool esp_efuse_block_is_empty(esp_efuse_block_t block);
|
||||||
ESP_EFUSE_KEY_PURPOSE_USER = 0,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_RESERVED = 1,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 = 2,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 = 3,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY = 4,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE = 7,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_HMAC_UP = 8,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0 = 9,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1 = 10,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 = 11,
|
|
||||||
ESP_EFUSE_KEY_PURPOSE_MAX,
|
|
||||||
} esp_efuse_purpose_t;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a pointer to a key purpose for an efuse key block.
|
|
||||||
*
|
|
||||||
* @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX
|
|
||||||
*
|
|
||||||
* To get the value of this field use esp_efuse_read_field_blob() or esp_efuse_get_key_purpose().
|
|
||||||
*
|
|
||||||
* @return Pointer: If Successful returns a pointer to the corresponding efuse field otherwise NULL.
|
|
||||||
*/
|
|
||||||
const esp_efuse_desc_t **esp_efuse_get_purpose_field(esp_efuse_block_t block);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns a pointer to a key block.
|
|
||||||
*
|
|
||||||
* @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX
|
|
||||||
*
|
|
||||||
* @return Pointer: If Successful returns a pointer to the corresponding efuse field otherwise NULL.
|
|
||||||
*/
|
|
||||||
const esp_efuse_desc_t** esp_efuse_get_key(esp_efuse_block_t block);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a read protection for the key block.
|
* @brief Returns a read protection for the key block.
|
||||||
@ -585,6 +543,62 @@ bool esp_efuse_get_key_dis_write(esp_efuse_block_t block);
|
|||||||
*/
|
*/
|
||||||
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block);
|
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the key block is unused, false otherwise.
|
||||||
|
*
|
||||||
|
* An unused key block is all zero content, not read or write protected,
|
||||||
|
* and has purpose 0 (ESP_EFUSE_KEY_PURPOSE_USER)
|
||||||
|
*
|
||||||
|
* @param block key block to check.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - True if key block is unused,
|
||||||
|
* - False if key block is used or the specified block index is not a key block.
|
||||||
|
*/
|
||||||
|
bool esp_efuse_key_block_unused(esp_efuse_block_t block);
|
||||||
|
|
||||||
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of key purpose
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_USER = 0,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_RESERVED = 1,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 = 2,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 = 3,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY = 4,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE = 7,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_UP = 8,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0 = 9,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1 = 10,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 = 11,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_MAX,
|
||||||
|
} esp_efuse_purpose_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a pointer to a key purpose for an efuse key block.
|
||||||
|
*
|
||||||
|
* @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX
|
||||||
|
*
|
||||||
|
* To get the value of this field use esp_efuse_read_field_blob() or esp_efuse_get_key_purpose().
|
||||||
|
*
|
||||||
|
* @return Pointer: If Successful returns a pointer to the corresponding efuse field otherwise NULL.
|
||||||
|
*/
|
||||||
|
const esp_efuse_desc_t **esp_efuse_get_purpose_field(esp_efuse_block_t block);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a pointer to a key block.
|
||||||
|
*
|
||||||
|
* @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX
|
||||||
|
*
|
||||||
|
* @return Pointer: If Successful returns a pointer to the corresponding efuse field otherwise NULL.
|
||||||
|
*/
|
||||||
|
const esp_efuse_desc_t** esp_efuse_get_key(esp_efuse_block_t block);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the current purpose set for an efuse key block.
|
* @brief Returns the current purpose set for an efuse key block.
|
||||||
*
|
*
|
||||||
@ -660,20 +674,6 @@ esp_efuse_block_t esp_efuse_find_unused_key_block(void);
|
|||||||
*/
|
*/
|
||||||
unsigned esp_efuse_count_unused_key_blocks(void);
|
unsigned esp_efuse_count_unused_key_blocks(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Returns true if the key block is unused, false otherwise.
|
|
||||||
*
|
|
||||||
* An unused key block is all zero content, not read or write protected,
|
|
||||||
* and has purpose 0 (ESP_EFUSE_KEY_PURPOSE_USER)
|
|
||||||
*
|
|
||||||
* @param block key block to check.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - True if key block is unused,
|
|
||||||
* - False if key block is used or the specified block index is not a key block.
|
|
||||||
*/
|
|
||||||
bool esp_efuse_key_block_unused(esp_efuse_block_t block);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the status of the Secure Boot public key digest revocation bit.
|
* @brief Returns the status of the Secure Boot public key digest revocation bit.
|
||||||
*
|
*
|
||||||
|
@ -23,15 +23,7 @@ extern "C" {
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#include_next "esp_efuse_utility.h"
|
||||||
#include "esp32/esp_efuse_utility.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
||||||
#include "esp32s2/esp_efuse_utility.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
||||||
#include "esp32s3/esp_efuse_utility.h"
|
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
#include "esp32c3/esp_efuse_utility.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Structure range address by blocks
|
* @brief Structure range address by blocks
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_efuse.h"
|
|
||||||
#include "esp_efuse_utility.h"
|
|
||||||
#include "soc/efuse_periph.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "esp_efuse_table.h"
|
|
||||||
|
|
||||||
const static char *TAG = "efuse";
|
|
||||||
|
|
||||||
// Sets a write protection for the whole block.
|
|
||||||
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK1) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK2) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK3) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK3, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read protect for blk.
|
|
||||||
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK1) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_BLK1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK2) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_BLK2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK3) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_BLK3, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get efuse coding_scheme.
|
|
||||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
esp_efuse_coding_scheme_t scheme;
|
|
||||||
if (blk == EFUSE_BLK0) {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
|
||||||
} else {
|
|
||||||
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
|
||||||
if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE ||
|
|
||||||
coding_scheme == (EFUSE_CODING_SCHEME_VAL_34 | EFUSE_CODING_SCHEME_VAL_REPEAT)) {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
|
||||||
} else if (coding_scheme == EFUSE_CODING_SCHEME_VAL_34) {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_3_4;
|
|
||||||
} else {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_REPEAT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ESP_EARLY_LOGD(TAG, "coding scheme %d", scheme);
|
|
||||||
return scheme;
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_efuse.h"
|
|
||||||
#include "esp_efuse_utility.h"
|
|
||||||
#include "soc/efuse_periph.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "esp_efuse_table.h"
|
|
||||||
|
|
||||||
const static char *TAG = "efuse";
|
|
||||||
|
|
||||||
// Sets a write protection for the whole block.
|
|
||||||
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK1) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK2) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK3) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_USER_DATA, 1);
|
|
||||||
} else if (blk == EFUSE_BLK4) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY0, 1);
|
|
||||||
} else if (blk == EFUSE_BLK5) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK6) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK7) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY3, 1);
|
|
||||||
} else if (blk == EFUSE_BLK8) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY4, 1);
|
|
||||||
} else if (blk == EFUSE_BLK9) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY5, 1);
|
|
||||||
} else if (blk == EFUSE_BLK10) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART2, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read protect for blk.
|
|
||||||
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK4) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY0, 1);
|
|
||||||
} else if (blk == EFUSE_BLK5) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK6) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK7) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY3, 1);
|
|
||||||
} else if (blk == EFUSE_BLK8) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY4, 1);
|
|
||||||
} else if (blk == EFUSE_BLK9) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY5, 1);
|
|
||||||
} else if (blk == EFUSE_BLK10) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_SYS_DATA_PART2, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get efuse coding_scheme.
|
|
||||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
esp_efuse_coding_scheme_t scheme;
|
|
||||||
if (blk == EFUSE_BLK0) {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
|
||||||
} else {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_RS;
|
|
||||||
}
|
|
||||||
ESP_LOGD(TAG, "coding scheme %d", scheme);
|
|
||||||
return scheme;
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_efuse.h"
|
|
||||||
#include "esp_efuse_utility.h"
|
|
||||||
#include "soc/efuse_periph.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "esp_efuse_table.h"
|
|
||||||
|
|
||||||
const static char *TAG = "efuse";
|
|
||||||
|
|
||||||
// Sets a write protection for the whole block.
|
|
||||||
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK1) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK2) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK3) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_USER_DATA, 1);
|
|
||||||
} else if (blk == EFUSE_BLK4) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY0, 1);
|
|
||||||
} else if (blk == EFUSE_BLK5) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK6) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK7) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY3, 1);
|
|
||||||
} else if (blk == EFUSE_BLK8) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY4, 1);
|
|
||||||
} else if (blk == EFUSE_BLK9) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY5, 1);
|
|
||||||
} else if (blk == EFUSE_BLK10) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART2, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read protect for blk.
|
|
||||||
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK4) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY0, 1);
|
|
||||||
} else if (blk == EFUSE_BLK5) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK6) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK7) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY3, 1);
|
|
||||||
} else if (blk == EFUSE_BLK8) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY4, 1);
|
|
||||||
} else if (blk == EFUSE_BLK9) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY5, 1);
|
|
||||||
} else if (blk == EFUSE_BLK10) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_SYS_DATA_PART2, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get efuse coding_scheme.
|
|
||||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
esp_efuse_coding_scheme_t scheme;
|
|
||||||
if (blk == EFUSE_BLK0) {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
|
||||||
} else {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_RS;
|
|
||||||
}
|
|
||||||
ESP_EARLY_LOGD(TAG, "coding scheme %d", scheme);
|
|
||||||
return scheme;
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_efuse.h"
|
|
||||||
#include "esp_efuse_utility.h"
|
|
||||||
#include "soc/efuse_periph.h"
|
|
||||||
#include "assert.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "esp_efuse_table.h"
|
|
||||||
|
|
||||||
const static char *TAG = "efuse";
|
|
||||||
|
|
||||||
// Sets a write protection for the whole block.
|
|
||||||
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK1) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK2) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK3) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_USER_DATA, 1);
|
|
||||||
} else if (blk == EFUSE_BLK4) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY0, 1);
|
|
||||||
} else if (blk == EFUSE_BLK5) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK6) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK7) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY3, 1);
|
|
||||||
} else if (blk == EFUSE_BLK8) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY4, 1);
|
|
||||||
} else if (blk == EFUSE_BLK9) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_KEY5, 1);
|
|
||||||
} else if (blk == EFUSE_BLK10) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART2, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// read protect for blk.
|
|
||||||
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
if (blk == EFUSE_BLK4) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY0, 1);
|
|
||||||
} else if (blk == EFUSE_BLK5) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY1, 1);
|
|
||||||
} else if (blk == EFUSE_BLK6) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY2, 1);
|
|
||||||
} else if (blk == EFUSE_BLK7) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY3, 1);
|
|
||||||
} else if (blk == EFUSE_BLK8) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY4, 1);
|
|
||||||
} else if (blk == EFUSE_BLK9) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_KEY5, 1);
|
|
||||||
} else if (blk == EFUSE_BLK10) {
|
|
||||||
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_SYS_DATA_PART2, 1);
|
|
||||||
}
|
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get efuse coding_scheme.
|
|
||||||
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
|
||||||
{
|
|
||||||
esp_efuse_coding_scheme_t scheme;
|
|
||||||
if (blk == EFUSE_BLK0) {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_NONE;
|
|
||||||
} else {
|
|
||||||
scheme = EFUSE_CODING_SCHEME_RS;
|
|
||||||
}
|
|
||||||
ESP_EARLY_LOGD(TAG, "coding scheme %d", scheme);
|
|
||||||
return scheme;
|
|
||||||
}
|
|
@ -282,307 +282,3 @@ esp_err_t esp_efuse_batch_write_commit(void)
|
|||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Keys and their attributes are packed into a structure
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
const esp_efuse_desc_t** key; /**< Key */
|
|
||||||
const esp_efuse_desc_t** keypurpose; /**< Key purpose */
|
|
||||||
const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
|
|
||||||
const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
|
|
||||||
const esp_efuse_desc_t** keypurpose_wr_dis; /**< Write protection of a key purpose*/
|
|
||||||
} esp_efuse_keys_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const esp_efuse_desc_t** revoke;
|
|
||||||
const esp_efuse_desc_t** revoke_wr_dis;
|
|
||||||
} esp_efuse_revokes_t;
|
|
||||||
|
|
||||||
const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
|
|
||||||
{ESP_EFUSE_KEY0, ESP_EFUSE_KEY_PURPOSE_0, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0_PURPOSE},
|
|
||||||
{ESP_EFUSE_KEY1, ESP_EFUSE_KEY_PURPOSE_1, ESP_EFUSE_RD_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1_PURPOSE},
|
|
||||||
{ESP_EFUSE_KEY2, ESP_EFUSE_KEY_PURPOSE_2, ESP_EFUSE_RD_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2_PURPOSE},
|
|
||||||
{ESP_EFUSE_KEY3, ESP_EFUSE_KEY_PURPOSE_3, ESP_EFUSE_RD_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3_PURPOSE},
|
|
||||||
{ESP_EFUSE_KEY4, ESP_EFUSE_KEY_PURPOSE_4, ESP_EFUSE_RD_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4_PURPOSE},
|
|
||||||
{ESP_EFUSE_KEY5, ESP_EFUSE_KEY_PURPOSE_5, ESP_EFUSE_RD_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5_PURPOSE},
|
|
||||||
#if 0
|
|
||||||
{ESP_EFUSE_KEY6, ESP_EFUSE_KEY_PURPOSE_6, ESP_EFUSE_RD_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6_PURPOSE},
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
const esp_efuse_revokes_t s_revoke_table[] = {
|
|
||||||
{ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0},
|
|
||||||
{ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1},
|
|
||||||
{ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2},
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ESP_EFUSE_CHK(ret) \
|
|
||||||
do \
|
|
||||||
{ \
|
|
||||||
if( ( err = (ret) ) != ESP_OK ) \
|
|
||||||
goto err_exit; \
|
|
||||||
} while( 0 )
|
|
||||||
|
|
||||||
|
|
||||||
const esp_efuse_desc_t **esp_efuse_get_purpose_field(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
switch(block) {
|
|
||||||
case EFUSE_BLK_KEY0:
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_0;
|
|
||||||
case EFUSE_BLK_KEY1:
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_1;
|
|
||||||
case EFUSE_BLK_KEY2:
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_2;
|
|
||||||
case EFUSE_BLK_KEY3:
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_3;
|
|
||||||
case EFUSE_BLK_KEY4:
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_4;
|
|
||||||
case EFUSE_BLK_KEY5:
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_5;
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const esp_efuse_desc_t** esp_efuse_get_key(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
return s_table[idx].key;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
const uint8_t one = 1;
|
|
||||||
return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &one, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
const uint8_t one = 1;
|
|
||||||
return esp_efuse_write_field_blob(s_table[idx].key_wr_dis, &one, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_MAX;
|
|
||||||
}
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
uint8_t value = 0;
|
|
||||||
esp_err_t err = esp_efuse_read_field_blob(s_table[idx].keypurpose, &value, s_table[idx].keypurpose[0]->bit_count);
|
|
||||||
if (err != ESP_OK) {
|
|
||||||
return ESP_EFUSE_KEY_PURPOSE_MAX;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
return esp_efuse_write_field_blob(s_table[idx].keypurpose, &purpose, s_table[idx].keypurpose[0]->bit_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
return esp_efuse_read_field_bit(s_table[idx].keypurpose_wr_dis);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
const uint8_t one = 1;
|
|
||||||
return esp_efuse_write_field_blob(s_table[idx].keypurpose_wr_dis, &one, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block)
|
|
||||||
{
|
|
||||||
esp_efuse_block_t dummy;
|
|
||||||
if (block == NULL) {
|
|
||||||
block = &dummy;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
|
|
||||||
if (esp_efuse_get_key_purpose(b) == purpose) {
|
|
||||||
*block = b;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_efuse_block_t esp_efuse_find_unused_key_block(void)
|
|
||||||
{
|
|
||||||
for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
|
|
||||||
if (esp_efuse_key_block_unused(b)) {
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return EFUSE_BLK_KEY_MAX; // nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned esp_efuse_count_unused_key_blocks(void)
|
|
||||||
{
|
|
||||||
unsigned r = 0;
|
|
||||||
for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
|
|
||||||
if (esp_efuse_key_block_unused(b)) {
|
|
||||||
r++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_key_block_unused(esp_efuse_block_t block)
|
|
||||||
{
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
|
||||||
return false; // Not a key block
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_efuse_get_key_purpose(block) != ESP_EFUSE_KEY_PURPOSE_USER ||
|
|
||||||
esp_efuse_get_keypurpose_dis_write(block) ||
|
|
||||||
esp_efuse_get_key_dis_read(block) ||
|
|
||||||
esp_efuse_get_key_dis_write(block)) {
|
|
||||||
return false; // Block in use!
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
|
||||||
if (esp_efuse_read_reg(block, i) != 0) {
|
|
||||||
return false; // Block in use!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true; // Unused
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_get_digest_revoke(unsigned num_digest)
|
|
||||||
{
|
|
||||||
assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
|
|
||||||
return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_set_digest_revoke(unsigned num_digest)
|
|
||||||
{
|
|
||||||
if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest)
|
|
||||||
{
|
|
||||||
assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
|
|
||||||
return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest)
|
|
||||||
{
|
|
||||||
if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpose, const void *key, size_t key_size_bytes)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_efuse_batch_write_begin();
|
|
||||||
|
|
||||||
if (!esp_efuse_key_block_unused(block)) {
|
|
||||||
err = ESP_ERR_INVALID_STATE;
|
|
||||||
} else {
|
|
||||||
unsigned idx = block - EFUSE_BLK_KEY0;
|
|
||||||
ESP_EFUSE_CHK(esp_efuse_write_field_blob(s_table[idx].key, key, key_size_bytes * 8));
|
|
||||||
ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
|
|
||||||
if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 ||
|
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ||
|
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY ||
|
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL ||
|
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG ||
|
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE ||
|
|
||||||
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
|
|
||||||
ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block));
|
|
||||||
}
|
|
||||||
ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose));
|
|
||||||
ESP_EFUSE_CHK(esp_efuse_set_keypurpose_dis_write(block));
|
|
||||||
return esp_efuse_batch_write_commit();
|
|
||||||
}
|
|
||||||
err_exit:
|
|
||||||
esp_efuse_batch_write_cancel();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_efuse_write_keys(esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys)
|
|
||||||
{
|
|
||||||
esp_err_t err = ESP_OK;
|
|
||||||
if (number_of_keys == 0 || number_of_keys > (EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) || keys == NULL || purposes == NULL) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_efuse_purpose_t purpose = 0;
|
|
||||||
esp_efuse_block_t block = EFUSE_BLK_KEY0;
|
|
||||||
|
|
||||||
esp_efuse_batch_write_begin();
|
|
||||||
|
|
||||||
unsigned unused_keys = esp_efuse_count_unused_key_blocks();
|
|
||||||
if (number_of_keys > unused_keys) {
|
|
||||||
ESP_LOGE(TAG, "Not enough unused key blocks available. Required %d, was %d", number_of_keys, unused_keys);
|
|
||||||
err = ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS;
|
|
||||||
} else {
|
|
||||||
for (int i_key = 0; (block < EFUSE_BLK_KEY_MAX) && (i_key < number_of_keys); block++) {
|
|
||||||
if (esp_efuse_key_block_unused(block)) {
|
|
||||||
purpose = purposes[i_key];
|
|
||||||
ESP_LOGI(TAG, "Writing EFUSE_BLK_KEY%d with purpose %d", block - EFUSE_BLK_KEY0, purpose);
|
|
||||||
ESP_EFUSE_CHK(esp_efuse_write_key(block, purpose, keys[i_key], 32));
|
|
||||||
i_key++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return esp_efuse_batch_write_commit();
|
|
||||||
err_exit:
|
|
||||||
ESP_LOGE(TAG, "Failed to write EFUSE_BLK_KEY%d with purpose %d. Can't continue.", block - EFUSE_BLK_KEY0, purpose);
|
|
||||||
}
|
|
||||||
esp_efuse_batch_write_cancel();
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // not CONFIG_IDF_TARGET_ESP32
|
|
||||||
|
148
components/efuse/src/esp_efuse_api_key_esp32.c
Normal file
148
components/efuse/src/esp_efuse_api_key_esp32.c
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
#include "esp_efuse_utility.h"
|
||||||
|
#include "soc/efuse_periph.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_efuse_table.h"
|
||||||
|
|
||||||
|
static __attribute__((unused)) const char *TAG = "efuse";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Keys and their attributes are packed into a structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
|
||||||
|
const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
|
||||||
|
} esp_efuse_keys_t;
|
||||||
|
|
||||||
|
const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
|
||||||
|
{ESP_EFUSE_RD_DIS_BLK1, ESP_EFUSE_WR_DIS_BLK1},
|
||||||
|
{ESP_EFUSE_RD_DIS_BLK2, ESP_EFUSE_WR_DIS_BLK2},
|
||||||
|
{ESP_EFUSE_RD_DIS_BLK3, ESP_EFUSE_WR_DIS_BLK3},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Sets a write protection for the whole block.
|
||||||
|
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
||||||
|
{
|
||||||
|
if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX) {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
unsigned idx = blk - EFUSE_BLK1;
|
||||||
|
return esp_efuse_write_field_cnt(s_table[idx].key_wr_dis, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read protect for blk.
|
||||||
|
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
||||||
|
{
|
||||||
|
if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX) {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
unsigned idx = blk - EFUSE_BLK1;
|
||||||
|
return esp_efuse_write_field_cnt(s_table[idx].key_rd_dis, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get efuse coding_scheme.
|
||||||
|
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
||||||
|
{
|
||||||
|
esp_efuse_coding_scheme_t scheme;
|
||||||
|
if (blk == EFUSE_BLK0) {
|
||||||
|
scheme = EFUSE_CODING_SCHEME_NONE;
|
||||||
|
} else {
|
||||||
|
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
||||||
|
if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE ||
|
||||||
|
coding_scheme == (EFUSE_CODING_SCHEME_VAL_34 | EFUSE_CODING_SCHEME_VAL_REPEAT)) {
|
||||||
|
scheme = EFUSE_CODING_SCHEME_NONE;
|
||||||
|
} else if (coding_scheme == EFUSE_CODING_SCHEME_VAL_34) {
|
||||||
|
scheme = EFUSE_CODING_SCHEME_3_4;
|
||||||
|
} else {
|
||||||
|
scheme = EFUSE_CODING_SCHEME_REPEAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_block_is_empty(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
unsigned blk_len_bit = 256;
|
||||||
|
uint32_t key[8];
|
||||||
|
if (esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4) {
|
||||||
|
blk_len_bit = 192;
|
||||||
|
}
|
||||||
|
esp_err_t err = esp_efuse_read_block(block, &key, 0, blk_len_bit);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned zeros = 0;
|
||||||
|
for (unsigned i = 0; i < blk_len_bit / 32; ++i) {
|
||||||
|
if (key[i] == 0) {
|
||||||
|
++zeros;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (zeros == blk_len_bit / 32) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
const uint8_t one = 1;
|
||||||
|
return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &one, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
const uint8_t one = 1;
|
||||||
|
return esp_efuse_write_field_blob(s_table[idx].key_wr_dis, &one, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_key_block_unused(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return false; // Not a key block
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esp_efuse_get_key_dis_read(block) || esp_efuse_get_key_dis_write(block) ||
|
||||||
|
!esp_efuse_block_is_empty(block)) {
|
||||||
|
return false; // Block in use!
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Unused
|
||||||
|
}
|
371
components/efuse/src/esp_efuse_api_key_esp32xx.c
Normal file
371
components/efuse/src/esp_efuse_api_key_esp32xx.c
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
#include "esp_efuse_utility.h"
|
||||||
|
#include "soc/efuse_periph.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_efuse_table.h"
|
||||||
|
|
||||||
|
const static char *TAG = "efuse";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Keys and their attributes are packed into a structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const esp_efuse_desc_t** key; /**< Key */
|
||||||
|
const esp_efuse_desc_t** keypurpose; /**< Key purpose */
|
||||||
|
const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
|
||||||
|
const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
|
||||||
|
const esp_efuse_desc_t** keypurpose_wr_dis; /**< Write protection of a key purpose*/
|
||||||
|
} esp_efuse_keys_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const esp_efuse_desc_t** revoke;
|
||||||
|
const esp_efuse_desc_t** revoke_wr_dis;
|
||||||
|
} esp_efuse_revokes_t;
|
||||||
|
|
||||||
|
const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
|
||||||
|
{ESP_EFUSE_KEY0, ESP_EFUSE_KEY_PURPOSE_0, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0_PURPOSE},
|
||||||
|
{ESP_EFUSE_KEY1, ESP_EFUSE_KEY_PURPOSE_1, ESP_EFUSE_RD_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1_PURPOSE},
|
||||||
|
{ESP_EFUSE_KEY2, ESP_EFUSE_KEY_PURPOSE_2, ESP_EFUSE_RD_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2_PURPOSE},
|
||||||
|
{ESP_EFUSE_KEY3, ESP_EFUSE_KEY_PURPOSE_3, ESP_EFUSE_RD_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3_PURPOSE},
|
||||||
|
{ESP_EFUSE_KEY4, ESP_EFUSE_KEY_PURPOSE_4, ESP_EFUSE_RD_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4_PURPOSE},
|
||||||
|
{ESP_EFUSE_KEY5, ESP_EFUSE_KEY_PURPOSE_5, ESP_EFUSE_RD_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5_PURPOSE},
|
||||||
|
#if 0
|
||||||
|
{ESP_EFUSE_KEY6, ESP_EFUSE_KEY_PURPOSE_6, ESP_EFUSE_RD_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6_PURPOSE},
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const esp_efuse_revokes_t s_revoke_table[] = {
|
||||||
|
{ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0},
|
||||||
|
{ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1},
|
||||||
|
{ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ESP_EFUSE_CHK(ret) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if( ( err = (ret) ) != ESP_OK ) \
|
||||||
|
goto err_exit; \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
bool esp_efuse_block_is_empty(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
const unsigned blk_len_bit = 256;
|
||||||
|
uint32_t key[8];
|
||||||
|
esp_err_t err = esp_efuse_read_block(block, &key, 0, blk_len_bit);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned zeros = 0;
|
||||||
|
for (unsigned i = 0; i < blk_len_bit / 32; ++i) {
|
||||||
|
if (key[i] == 0) {
|
||||||
|
++zeros;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (zeros == blk_len_bit / 32) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets a write protection for the whole block.
|
||||||
|
esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
|
||||||
|
{
|
||||||
|
if (blk == EFUSE_BLK1) {
|
||||||
|
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_BLK1, 1);
|
||||||
|
} else if (blk == EFUSE_BLK2) {
|
||||||
|
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART1, 1);
|
||||||
|
} else if (blk == EFUSE_BLK3) {
|
||||||
|
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_USER_DATA, 1);
|
||||||
|
} else if (blk == EFUSE_BLK10) {
|
||||||
|
return esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_SYS_DATA_PART2, 1);
|
||||||
|
} else if (blk >= EFUSE_BLK_KEY0 && blk < EFUSE_BLK_KEY_MAX) {
|
||||||
|
unsigned idx = blk - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_write_field_cnt(s_table[idx].key_wr_dis, 1);
|
||||||
|
}
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read protect for blk.
|
||||||
|
esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
|
||||||
|
{
|
||||||
|
if (blk >= EFUSE_BLK_KEY0 && blk < EFUSE_BLK_KEY_MAX) {
|
||||||
|
unsigned idx = blk - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_write_field_cnt(s_table[idx].key_rd_dis, 1);
|
||||||
|
} else if (blk == EFUSE_BLK10) {
|
||||||
|
return esp_efuse_write_field_cnt(ESP_EFUSE_RD_DIS_SYS_DATA_PART2, 1);
|
||||||
|
}
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// get efuse coding_scheme.
|
||||||
|
esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
|
||||||
|
{
|
||||||
|
esp_efuse_coding_scheme_t scheme;
|
||||||
|
if (blk == EFUSE_BLK0) {
|
||||||
|
scheme = EFUSE_CODING_SCHEME_NONE;
|
||||||
|
} else {
|
||||||
|
scheme = EFUSE_CODING_SCHEME_RS;
|
||||||
|
}
|
||||||
|
return scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esp_efuse_desc_t **esp_efuse_get_purpose_field(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return s_table[idx].keypurpose;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esp_efuse_desc_t** esp_efuse_get_key(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return s_table[idx].key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
const uint8_t one = 1;
|
||||||
|
return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &one, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
const uint8_t one = 1;
|
||||||
|
return esp_efuse_write_field_blob(s_table[idx].key_wr_dis, &one, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_EFUSE_KEY_PURPOSE_MAX;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
uint8_t value = 0;
|
||||||
|
esp_err_t err = esp_efuse_read_field_blob(s_table[idx].keypurpose, &value, s_table[idx].keypurpose[0]->bit_count);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return ESP_EFUSE_KEY_PURPOSE_MAX;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_write_field_blob(s_table[idx].keypurpose, &purpose, s_table[idx].keypurpose[0]->bit_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
return esp_efuse_read_field_bit(s_table[idx].keypurpose_wr_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
const uint8_t one = 1;
|
||||||
|
return esp_efuse_write_field_blob(s_table[idx].keypurpose_wr_dis, &one, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block)
|
||||||
|
{
|
||||||
|
esp_efuse_block_t dummy;
|
||||||
|
if (block == NULL) {
|
||||||
|
block = &dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
|
||||||
|
if (esp_efuse_get_key_purpose(b) == purpose) {
|
||||||
|
*block = b;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_efuse_block_t esp_efuse_find_unused_key_block(void)
|
||||||
|
{
|
||||||
|
for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
|
||||||
|
if (esp_efuse_key_block_unused(b)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EFUSE_BLK_KEY_MAX; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned esp_efuse_count_unused_key_blocks(void)
|
||||||
|
{
|
||||||
|
unsigned r = 0;
|
||||||
|
for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
|
||||||
|
if (esp_efuse_key_block_unused(b)) {
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_key_block_unused(esp_efuse_block_t block)
|
||||||
|
{
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
|
||||||
|
return false; // Not a key block
|
||||||
|
}
|
||||||
|
|
||||||
|
if (esp_efuse_get_key_purpose(block) != ESP_EFUSE_KEY_PURPOSE_USER ||
|
||||||
|
esp_efuse_get_keypurpose_dis_write(block) ||
|
||||||
|
esp_efuse_get_key_dis_read(block) ||
|
||||||
|
esp_efuse_get_key_dis_write(block)) {
|
||||||
|
return false; // Block in use!
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!esp_efuse_block_is_empty(block)) {
|
||||||
|
return false; // Block in use!
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Unused
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_digest_revoke(unsigned num_digest)
|
||||||
|
{
|
||||||
|
assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
|
||||||
|
return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_digest_revoke(unsigned num_digest)
|
||||||
|
{
|
||||||
|
if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest)
|
||||||
|
{
|
||||||
|
assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
|
||||||
|
return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest)
|
||||||
|
{
|
||||||
|
if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpose, const void *key, size_t key_size_bytes)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_efuse_batch_write_begin();
|
||||||
|
|
||||||
|
if (!esp_efuse_key_block_unused(block)) {
|
||||||
|
err = ESP_ERR_INVALID_STATE;
|
||||||
|
} else {
|
||||||
|
unsigned idx = block - EFUSE_BLK_KEY0;
|
||||||
|
ESP_EFUSE_CHK(esp_efuse_write_field_blob(s_table[idx].key, key, key_size_bytes * 8));
|
||||||
|
ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
|
||||||
|
if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 ||
|
||||||
|
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ||
|
||||||
|
purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY ||
|
||||||
|
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL ||
|
||||||
|
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG ||
|
||||||
|
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE ||
|
||||||
|
purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
|
||||||
|
ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block));
|
||||||
|
}
|
||||||
|
ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose));
|
||||||
|
ESP_EFUSE_CHK(esp_efuse_set_keypurpose_dis_write(block));
|
||||||
|
return esp_efuse_batch_write_commit();
|
||||||
|
}
|
||||||
|
err_exit:
|
||||||
|
esp_efuse_batch_write_cancel();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_write_keys(esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys)
|
||||||
|
{
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
if (number_of_keys == 0 || number_of_keys > (EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) || keys == NULL || purposes == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_efuse_purpose_t purpose = 0;
|
||||||
|
esp_efuse_block_t block = EFUSE_BLK_KEY0;
|
||||||
|
|
||||||
|
esp_efuse_batch_write_begin();
|
||||||
|
|
||||||
|
unsigned unused_keys = esp_efuse_count_unused_key_blocks();
|
||||||
|
if (number_of_keys > unused_keys) {
|
||||||
|
ESP_LOGE(TAG, "Not enough unused key blocks available. Required %d, was %d", number_of_keys, unused_keys);
|
||||||
|
err = ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS;
|
||||||
|
} else {
|
||||||
|
for (int i_key = 0; (block < EFUSE_BLK_KEY_MAX) && (i_key < number_of_keys); block++) {
|
||||||
|
if (esp_efuse_key_block_unused(block)) {
|
||||||
|
purpose = purposes[i_key];
|
||||||
|
ESP_LOGI(TAG, "Writing EFUSE_BLK_KEY%d with purpose %d", block - EFUSE_BLK_KEY0, purpose);
|
||||||
|
ESP_EFUSE_CHK(esp_efuse_write_key(block, purpose, keys[i_key], 32));
|
||||||
|
i_key++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return esp_efuse_batch_write_commit();
|
||||||
|
err_exit:
|
||||||
|
ESP_LOGE(TAG, "Failed to write EFUSE_BLK_KEY%d with purpose %d. Can't continue.", block - EFUSE_BLK_KEY0, purpose);
|
||||||
|
}
|
||||||
|
esp_efuse_batch_write_cancel();
|
||||||
|
return err;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
|
idf_build_get_property(target IDF_TARGET)
|
||||||
|
|
||||||
idf_component_register(SRC_DIRS "."
|
idf_component_register(SRC_DIRS "."
|
||||||
PRIV_INCLUDE_DIRS "." "include"
|
PRIV_INCLUDE_DIRS "." "include" "../private_include" ../${target}/private_include
|
||||||
PRIV_INCLUDE_DIRS "../private_include"
|
|
||||||
PRIV_REQUIRES cmock test_utils efuse bootloader_support
|
PRIV_REQUIRES cmock test_utils efuse bootloader_support
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "driver/adc.h"
|
#include "driver/adc.h"
|
||||||
#include "hal/adc_ll.h"
|
#include "hal/adc_ll.h"
|
||||||
#include "esp32c3/esp_efuse_rtc_calib.h"
|
#include "esp_efuse_rtc_calib.h"
|
||||||
#include "esp_adc_cal.h"
|
#include "esp_adc_cal.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#include "esp_adc_cal.h"
|
#include "esp_adc_cal.h"
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "esp_efuse_table.h"
|
#include "esp_efuse_table.h"
|
||||||
#include "esp32s2/esp_efuse_rtc_table.h"
|
#include "esp_efuse_rtc_table.h"
|
||||||
#include "hal/adc_hal.h"
|
#include "hal/adc_hal.h"
|
||||||
|
|
||||||
#define ADC_CAL_CHECK(cond, ret) ({ \
|
#define ADC_CAL_CHECK(cond, ret) ({ \
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "esp_flash_encrypt.h"
|
#include "esp_flash_encrypt.h"
|
||||||
|
#include "esp_secure_boot.h"
|
||||||
|
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
// Headers for other components init functions
|
// Headers for other components init functions
|
||||||
@ -48,7 +49,6 @@
|
|||||||
#include "esp_core_dump.h"
|
#include "esp_core_dump.h"
|
||||||
#include "esp_app_trace.h"
|
#include "esp_app_trace.h"
|
||||||
#include "esp_private/dbg_stubs.h"
|
#include "esp_private/dbg_stubs.h"
|
||||||
#include "esp_flash_encrypt.h"
|
|
||||||
#include "esp_pm.h"
|
#include "esp_pm.h"
|
||||||
#include "esp_private/pm_impl.h"
|
#include "esp_private/pm_impl.h"
|
||||||
#include "esp_pthread.h"
|
#include "esp_pthread.h"
|
||||||
@ -276,6 +276,10 @@ static void do_core_init(void)
|
|||||||
esp_flash_encryption_init_checks();
|
esp_flash_encryption_init_checks();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SECURE_BOOT
|
||||||
|
esp_secure_boot_init_checks();
|
||||||
|
#endif
|
||||||
|
|
||||||
esp_err_t err;
|
esp_err_t err;
|
||||||
|
|
||||||
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
||||||
|
@ -173,6 +173,8 @@ eFuse usage
|
|||||||
|
|
||||||
- SECURE_BOOT_AGGRESSIVE_REVOKE - Enables aggressive revocation of keys. The key is revoked as soon as verification with this key fails.
|
- SECURE_BOOT_AGGRESSIVE_REVOKE - Enables aggressive revocation of keys. The key is revoked as soon as verification with this key fails.
|
||||||
|
|
||||||
|
To ensure no trusted keys can be added later by an attacker, each unused key digest slot should be revoked (KEY_REVOKEX). It will be checked during app startup in :cpp:func:`esp_secure_boot_init_checks` and fixed unless :ref:`CONFIG_SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS` is enabled.
|
||||||
|
|
||||||
.. _secure-boot-v2-howto:
|
.. _secure-boot-v2-howto:
|
||||||
|
|
||||||
How To Enable Secure Boot V2
|
How To Enable Secure Boot V2
|
||||||
|
@ -92,6 +92,8 @@ components/unity/include/unity_test_runner.h
|
|||||||
components/cmock/CMock/src/cmock.h
|
components/cmock/CMock/src/cmock.h
|
||||||
components/cmock/CMock/src/cmock_internals.h
|
components/cmock/CMock/src/cmock_internals.h
|
||||||
|
|
||||||
|
components/efuse/include/esp_efuse.h
|
||||||
|
|
||||||
### Here are the files that do not compile for some reason
|
### Here are the files that do not compile for some reason
|
||||||
#
|
#
|
||||||
components/app_trace/include/esp_sysview_trace.h
|
components/app_trace/include/esp_sysview_trace.h
|
||||||
|
Loading…
x
Reference in New Issue
Block a user