mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/esp_efuse_adds_funcs_key_blocks__purposes' into 'master'
efuse: Add functions working with key, purposes, revoke & protection Closes IDF-1976 See merge request espressif/esp-idf!10876
This commit is contained in:
commit
9fd5138ce2
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 <sys/lock.h>
|
||||
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
|
||||
|
@ -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
|
||||
|
368
components/efuse/test/test_efuse_keys.c
Normal file
368
components/efuse/test/test_efuse_keys.c
Normal file
@ -0,0 +1,368 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#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
|
@ -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
|
||||
|
@ -499,7 +499,7 @@ UT_034:
|
||||
|
||||
UT_035:
|
||||
extends: .unit_test_s2_template
|
||||
parallel: 46
|
||||
parallel: 47
|
||||
tags:
|
||||
- ESP32S2_IDF
|
||||
- UT_T1_1
|
||||
|
Loading…
Reference in New Issue
Block a user