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:
KonstantinKondrashov 2021-01-26 04:27:03 +08:00
parent b92c290e56
commit 90f2d3199a
55 changed files with 877 additions and 767 deletions

View File

@ -692,6 +692,16 @@ menu "Security features"
key digest, causing an immediate denial of service and possibly allowing an additional fault
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
bool "Don't automatically restrict UART download mode"
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED

View File

@ -9,6 +9,7 @@ set(srcs
"src/bootloader_utility.c"
"src/esp_image_format.c"
"src/flash_encrypt.c"
"src/secure_boot.c"
"src/flash_partitions.c"
"src/flash_qio_mode.c"
"src/bootloader_flash_config_${IDF_TARGET}.c"

View File

@ -214,6 +214,17 @@ typedef struct {
uint8_t digest[64];
} 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
}
#endif

View 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

View File

@ -31,7 +31,7 @@
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "hal/dma_types.h"
#include "esp32c3/esp_efuse_rtc_calib.h"
#include "esp_efuse_rtc_calib.h"
#include "esp_private/gdma.h"
#define ADC_CHECK_RET(fun_ret) ({ \

View File

@ -29,7 +29,7 @@
#include "driver/rtc_cntl.h"
#include "driver/gpio.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_hal.h"

View File

@ -26,7 +26,7 @@
#include "driver/temp_sensor.h"
#include "regi2c_ctrl.h"
#include "esp_log.h"
#include "esp32s2/esp_efuse_rtc_table.h"
#include "esp_efuse_rtc_table.h"
static const char *TAG = "tsens";

View File

@ -4,26 +4,23 @@ if(EXISTS "${COMPONENT_DIR}/${target}")
include(${COMPONENT_DIR}/${target}/sources.cmake)
spaces2list(EFUSE_SOC_SRCS)
set(include_dirs include ${target}/include)
set(private_include private_include ${target}/private_include)
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()
list(APPEND srcs "src/esp_efuse_api.c"
"src/esp_efuse_fields.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}"
PRIV_REQUIRES bootloader_support soc spi_flash
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS private_include)
PRIV_INCLUDE_DIRS "${private_include}")
if(target)
set(TOOL_TARGET -t ${target})

View File

@ -3,8 +3,12 @@
# currently the only SoC supported; to be moved into Kconfig
TARGET := $(IDF_TARGET)
COMPONENT_SRCDIRS := $(TARGET) src src/$(TARGET)
COMPONENT_PRIV_INCLUDEDIRS := private_include
COMPONENT_ADD_INCLUDEDIRS := $(TARGET)/include include
COMPONENT_SRCDIRS := $(TARGET) src
ifdef CONFIG_IDF_TARGET_ESP32
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

View File

@ -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");
// you may not use this file except in compliance with the License.

View 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

View File

@ -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");
// you may not use this file except in compliance with the License.

View File

@ -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")

View File

@ -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")

View File

@ -13,7 +13,7 @@
// limitations under the License.
#include <stdbool.h>
#include "esp32s2/esp_efuse_rtc_table.h"
#include "esp_efuse_rtc_table.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_log.h"

View File

@ -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")

View File

@ -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")

View File

@ -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

View File

@ -23,15 +23,7 @@ extern "C" {
#include "esp_log.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#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
#include_next "esp_efuse.h"
#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. */
@ -496,48 +488,14 @@ esp_err_t esp_efuse_batch_write_cancel(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 {
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);
bool esp_efuse_block_is_empty(esp_efuse_block_t 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);
/**
* @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.
*
@ -660,20 +674,6 @@ esp_efuse_block_t esp_efuse_find_unused_key_block(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.
*

View File

@ -23,15 +23,7 @@ extern "C" {
#include "esp_err.h"
#include "esp_efuse.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#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
#include_next "esp_efuse_utility.h"
/**
* @brief Structure range address by blocks

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -282,307 +282,3 @@ esp_err_t esp_efuse_batch_write_commit(void)
}
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

View 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
}

View 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;
}

View File

@ -1,5 +1,6 @@
idf_build_get_property(target IDF_TARGET)
idf_component_register(SRC_DIRS "."
PRIV_INCLUDE_DIRS "." "include"
PRIV_INCLUDE_DIRS "../private_include"
PRIV_INCLUDE_DIRS "." "include" "../private_include" ../${target}/private_include
PRIV_REQUIRES cmock test_utils efuse bootloader_support
)

View File

@ -20,7 +20,7 @@
#include "esp_log.h"
#include "driver/adc.h"
#include "hal/adc_ll.h"
#include "esp32c3/esp_efuse_rtc_calib.h"
#include "esp_efuse_rtc_calib.h"
#include "esp_adc_cal.h"

View File

@ -21,7 +21,7 @@
#include "esp_adc_cal.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp32s2/esp_efuse_rtc_table.h"
#include "esp_efuse_rtc_table.h"
#include "hal/adc_hal.h"
#define ADC_CAL_CHECK(cond, ret) ({ \

View File

@ -39,6 +39,7 @@
#include "esp_timer.h"
#include "esp_efuse.h"
#include "esp_flash_encrypt.h"
#include "esp_secure_boot.h"
/***********************************************/
// Headers for other components init functions
@ -48,7 +49,6 @@
#include "esp_core_dump.h"
#include "esp_app_trace.h"
#include "esp_private/dbg_stubs.h"
#include "esp_flash_encrypt.h"
#include "esp_pm.h"
#include "esp_private/pm_impl.h"
#include "esp_pthread.h"
@ -276,6 +276,10 @@ static void do_core_init(void)
esp_flash_encryption_init_checks();
#endif
#ifdef CONFIG_SECURE_BOOT
esp_secure_boot_init_checks();
#endif
esp_err_t err;
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE

View File

@ -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.
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:
How To Enable Secure Boot V2

View File

@ -92,6 +92,8 @@ components/unity/include/unity_test_runner.h
components/cmock/CMock/src/cmock.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
#
components/app_trace/include/esp_sysview_trace.h