From 4a487af43a7f1886850984ce3ecfd701517c6219 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Fri, 4 Dec 2020 10:42:57 +0800 Subject: [PATCH] efuse: Add new APIs for keys, purposes, wr/rd protection - the batch mode can be called recursively --- components/efuse/include/esp32s2/esp_efuse.h | 9 +- components/efuse/include/esp32s3/esp_efuse.h | 9 +- components/efuse/include/esp_efuse.h | 319 +++++++++++++++- components/efuse/src/esp32s2/esp_efuse_api.c | 21 -- components/efuse/src/esp32s3/esp_efuse_api.c | 21 -- components/efuse/src/esp_efuse_api.c | 371 +++++++++++++++++-- components/efuse/test/test_efuse.c | 51 +++ components/efuse/test/test_efuse_keys.c | 368 ++++++++++++++++++ components/esp_common/src/esp_err_to_name.c | 3 + tools/ci/config/target-test.yml | 2 +- 10 files changed, 1068 insertions(+), 106 deletions(-) create mode 100644 components/efuse/test/test_efuse_keys.c diff --git a/components/efuse/include/esp32s2/esp_efuse.h b/components/efuse/include/esp32s2/esp_efuse.h index 30dcb5e805..9e5096b9b8 100644 --- a/components/efuse/include/esp32s2/esp_efuse.h +++ b/components/efuse/include/esp32s2/esp_efuse.h @@ -49,6 +49,7 @@ typedef enum { EFUSE_BLK9 = 9, /**< Number of eFuse BLOCK9. KEY5 */ EFUSE_BLK_KEY5 = 9, /**< Number of eFuse BLOCK9. KEY5 */ + EFUSE_BLK_KEY_MAX = 10, EFUSE_BLK10 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */ EFUSE_BLK_SYS_DATA_PART2 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */ @@ -56,14 +57,6 @@ typedef enum { EFUSE_BLK_MAX } esp_efuse_block_t; -struct esp_efuse_desc_s; - -/** - * @brief Given a key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY5, return - * efuse field for setting the key purpose - */ -const struct esp_efuse_desc_s **esp_efuse_get_purpose_field(esp_efuse_block_t block); - /** * @brief Type of coding scheme */ diff --git a/components/efuse/include/esp32s3/esp_efuse.h b/components/efuse/include/esp32s3/esp_efuse.h index 484ca44454..4c2beedfd5 100644 --- a/components/efuse/include/esp32s3/esp_efuse.h +++ b/components/efuse/include/esp32s3/esp_efuse.h @@ -49,6 +49,7 @@ typedef enum { EFUSE_BLK9 = 9, /**< Number of eFuse BLOCK9. KEY5 */ EFUSE_BLK_KEY5 = 9, /**< Number of eFuse BLOCK9. KEY5 */ + EFUSE_BLK_KEY_MAX = 10, EFUSE_BLK10 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */ EFUSE_BLK_SYS_DATA_PART2 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */ @@ -56,14 +57,6 @@ typedef enum { EFUSE_BLK_MAX } esp_efuse_block_t; -struct esp_efuse_desc_s; - -/** - * @brief Given a key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY5, return - * efuse field for setting the key purpose - */ -const struct esp_efuse_desc_s **esp_efuse_get_purpose_field(esp_efuse_block_t block); - /** * @brief Type of coding scheme */ diff --git a/components/efuse/include/esp_efuse.h b/components/efuse/include/esp_efuse.h index bebfd64403..6b349e6652 100644 --- a/components/efuse/include/esp_efuse.h +++ b/components/efuse/include/esp_efuse.h @@ -38,20 +38,16 @@ extern "C" { #define ESP_ERR_EFUSE_CNT_IS_FULL (ESP_ERR_EFUSE + 0x02) /*!< Error field is full. */ #define ESP_ERR_EFUSE_REPEATED_PROG (ESP_ERR_EFUSE + 0x03) /*!< Error repeated programming of programmed bits is strictly forbidden. */ #define ESP_ERR_CODING (ESP_ERR_EFUSE + 0x04) /*!< Error while a encoding operation. */ - -/** - * @brief Structure eFuse field - */ -struct esp_efuse_desc_s { - esp_efuse_block_t efuse_block: 8; /**< Block of eFuse */ - uint8_t bit_start; /**< Start bit [0..255] */ - uint16_t bit_count; /**< Length of bit field [1..-]*/ -}; +#define ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS (ESP_ERR_EFUSE + 0x05) /*!< Error not enough unused key blocks available */ /** * @brief Type definition for an eFuse field */ -typedef struct esp_efuse_desc_s esp_efuse_desc_t; +typedef struct { + esp_efuse_block_t efuse_block: 8; /**< Block of eFuse */ + uint8_t bit_start; /**< Start bit [0..255] */ + uint16_t bit_count; /**< Length of bit field [1..-]*/ +} esp_efuse_desc_t; /** * @brief Reads bits from EFUSE field and writes it into an array. @@ -59,6 +55,9 @@ typedef struct esp_efuse_desc_s esp_efuse_desc_t; * The number of read bits will be limited to the minimum value * from the description of the bits in "field" structure or "dst_size_bits" required size. * Use "esp_efuse_get_field_size()" function to determine the length of the field. + * + * @note Please note that reading in the batch mode does not show uncommitted changes. + * * @param[in] field A pointer to the structure describing the fields of efuse. * @param[out] dst A pointer to array that will contain the result of reading. * @param[in] dst_size_bits The number of bits required to read. @@ -79,6 +78,7 @@ esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, * in the provided arguments, call esp_efuse_read_field_blob() and check the returned value instead. * * @note If assertions are enabled and the parameter is invalid, execution will abort + * @note Please note that reading in the batch mode does not show uncommitted changes. * * @param[in] field A pointer to the structure describing the fields of efuse. * @return @@ -92,6 +92,8 @@ bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[]); * @brief Reads bits from EFUSE field and returns number of bits programmed as "1". * * If the bits are set not sequentially, they will still be counted. + * @note Please note that reading in the batch mode does not show uncommitted changes. + * * @param[in] field A pointer to the structure describing the fields of efuse. * @param[out] out_cnt A pointer that will contain the number of programmed as "1" bits. * @@ -197,6 +199,8 @@ int esp_efuse_get_field_size(const esp_efuse_desc_t* field[]); * * This is a thread-safe implementation. * Example: EFUSE_BLK2_RDATA3_REG where (blk=2, num_reg=3) + * @note Please note that reading in the batch mode does not show uncommitted changes. + * * @param[in] blk Block number of eFuse. * @param[in] num_reg The register number in the block. * @@ -233,6 +237,8 @@ esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk); /** * @brief Read key to efuse block starting at the offset and the required size. * + * @note Please note that reading in the batch mode does not show uncommitted changes. + * * @param[in] blk Block number of eFuse. * @param[in] dst_key A pointer to array that will contain the result of reading. * @param[in] offset_in_bits Start bit in block. @@ -409,13 +415,19 @@ esp_err_t esp_efuse_update_secure_version(uint32_t secure_version); */ void esp_efuse_init(uint32_t offset, uint32_t size); -/* @brief Set the batch mode of writing fields. +/** + * @brief Set the batch mode of writing fields. * - * This mode allows you to write the fields in the batch mode. - * If this mode is enabled, esp_efuse_batch_write_commit() must be called - * to actually burn any written efuses. - * In this mode, reading efuse is not possible. - * This mode should be used when burning several efuses at one time. + * This mode allows you to write the fields in the batch mode when need to burn several efuses at one time. + * To enable batch mode call begin() then perform as usually the necessary operations + * read and write and at the end call commit() to actually burn all written efuses. + * The batch mode can be used nested. The commit will be done by the last commit() function. + * The number of begin() functions should be equal to the number of commit() functions. + * + * @note Please note that reading in the batch mode does not show uncommitted changes. + * + * Note: If batch mode is enabled by the first task, at this time the second task cannot write/read efuses. + * The second task will wait for the first task to complete the batch operation. * * \code{c} * // Example of using the batch writing mode. @@ -429,10 +441,20 @@ void esp_efuse_init(uint32_t offset, uint32_t size); * esp_efuse_set_write_protect(EFUSE_BLKx); * esp_efuse_write_reg(EFUSE_BLKx, ...); * esp_efuse_write_block(EFUSE_BLKx, ...); + * esp_efuse_write(ESP_EFUSE_1, 3); // ESP_EFUSE_1 == 1, here we write a new value = 3. The changes will be burn by the commit() function. + * esp_efuse_read_...(ESP_EFUSE_1); // this function returns ESP_EFUSE_1 == 1 because uncommitted changes are not readable, it will be available only after commit. + * ... + * + * // esp_efuse_batch_write APIs can be called recursively. + * esp_efuse_batch_write_begin(); + * esp_efuse_set_write_protect(EFUSE_BLKx); + * esp_efuse_batch_write_commit(); // the burn will be skipped here, it will be done in the last commit(). + * * ... * * // Write all of these fields to the efuse registers * esp_efuse_batch_write_commit(); + * esp_efuse_read_...(ESP_EFUSE_1); // this function returns ESP_EFUSE_1 == 3. * * \endcode * @@ -462,6 +484,271 @@ 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 + */ +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 a read protection for the key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return True: The key block is read protected + * False: The key block is readable. + */ +bool esp_efuse_get_key_dis_read(esp_efuse_block_t block); + +/** + * @brief Sets a read protection for the key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block); + +/** + * @brief Returns a write protection for the key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return True: The key block is write protected + * False: The key block is writeable. + */ +bool esp_efuse_get_key_dis_write(esp_efuse_block_t block); + +/** + * @brief Sets a write protection for the key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block); + +/** + * @brief Returns the current purpose set for an efuse key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return + * - Value: If Successful, it returns the value of the purpose related to the given key block. + * - ESP_EFUSE_KEY_PURPOSE_MAX: Otherwise. + */ +esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block); + +/** + * @brief Sets a key purpose for an efuse key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * @param[in] purpose Key purpose. + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose); + +/** + * @brief Returns a write protection of the key purpose field for an efuse key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return True: The key purpose is write protected. + * False: The key purpose is writeable. + */ +bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block); + +/** + * @brief Sets a write protection of the key purpose field for an efuse key block. + * + * @param[in] block A key block in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block); + +/** + * @brief Find a key block with the particular purpose set. + * + * @param[in] purpose Purpose to search for. + * @param[out] block Pointer in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX which will be set to the key block if found. + * Can be NULL, if only need to test the key block exists. + * + * @return + * - True: If found, + * - False: If not found (value at block pointer is unchanged). + */ +bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block); + +/** + * @brief Search for an unused key block and return the first one found. + * + * See esp_efuse_key_block_unused for a description of an unused key block. + * + * @return First unused key block, or EFUSE_BLK_KEY_MAX if no unused key block is found. + */ +esp_efuse_block_t esp_efuse_find_unused_key_block(void); + +/** + * @brief Return the number of unused efuse key blocks in the range EFUSE_BLK_KEY0..EFUSE_BLK_KEY_MAX + */ +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. + * + * @param[in] num_digest The number of digest in range 0..2 + * + * @return + * - True: If key digest is revoked, + * - False; If key digest is not revoked. + */ +bool esp_efuse_get_digest_revoke(unsigned num_digest); + +/** + * @brief Sets the Secure Boot public key digest revocation bit. + * + * @param[in] num_digest The number of digest in range 0..2 + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_set_digest_revoke(unsigned num_digest); + +/** + * @brief Returns a write protection of the Secure Boot public key digest revocation bit. + * + * @param[in] num_digest The number of digest in range 0..2 + * + * @return True: The revocation bit is write protected. + * False: The revocation bit is writeable. + */ +bool esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest); + +/** + * @brief Sets a write protection of the Secure Boot public key digest revocation bit. + * + * @param[in] num_digest The number of digest in range 0..2 + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest); + +/** + * @brief Program a block of key data to an efuse block + * + * The burn of a key, protection bits, and a purpose happens in batch mode. + * + * @param[in] block Block to read purpose for. Must be in range EFUSE_BLK_KEY0 to EFUSE_BLK_KEY_MAX. Key block must be unused (esp_efuse_key_block_unused). + * @param[in] purpose Purpose to set for this key. Purpose must be already unset. + * @param[in] key Pointer to data to write. + * @param[in] key_size_bytes Bytes length of data to write. + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_INVALID_STATE: Error in efuses state, unused block not found. + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +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); + +/** + * @brief Program keys to unused efuse blocks + * + * The burn of keys, protection bits, and purposes happens in batch mode. + * + * @param[in] purposes Array of purposes (purpose[number_of_keys]). + * @param[in] keys Array of keys (uint8_t keys[number_of_keys][32]). Each key is 32 bytes long. + * @param[in] number_of_keys The number of keys to write (up to 6 keys). + * + * @return + * - ESP_OK: Successful. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments. + * - ESP_ERR_INVALID_STATE: Error in efuses state, unused block not found. + * - ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS: Error not enough unused key blocks available + * - ESP_ERR_EFUSE_REPEATED_PROG: Error repeated programming of programmed bits is strictly forbidden. + * - ESP_ERR_CODING: Error range of data does not match the coding scheme. + */ +esp_err_t esp_efuse_write_keys(esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys); + +#endif // not CONFIG_IDF_TARGET_ESP32 + #ifdef __cplusplus } #endif diff --git a/components/efuse/src/esp32s2/esp_efuse_api.c b/components/efuse/src/esp32s2/esp_efuse_api.c index b77319c05b..184d883383 100644 --- a/components/efuse/src/esp32s2/esp_efuse_api.c +++ b/components/efuse/src/esp32s2/esp_efuse_api.c @@ -81,24 +81,3 @@ esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk) ESP_EARLY_LOGD(TAG, "coding scheme %d", scheme); return scheme; } - - -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; - } -} diff --git a/components/efuse/src/esp32s3/esp_efuse_api.c b/components/efuse/src/esp32s3/esp_efuse_api.c index 65abab4108..ae4ed61fd8 100644 --- a/components/efuse/src/esp32s3/esp_efuse_api.c +++ b/components/efuse/src/esp32s3/esp_efuse_api.c @@ -81,24 +81,3 @@ esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk) ESP_EARLY_LOGD(TAG, "coding scheme %d", scheme); return scheme; } - - -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; - } -} diff --git a/components/efuse/src/esp_efuse_api.c b/components/efuse/src/esp_efuse_api.c index a72a77dff6..ce01213ded 100644 --- a/components/efuse/src/esp_efuse_api.c +++ b/components/efuse/src/esp_efuse_api.c @@ -22,27 +22,23 @@ const static char *TAG = "efuse"; #if defined(BOOTLOADER_BUILD) -#define EFUSE_LOCK_ACQUIRE() -#define EFUSE_LOCK_RELEASE() #define EFUSE_LOCK_ACQUIRE_RECURSIVE() #define EFUSE_LOCK_RELEASE_RECURSIVE() #else #include static _lock_t s_efuse_lock; -#define EFUSE_LOCK_ACQUIRE() _lock_acquire(&s_efuse_lock) -#define EFUSE_LOCK_RELEASE() _lock_release(&s_efuse_lock) #define EFUSE_LOCK_ACQUIRE_RECURSIVE() _lock_acquire_recursive(&s_efuse_lock) #define EFUSE_LOCK_RELEASE_RECURSIVE() _lock_release_recursive(&s_efuse_lock) #endif -static bool s_batch_writing_mode = false; +static int s_batch_writing_mode = 0; // Public API functions // read value from EFUSE, writing it into an array esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits) { - EFUSE_LOCK_ACQUIRE(); + EFUSE_LOCK_ACQUIRE_RECURSIVE(); esp_err_t err = ESP_OK; if (field == NULL || dst == NULL || dst_size_bits == 0) { err = ESP_ERR_INVALID_ARG; @@ -50,7 +46,7 @@ esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8)); err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff); } - EFUSE_LOCK_RELEASE(); + EFUSE_LOCK_RELEASE_RECURSIVE(); return err; } @@ -65,7 +61,7 @@ bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[]) // read number of bits programmed as "1" in the particular field esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt) { - EFUSE_LOCK_ACQUIRE(); + EFUSE_LOCK_ACQUIRE_RECURSIVE(); esp_err_t err = ESP_OK; if (field == NULL || out_cnt == NULL) { err = ESP_ERR_INVALID_ARG; @@ -73,7 +69,7 @@ esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_ *out_cnt = 0; err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once); } - EFUSE_LOCK_RELEASE(); + EFUSE_LOCK_RELEASE_RECURSIVE(); return err; } @@ -85,12 +81,12 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void if (field == NULL || src == NULL || src_size_bits == 0) { err = ESP_ERR_INVALID_ARG; } else { - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { esp_efuse_utility_reset(); } err = esp_efuse_utility_process(field, (void*)src, src_size_bits, esp_efuse_utility_write_blob); - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { if (err == ESP_OK) { err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { @@ -112,7 +108,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt) if (field == NULL || cnt == 0) { err = ESP_ERR_INVALID_ARG; } else { - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { esp_efuse_utility_reset(); } err = esp_efuse_utility_process(field, &cnt, 0, esp_efuse_utility_write_cnt); @@ -125,7 +121,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt) err = ESP_OK; } - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { if (err == ESP_OK) { err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { @@ -175,9 +171,9 @@ int esp_efuse_get_field_size(const esp_efuse_desc_t* field[]) // reading efuse register. uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg) { - EFUSE_LOCK_ACQUIRE(); + EFUSE_LOCK_ACQUIRE_RECURSIVE(); uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg); - EFUSE_LOCK_RELEASE(); + EFUSE_LOCK_RELEASE_RECURSIVE(); return ret_val; } @@ -185,11 +181,11 @@ uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg) esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val) { EFUSE_LOCK_ACQUIRE_RECURSIVE(); - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { esp_efuse_utility_reset(); } esp_err_t err = esp_efuse_utility_write_reg(blk, num_reg, val); - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { if (err == ESP_OK) { err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { @@ -244,36 +240,349 @@ esp_err_t esp_efuse_write_block(esp_efuse_block_t blk, const void* src_key, size esp_err_t esp_efuse_batch_write_begin(void) { - EFUSE_LOCK_ACQUIRE(); - s_batch_writing_mode = true; - esp_efuse_utility_reset(); - ESP_LOGI(TAG, "Batch mode of writing fields is enabled"); + EFUSE_LOCK_ACQUIRE_RECURSIVE(); + assert(s_batch_writing_mode >= 0); + if (++s_batch_writing_mode == 1) { + esp_efuse_utility_reset(); + ESP_LOGI(TAG, "Batch mode of writing fields is enabled"); + }; return ESP_OK; } esp_err_t esp_efuse_batch_write_cancel(void) { - if (s_batch_writing_mode == true) { - s_batch_writing_mode = false; - esp_efuse_utility_reset(); - ESP_LOGI(TAG, "Batch mode of writing fields is disabled"); - EFUSE_LOCK_RELEASE(); - return ESP_OK; - } else { + if (s_batch_writing_mode == 0) { + ESP_LOGE(TAG, "Batch mode was not enabled"); return ESP_ERR_INVALID_STATE; } + if (--s_batch_writing_mode == 0) { + esp_efuse_utility_reset(); + ESP_LOGI(TAG, "Batch mode of writing fields is cancelled"); + EFUSE_LOCK_RELEASE_RECURSIVE(); + } + return ESP_OK; } esp_err_t esp_efuse_batch_write_commit(void) { - if (s_batch_writing_mode == false) { + if (s_batch_writing_mode == 0) { + ESP_LOGE(TAG, "Batch mode was not enabled"); return ESP_ERR_INVALID_STATE; - } else { + } + if (--s_batch_writing_mode == 0) { esp_err_t err = esp_efuse_utility_apply_new_coding_scheme(); if (err == ESP_OK) { esp_efuse_utility_burn_efuses(); + ESP_LOGI(TAG, "Batch mode. Prepared fields are committed"); + } else { + esp_efuse_utility_reset(); } - esp_efuse_batch_write_cancel(); + EFUSE_LOCK_RELEASE_RECURSIVE(); return err; } + 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 diff --git a/components/efuse/test/test_efuse.c b/components/efuse/test/test_efuse.c index 16fec92009..a78111818d 100644 --- a/components/efuse/test/test_efuse.c +++ b/components/efuse/test/test_efuse.c @@ -885,5 +885,56 @@ TEST_CASE("Test writing order is BLK_MAX->BLK0", "[efuse]") TEST_ASSERT_EQUAL_HEX8_ARRAY(new_key, key, sizeof(key)); } +TEST_CASE("Test reading inside of batch mode in a nested way", "[efuse]") +{ + uint8_t new_key[32] = {44, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 12, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 22, 24, 25, 26, 27, 28, 29, + 30, 31}; + uint8_t key[32] = { 0xEE }; + esp_efuse_utility_reset(); + esp_efuse_utility_erase_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_KEY5, &key, 256)); + TEST_ASSERT_EACH_EQUAL_HEX8(0, key, sizeof(key)); + + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_KEY5, &new_key, 256)); + TEST_ESP_OK(esp_efuse_set_write_protect(EFUSE_BLK_KEY5)); + ESP_LOGI(TAG, "Reading inside Batch mode, the key was not burn yet and it is empty"); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_KEY5, &key, 256)); + TEST_ASSERT_EACH_EQUAL_HEX8(0, key, sizeof(key)); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_batch_write_begin()); + ESP_LOGI(TAG, "Reading inside Batch mode, the key is already set"); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_KEY5, &key, 256)); + TEST_ASSERT_EQUAL_HEX8_ARRAY(new_key, key, sizeof(key)); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + + esp_efuse_utility_debug_dump_blocks(); + + ESP_LOGI(TAG, "Reading inside Batch mode, the key is already set"); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_efuse_batch_write_commit()); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_efuse_batch_write_cancel()); + TEST_ESP_OK(esp_efuse_batch_write_begin()); + TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_KEY2, &new_key, 256)); + TEST_ESP_OK(esp_efuse_batch_write_commit()); + TEST_ESP_OK(esp_efuse_read_field_blob(ESP_EFUSE_KEY2, &key, 256)); + TEST_ASSERT_EQUAL_HEX8_ARRAY(new_key, key, sizeof(key)); + + esp_efuse_utility_debug_dump_blocks(); +} #endif // CONFIG_IDF_ENV_FPGA || CONFIG_EFUSE_VIRTUAL #endif // not CONFIG_IDF_TARGET_ESP32 diff --git a/components/efuse/test/test_efuse_keys.c b/components/efuse/test/test_efuse_keys.c new file mode 100644 index 0000000000..b7f1915211 --- /dev/null +++ b/components/efuse/test/test_efuse_keys.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include +#include +#include +#include "unity.h" +#include "test_utils.h" +#include "esp_log.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" +#include "esp_efuse_utility.h" +#include "sdkconfig.h" + +__attribute__((unused)) static const char* TAG = "efuse_test"; + + +#ifndef CONFIG_IDF_TARGET_ESP32 + +TEST_CASE("Test keys and purposes, rd, wr, wr_key_purposes are in the initial state", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + for (esp_efuse_block_t num_key = EFUSE_BLK_KEY0; num_key < EFUSE_BLK_KEY_MAX; ++num_key) { + printf("EFUSE_BLK_KEY%d, RD, WR, PURPOSE_USER, PURPOSE_USER WR ... \n", num_key - EFUSE_BLK_KEY0); + uint8_t key[32] = { 0xEE }; + TEST_ESP_OK(esp_efuse_read_field_blob(esp_efuse_get_key(num_key), &key, sizeof(key) * 8)); + TEST_ASSERT_EACH_EQUAL_HEX8(0, key, sizeof(key)); + TEST_ASSERT_FALSE(esp_efuse_get_key_dis_read(num_key)); + TEST_ASSERT_FALSE(esp_efuse_get_key_dis_write(num_key)); + TEST_ASSERT_EQUAL(ESP_EFUSE_KEY_PURPOSE_USER, esp_efuse_get_key_purpose(num_key)); + TEST_ASSERT_FALSE(esp_efuse_get_keypurpose_dis_write(num_key)); + + esp_efuse_block_t key_block = EFUSE_BLK_MAX; + TEST_ASSERT_TRUE(esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_USER, NULL)); + TEST_ASSERT_TRUE(esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_USER, &key_block)); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY0, key_block); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY0, esp_efuse_find_unused_key_block()); + + printf("EFUSE_BLK_KEY%d, RD, WR, PURPOSE_USER, PURPOSE_USER WR ... OK\n", num_key - EFUSE_BLK_KEY0); + } +} + +// If using efuse is real, then turn off writing tests. +#if CONFIG_EFUSE_VIRTUAL || CONFIG_IDF_ENV_FPGA + +static esp_err_t s_check_key(esp_efuse_block_t num_key, void* wr_key) +{ + uint8_t rd_key[32] = { 0xEE }; + esp_efuse_purpose_t purpose = esp_efuse_get_key_purpose(num_key); + TEST_ESP_OK(esp_efuse_read_field_blob(esp_efuse_get_key(num_key), &rd_key, sizeof(rd_key) * 8)); +#ifndef CONFIG_IDF_ENV_FPGA + TEST_ASSERT_EQUAL_HEX8_ARRAY(wr_key, rd_key, sizeof(wr_key)); +#endif // not CONFIG_IDF_ENV_FPGA + + TEST_ASSERT_TRUE(esp_efuse_get_key_dis_write(num_key)); + 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) { + TEST_ASSERT_TRUE(esp_efuse_get_key_dis_read(num_key)); +#if CONFIG_IDF_ENV_FPGA && !CONFIG_EFUSE_VIRTUAL + TEST_ASSERT_EACH_EQUAL_HEX8(0, rd_key, sizeof(rd_key)); +#endif // CONFIG_IDF_ENV_FPGA && ! CONFIG_EFUSE_VIRTUAL + } else { + TEST_ASSERT_FALSE(esp_efuse_get_key_dis_read(num_key)); + TEST_ASSERT_EQUAL_HEX8_ARRAY(wr_key, rd_key, sizeof(wr_key)); + } + + TEST_ASSERT_EQUAL(purpose, esp_efuse_get_key_purpose(num_key)); + esp_efuse_purpose_t purpose2 = 0; + TEST_ESP_OK(esp_efuse_read_field_blob(esp_efuse_get_purpose_field(num_key), &purpose2, 4)); + TEST_ASSERT_EQUAL(purpose, purpose2); + TEST_ASSERT_TRUE(esp_efuse_get_keypurpose_dis_write(num_key)); + return ESP_OK; +} + +void test_write_key(esp_efuse_block_t num_key, esp_efuse_purpose_t purpose) { + int id = num_key - EFUSE_BLK_KEY0; + printf("EFUSE_BLK_KEY%d, purpose=%d ... \n", id, purpose); + + uint8_t wr_key[32]; + for (int i = 0; i < sizeof(wr_key); i++) { + wr_key[i] = id + 1 + i; + } + + TEST_ASSERT_TRUE(esp_efuse_key_block_unused(num_key)); + + TEST_ESP_OK(esp_efuse_write_key(num_key, purpose, &wr_key, sizeof(wr_key))); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_efuse_write_key(num_key, purpose, &wr_key, sizeof(wr_key))); + + TEST_ESP_OK(s_check_key(num_key, wr_key)); + + TEST_ASSERT_FALSE(esp_efuse_key_block_unused(num_key)); + + printf("EFUSE_BLK_KEY%d, purpose=%d ... OK\n", id, purpose); +} + +#ifndef CONFIG_IDF_ENV_FPGA +TEST_CASE("Test esp_efuse_write_key for virt mode", "[efuse]") +{ + uint8_t rd_key[32] = { 0xEE }; + int tmp_purpose = 0; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_key(EFUSE_BLK3, tmp_purpose, &rd_key, sizeof(rd_key))); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_key(EFUSE_BLK_KEY0, tmp_purpose, &rd_key, 33)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_key(EFUSE_BLK10, tmp_purpose, &rd_key, sizeof(rd_key))); + + for (esp_efuse_purpose_t purpose = ESP_EFUSE_KEY_PURPOSE_RESERVED; purpose < ESP_EFUSE_KEY_PURPOSE_MAX; ++purpose) { + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + TEST_ASSERT_FALSE(esp_efuse_find_purpose(purpose, NULL)); + + for (esp_efuse_block_t num_key = (EFUSE_BLK_KEY_MAX - 1); num_key >= EFUSE_BLK_KEY0; --num_key) { + int id = num_key - EFUSE_BLK_KEY0; + TEST_ASSERT_EQUAL(id + 1, esp_efuse_count_unused_key_blocks()); + test_write_key(num_key, purpose); + TEST_ASSERT_EQUAL(id, esp_efuse_count_unused_key_blocks()); + + esp_efuse_block_t key_block = EFUSE_BLK_KEY_MAX; + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose, &key_block)); + TEST_ASSERT_EQUAL(num_key, key_block); + } + esp_efuse_utility_debug_dump_blocks(); + } +} +#endif // not CONFIG_IDF_ENV_FPGA + +TEST_CASE("Test 1 esp_efuse_write_key for FPGA", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + TEST_ASSERT_EQUAL_MESSAGE(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0, esp_efuse_count_unused_key_blocks(), "Efuses should be in initial state"); + + esp_efuse_purpose_t purpose [] = { + ESP_EFUSE_KEY_PURPOSE_USER, + ESP_EFUSE_KEY_PURPOSE_RESERVED, + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, + ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, + ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL, + }; + + int max_keys = EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0; + for (esp_efuse_block_t num_key = EFUSE_BLK_KEY0; num_key < EFUSE_BLK_KEY_MAX; ++num_key) { + int id = num_key - EFUSE_BLK_KEY0; + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - num_key, esp_efuse_count_unused_key_blocks()); + test_write_key(num_key, purpose[id]); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - num_key - 1, esp_efuse_count_unused_key_blocks()); + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose[id], NULL)); + TEST_ASSERT_EQUAL(--max_keys, esp_efuse_count_unused_key_blocks()); + } + esp_efuse_utility_debug_dump_blocks(); + printf("reset efuses on the FPGA board for the next test\n"); +} + +TEST_CASE("Test 2 esp_efuse_write_key for FPGA", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + TEST_ASSERT_EQUAL_MESSAGE(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0, esp_efuse_count_unused_key_blocks(), "Efuses should be in initial state"); + + esp_efuse_purpose_t purpose [] = { + ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG, + ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE, + ESP_EFUSE_KEY_PURPOSE_HMAC_UP, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, + }; + + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY0, esp_efuse_find_unused_key_block()); + int max_keys = EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0; + for (esp_efuse_block_t num_key = EFUSE_BLK_KEY0; num_key < EFUSE_BLK_KEY_MAX; ++num_key) { + int id = num_key - EFUSE_BLK_KEY0; + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - num_key, esp_efuse_count_unused_key_blocks()); + test_write_key(num_key, purpose[id]); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - num_key - 1, esp_efuse_count_unused_key_blocks()); + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose[id], NULL)); + TEST_ASSERT_EQUAL(--max_keys, esp_efuse_count_unused_key_blocks()); + if (esp_efuse_count_unused_key_blocks()) { + TEST_ASSERT_EQUAL(num_key + 1, esp_efuse_find_unused_key_block()); + } else { + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX, esp_efuse_find_unused_key_block()); + } + } + esp_efuse_utility_debug_dump_blocks(); + printf("reset efuses on the FPGA board for the next test\n"); +} + +TEST_CASE("Test esp_efuse_write_keys", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + TEST_ASSERT_EQUAL_MESSAGE(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0, esp_efuse_count_unused_key_blocks(), "Efuses should be in initial state"); + esp_efuse_block_t key_block = EFUSE_BLK_MAX; + + enum { BLOCKS_NEEDED1 = 2 }; + esp_efuse_purpose_t purpose1[BLOCKS_NEEDED1] = { + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, + }; + uint8_t keys1[BLOCKS_NEEDED1][32] = {{0xEE}}; + + for (int num_key = 0; num_key < BLOCKS_NEEDED1; ++num_key) { + for (int i = 0; i < 32; ++i) { + keys1[num_key][i] = purpose1[num_key] + i + 1; + } + } + + TEST_ESP_OK(esp_efuse_write_keys(purpose1, keys1, BLOCKS_NEEDED1)); + + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose1[0], &key_block)); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY0, key_block); + TEST_ESP_OK(s_check_key(key_block, keys1[0])); + + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose1[1], &key_block)); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY1, key_block); + TEST_ESP_OK(s_check_key(key_block, keys1[1])); + esp_efuse_utility_debug_dump_blocks(); + + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0 - 2, esp_efuse_count_unused_key_blocks()); + + enum { BLOCKS_NEEDED2 = 3 }; + esp_efuse_purpose_t purpose2[BLOCKS_NEEDED2] = { + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, + }; + uint8_t keys2[BLOCKS_NEEDED2][32] = {{0xDD}}; + + for (int num_key = 0; num_key < BLOCKS_NEEDED2; ++num_key) { + for (int i = 0; i < 32; ++i) { + keys2[num_key][i] = purpose2[num_key] + i + 1; + } + } + + TEST_ESP_OK(esp_efuse_write_keys(purpose2, keys2, BLOCKS_NEEDED2)); + + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose2[0], &key_block)); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY2, key_block); + TEST_ESP_OK(s_check_key(key_block, keys2[0])); + + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose2[1], &key_block)); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY3, key_block); + TEST_ESP_OK(s_check_key(key_block, keys2[1])); + + TEST_ASSERT_TRUE(esp_efuse_find_purpose(purpose2[2], &key_block)); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY4, key_block); + TEST_ESP_OK(s_check_key(key_block, keys2[2])); + esp_efuse_utility_debug_dump_blocks(); + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0 - 2 - 3, esp_efuse_count_unused_key_blocks()); + + printf("reset efuses on the FPGA board for the next test\n"); +} + +TEST_CASE("Test esp_efuse_write_keys for returned errors", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + TEST_ASSERT_EQUAL_MESSAGE(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0, esp_efuse_count_unused_key_blocks(), "Efuses should be in initial state"); + + enum { BLOCKS_NEEDED = 4 }; + esp_efuse_purpose_t purpose[BLOCKS_NEEDED] = { + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, + ESP_EFUSE_KEY_PURPOSE_MAX, // it leads ESP_ERR_INVALID_ARG in esp_efuse_write_keys + }; + uint8_t keys[BLOCKS_NEEDED][32] = {{0xEE}}; + + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_keys(NULL, keys, BLOCKS_NEEDED)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_keys(purpose, NULL, BLOCKS_NEEDED)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_keys(purpose, keys, (EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) + 1)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_write_keys(purpose, keys, BLOCKS_NEEDED)); // ESP_EFUSE_KEY_PURPOSE_MAX is not a valid purpose. + TEST_ASSERT_EQUAL(EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0, esp_efuse_count_unused_key_blocks()); + TEST_ESP_OK(esp_efuse_write_keys(purpose, keys, BLOCKS_NEEDED - 1)); + TEST_ASSERT_EQUAL((EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) - (BLOCKS_NEEDED - 1), esp_efuse_count_unused_key_blocks()); + unsigned unused_keys = esp_efuse_count_unused_key_blocks(); + TEST_ESP_ERR(ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS, esp_efuse_write_keys(purpose, keys, unused_keys + 1)); +} + +TEST_CASE("Test revocation APIs", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(0)); + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(1)); + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(2)); + + TEST_ASSERT_FALSE(esp_efuse_get_write_protect_of_digest_revoke(0)); + TEST_ASSERT_FALSE(esp_efuse_get_write_protect_of_digest_revoke(1)); + TEST_ASSERT_FALSE(esp_efuse_get_write_protect_of_digest_revoke(2)); + + // esp_efuse_get_digest_revoke(3); // assert + + TEST_ESP_OK(esp_efuse_set_digest_revoke(0)); + TEST_ASSERT_TRUE(esp_efuse_get_digest_revoke(0)); + + TEST_ESP_OK(esp_efuse_set_digest_revoke(1)); + TEST_ASSERT_TRUE(esp_efuse_get_digest_revoke(1)); + + TEST_ESP_OK(esp_efuse_set_digest_revoke(2)); + TEST_ASSERT_TRUE(esp_efuse_get_digest_revoke(2)); + + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_set_digest_revoke(3)); + + TEST_ESP_OK(esp_efuse_set_write_protect_of_digest_revoke(0)); + TEST_ASSERT_TRUE(esp_efuse_get_write_protect_of_digest_revoke(0)); + TEST_ESP_OK(esp_efuse_set_write_protect_of_digest_revoke(1)); + TEST_ASSERT_TRUE(esp_efuse_get_write_protect_of_digest_revoke(1)); + TEST_ESP_OK(esp_efuse_set_write_protect_of_digest_revoke(2)); + TEST_ASSERT_TRUE(esp_efuse_get_write_protect_of_digest_revoke(2)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_efuse_set_write_protect_of_digest_revoke(3)); +} + +TEST_CASE("Test set_write_protect_of_digest_revoke", "[efuse]") +{ + esp_efuse_utility_reset(); + esp_efuse_utility_update_virt_blocks(); + esp_efuse_utility_debug_dump_blocks(); + + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(0)); + TEST_ASSERT_FALSE(esp_efuse_get_write_protect_of_digest_revoke(0)); + TEST_ESP_OK(esp_efuse_set_write_protect_of_digest_revoke(0)); + TEST_ASSERT_TRUE(esp_efuse_get_write_protect_of_digest_revoke(0)); + + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(1)); + TEST_ASSERT_FALSE(esp_efuse_get_write_protect_of_digest_revoke(1)); + TEST_ESP_OK(esp_efuse_set_write_protect_of_digest_revoke(1)); + TEST_ASSERT_TRUE(esp_efuse_get_write_protect_of_digest_revoke(1)); + + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(2)); + TEST_ASSERT_FALSE(esp_efuse_get_write_protect_of_digest_revoke(2)); + TEST_ESP_OK(esp_efuse_set_write_protect_of_digest_revoke(2)); + TEST_ASSERT_TRUE(esp_efuse_get_write_protect_of_digest_revoke(2)); + + TEST_ESP_OK(esp_efuse_set_digest_revoke(0)); + TEST_ESP_OK(esp_efuse_set_digest_revoke(1)); + TEST_ESP_OK(esp_efuse_set_digest_revoke(2)); + +#if CONFIG_IDF_ENV_FPGA && !CONFIG_EFUSE_VIRTUAL + // the write protection bits are set and the revocation bits will not be changed. + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(0)); + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(1)); + TEST_ASSERT_FALSE(esp_efuse_get_digest_revoke(2)); +#else + TEST_ASSERT_TRUE(esp_efuse_get_digest_revoke(0)); + TEST_ASSERT_TRUE(esp_efuse_get_digest_revoke(1)); + TEST_ASSERT_TRUE(esp_efuse_get_digest_revoke(2)); +#endif // CONFIG_IDF_ENV_FPGA && !CONFIG_EFUSE_VIRTUAL +} + +#endif // CONFIG_EFUSE_VIRTUAL || CONFIG_IDF_ENV_FPGA + +#endif // not CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index d7fe7b003a..7eb9aa5db7 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -290,6 +290,9 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_CODING ERR_TBL_IT(ESP_ERR_CODING), /* 5636 0x1604 Error while a encoding operation. */ +# endif +# ifdef ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS + ERR_TBL_IT(ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS), /* 5637 0x1605 Error not enough unused key blocks available */ # endif // components/bootloader_support/include/esp_image_format.h # ifdef ESP_ERR_IMAGE_BASE diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index 94bd103331..a506db4349 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -499,7 +499,7 @@ UT_034: UT_035: extends: .unit_test_s2_template - parallel: 46 + parallel: 47 tags: - ESP32S2_IDF - UT_T1_1