diff --git a/components/bootloader_support/src/esp32s2/flash_encrypt.c b/components/bootloader_support/src/esp32s2/flash_encrypt.c index 9c624c6cf1..ad383ee296 100644 --- a/components/bootloader_support/src/esp32s2/flash_encrypt.c +++ b/components/bootloader_support/src/esp32s2/flash_encrypt.c @@ -24,7 +24,6 @@ #include "esp_log.h" #include "esp32s2/rom/secure_boot.h" #include "esp32s2/rom/cache.h" -#include "esp32s2/rom/efuse.h" #include "esp_efuse.h" #include "esp_efuse_table.h" #include "hal/wdt_hal.h" @@ -73,39 +72,26 @@ esp_err_t esp_flash_encrypt_check_and_update(void) } } -static bool s_key_dis_read(ets_efuse_block_t block) -{ - unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0; - return REG_GET_FIELD(EFUSE_RD_REPEAT_DATA0_REG, EFUSE_RD_DIS) & (EFUSE_RD_DIS_KEY0 << key_num); -} - -static bool s_key_dis_write(ets_efuse_block_t block) -{ - unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0; - return REG_GET_FIELD(EFUSE_RD_WR_DIS_REG, EFUSE_WR_DIS) & (EFUSE_WR_DIS_KEY0 << key_num); -} - static esp_err_t check_and_generate_encryption_keys(void) { - esp_err_t err = ESP_ERR_INVALID_STATE; - ets_efuse_block_t aes_128_key_block; - ets_efuse_block_t aes_256_key_block_1; - ets_efuse_block_t aes_256_key_block_2; + esp_efuse_block_t aes_128_key_block; + esp_efuse_block_t aes_256_key_block_1; + esp_efuse_block_t aes_256_key_block_2; - bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block); - bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, &aes_256_key_block_1); - bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, &aes_256_key_block_2); + bool has_aes128 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block); + bool has_aes256_1 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, &aes_256_key_block_1); + bool has_aes256_2 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, &aes_256_key_block_2); bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2); bool dis_write = false; bool dis_read = false; // If there are keys set, they must be write and read protected! if(has_key && has_aes128) { - dis_write = s_key_dis_write(aes_128_key_block); - dis_read = s_key_dis_read(aes_128_key_block); + dis_write = esp_efuse_get_key_dis_write(aes_128_key_block); + dis_read = esp_efuse_get_key_dis_read(aes_128_key_block); } else if (has_key && has_aes256_1 && has_aes256_2) { - dis_write = s_key_dis_write(aes_256_key_block_1) && s_key_dis_write(aes_256_key_block_2); - dis_read = s_key_dis_read(aes_256_key_block_1) && s_key_dis_read(aes_256_key_block_2); + dis_write = esp_efuse_get_key_dis_write(aes_256_key_block_1) && esp_efuse_get_key_dis_write(aes_256_key_block_2); + dis_read = esp_efuse_get_key_dis_read(aes_256_key_block_1) && esp_efuse_get_key_dis_read(aes_256_key_block_2); } if (!has_key && (has_aes256_1 || has_aes256_2)) { @@ -121,51 +107,30 @@ static esp_err_t check_and_generate_encryption_keys(void) if(!has_key && !dis_write && !dis_read) { ESP_LOGI(TAG, "Generating new flash encryption key..."); #ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256 - const unsigned BLOCKS_NEEDED = 2; - const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1; - const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2; + enum { BLOCKS_NEEDED = 2 }; + esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = { + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, + }; #else - const unsigned BLOCKS_NEEDED = 1; - const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY; - const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY; + enum { BLOCKS_NEEDED = 1 }; + esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = { + ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, + }; #endif - - if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) { - ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED); - return ESP_ERR_INVALID_STATE; + uint8_t keys[BLOCKS_NEEDED][32] = { 0 }; + for (int i = 0; i < BLOCKS_NEEDED; ++i) { + bootloader_fill_random(keys[i], 32); } - for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) { - uint32_t buf[8] = {0}; - bootloader_fill_random(buf, sizeof(buf)); - ets_efuse_block_t block = ets_efuse_find_unused_key_block(); - ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d", - block - ETS_EFUSE_BLOCK_KEY0, purpose); - - /* Note: everything else in this function is deferred as a batch write, but we write the - key (and write protect it) immediately as it's too fiddly to manage unused key blocks, etc. - in bootloader size footprint otherwise. */ - int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf)); - if (r != 0) { - ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", - block, purpose); - return ESP_FAIL; - } - - /* assuming numbering of esp_efuse_block_t matches ets_efuse_block_t */ - _Static_assert((int)EFUSE_BLK_KEY0 == (int)ETS_EFUSE_BLOCK_KEY0, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY1 == (int)ETS_EFUSE_BLOCK_KEY1, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY2 == (int)ETS_EFUSE_BLOCK_KEY2, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY3 == (int)ETS_EFUSE_BLOCK_KEY3, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY4 == (int)ETS_EFUSE_BLOCK_KEY4, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY5 == (int)ETS_EFUSE_BLOCK_KEY5, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - - // protect this block against reading after key is set (writing is done by ets_efuse_write_key) - err = esp_efuse_set_read_protect(block); - if(err != ESP_OK) { - ESP_LOGE(TAG, "Failed to set read protect to efuse block %d. Can't continue.", block); - return err; + esp_err_t err = esp_efuse_write_keys(purposes, keys, BLOCKS_NEEDED); + if (err != ESP_OK) { + if (err == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) { + ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED); + } else { + ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", err); } + return err; } ESP_LOGD(TAG, "Key generation complete"); return ESP_OK; @@ -181,7 +146,7 @@ static esp_err_t initialise_flash_encryption(void) esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ esp_err_t key_state = check_and_generate_encryption_keys(); - if(key_state != ESP_OK) { + if (key_state != ESP_OK) { esp_efuse_batch_write_cancel(); return key_state; } @@ -212,6 +177,9 @@ static esp_err_t initialise_flash_encryption(void) esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); esp_err_t err = esp_efuse_batch_write_commit(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err); + } return err; } diff --git a/components/bootloader_support/src/esp32s2/secure_boot.c b/components/bootloader_support/src/esp32s2/secure_boot.c index 7a8ac94f6a..970e6ca3ae 100644 --- a/components/bootloader_support/src/esp32s2/secure_boot.c +++ b/components/bootloader_support/src/esp32s2/secure_boot.c @@ -155,15 +155,8 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin return ret; } -esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) +static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t *image_data) { - ESP_LOGI(TAG, "enabling secure boot v2 - ESP32-S2..."); - - if (esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing.."); - return ESP_OK; - } - esp_err_t ret; /* Verify the bootloader */ esp_image_metadata_t bootloader_data = { 0 }; @@ -174,12 +167,11 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } /* Check if secure boot digests are present */ - bool has_secure_boot_digest = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL); - has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL); - has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL); + bool has_secure_boot_digest = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL); + has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL); + has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL); ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating.."); - ets_efuse_clear_program_registers(); if (!has_secure_boot_digest) { image_sig_public_key_digests_t boot_key_digests = {0}; image_sig_public_key_digests_t app_key_digests = {0}; @@ -197,30 +189,20 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } ESP_LOGI(TAG, "%d signature block(s) found appended to the bootloader.", boot_key_digests.num_digests); - int unused_key_slots = ets_efuse_count_unused_key_blocks(); - if (boot_key_digests.num_digests > unused_key_slots) { - ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots(%d).", boot_key_digests.num_digests, unused_key_slots); - return ESP_FAIL; - } + esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, + }; - for (int i = 0; i < boot_key_digests.num_digests; i++) { - ets_efuse_block_t block; - const uint32_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, - ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 }; - - block = ets_efuse_find_unused_key_block(); - if (block == ETS_EFUSE_BLOCK_MAX) { - ESP_LOGE(TAG, "No more unused key blocks available."); - return ESP_FAIL; + ret = esp_efuse_write_keys(secure_boot_key_purpose, boot_key_digests.key_digests, boot_key_digests.num_digests); + if (ret) { + if (ret == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) { + ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots.", boot_key_digests.num_digests); + } else { + ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", ret); } - - int r = ets_efuse_write_key(block, secure_boot_key_purpose[i], boot_key_digests.key_digests[i], DIGEST_LEN); - if (r != 0) { - ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", block, secure_boot_key_purpose[i]); - return ESP_FAIL; - } - - // Note: write key will write protect both the block and the purpose eFuse, always + return ret; } /* Generate the application public key digests */ @@ -243,12 +225,10 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag /* Confirm if at least one public key from the application matches a public key in the bootloader (Also, ensure if that public revoke bit is not set for the matched key) */ bool match = false; - const uint32_t revoke_bits[SECURE_BOOT_NUM_BLOCKS] = { EFUSE_SECURE_BOOT_KEY_REVOKE0, - EFUSE_SECURE_BOOT_KEY_REVOKE1, EFUSE_SECURE_BOOT_KEY_REVOKE2 }; for (int i = 0; i < boot_key_digests.num_digests; i++) { - if (REG_GET_BIT(EFUSE_RD_REPEAT_DATA1_REG, revoke_bits[i])) { + if (esp_efuse_get_digest_revoke(i)) { ESP_LOGI(TAG, "Key block(%d) has been revoked.", i); continue; // skip if the key block is revoked } @@ -271,15 +251,28 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag /* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */ for (uint8_t i = boot_key_digests.num_digests; i < SECURE_BOOT_NUM_BLOCKS; i++) { ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i); - ets_secure_boot_revoke_public_key_digest(i); + esp_efuse_set_digest_revoke(i); } } } + return ESP_OK; +} - esp_err_t err = esp_efuse_batch_write_begin(); - if (err != ESP_OK) { - ESP_LOGI(TAG, "Error batch programming security eFuses."); - return err; +esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) +{ + ESP_LOGI(TAG, "enabling secure boot v2 - ESP32-S2..."); + + if (esp_secure_boot_enabled()) { + ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing.."); + return ESP_OK; + } + + esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ + + esp_err_t key_state = check_and_generate_secure_boot_keys(image_data); + if (key_state != ESP_OK) { + esp_efuse_batch_write_cancel(); + return key_state; } __attribute__((unused)) static const uint8_t enable = 1; @@ -308,9 +301,9 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); - err = esp_efuse_batch_write_commit(); + esp_err_t err = esp_efuse_batch_write_commit(); if (err != ESP_OK) { - ESP_LOGI(TAG, "Error programming security eFuses."); + ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err); return err; } diff --git a/components/bootloader_support/src/esp32s3/flash_encrypt.c b/components/bootloader_support/src/esp32s3/flash_encrypt.c index a29dc429e2..99ba1e41fe 100644 --- a/components/bootloader_support/src/esp32s3/flash_encrypt.c +++ b/components/bootloader_support/src/esp32s3/flash_encrypt.c @@ -71,43 +71,26 @@ esp_err_t esp_flash_encrypt_check_and_update(void) } } -static bool s_key_dis_read(ets_efuse_block_t block) -{ - // TODO: eFuse support on ESP32-S3 - // unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0; - // return REG_GET_FIELD(EFUSE_RD_REPEAT_DATA0_REG, EFUSE_RD_DIS) & (EFUSE_RD_DIS_KEY0 << key_num); - return true; -} - -static bool s_key_dis_write(ets_efuse_block_t block) -{ - // TODO: eFuse support on ESP32-S3 - // unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0; - // return REG_GET_FIELD(EFUSE_RD_WR_DIS_REG, EFUSE_WR_DIS) & (EFUSE_WR_DIS_KEY0 << key_num); - return true; -} - static esp_err_t check_and_generate_encryption_keys(void) { - esp_err_t err = ESP_ERR_INVALID_STATE; - ets_efuse_block_t aes_128_key_block; - ets_efuse_block_t aes_256_key_block_1; - ets_efuse_block_t aes_256_key_block_2; + esp_efuse_block_t aes_128_key_block; + esp_efuse_block_t aes_256_key_block_1; + esp_efuse_block_t aes_256_key_block_2; - bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block); - bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, &aes_256_key_block_1); - bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, &aes_256_key_block_2); + bool has_aes128 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block); + bool has_aes256_1 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, &aes_256_key_block_1); + bool has_aes256_2 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, &aes_256_key_block_2); bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2); bool dis_write = false; bool dis_read = false; // If there are keys set, they must be write and read protected! if(has_key && has_aes128) { - dis_write = s_key_dis_write(aes_128_key_block); - dis_read = s_key_dis_read(aes_128_key_block); + dis_write = esp_efuse_get_key_dis_write(aes_128_key_block); + dis_read = esp_efuse_get_key_dis_read(aes_128_key_block); } else if (has_key && has_aes256_1 && has_aes256_2) { - dis_write = s_key_dis_write(aes_256_key_block_1) && s_key_dis_write(aes_256_key_block_2); - dis_read = s_key_dis_read(aes_256_key_block_1) && s_key_dis_read(aes_256_key_block_2); + dis_write = esp_efuse_get_key_dis_write(aes_256_key_block_1) && esp_efuse_get_key_dis_write(aes_256_key_block_2); + dis_read = esp_efuse_get_key_dis_read(aes_256_key_block_1) && esp_efuse_get_key_dis_read(aes_256_key_block_2); } if (!has_key && (has_aes256_1 || has_aes256_2)) { @@ -123,51 +106,30 @@ static esp_err_t check_and_generate_encryption_keys(void) if(!has_key && !dis_write && !dis_read) { ESP_LOGI(TAG, "Generating new flash encryption key..."); #ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256 - const unsigned BLOCKS_NEEDED = 2; - const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1; - const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2; + enum { BLOCKS_NEEDED = 2 }; + esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = { + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, + ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, + }; #else - const unsigned BLOCKS_NEEDED = 1; - const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY; - const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY; + enum { BLOCKS_NEEDED = 1 }; + esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = { + ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, + }; #endif - - if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) { - ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED); - return ESP_ERR_INVALID_STATE; + uint8_t keys[BLOCKS_NEEDED][32] = { 0 }; + for (int i = 0; i < BLOCKS_NEEDED; ++i) { + bootloader_fill_random(keys[i], 32); } - for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) { - uint32_t buf[8] = {0}; - bootloader_fill_random(buf, sizeof(buf)); - ets_efuse_block_t block = ets_efuse_find_unused_key_block(); - ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d", - block - ETS_EFUSE_BLOCK_KEY0, purpose); - - /* Note: everything else in this function is deferred as a batch write, but we write the - key (and write protect it) immediately as it's too fiddly to manage unused key blocks, etc. - in bootloader size footprint otherwise. */ - int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf)); - if (r != 0) { - ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", - block, purpose); - return ESP_FAIL; - } - - /* assuming numbering of esp_efuse_block_t matches ets_efuse_block_t */ - _Static_assert((int)EFUSE_BLK_KEY0 == (int)ETS_EFUSE_BLOCK_KEY0, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY1 == (int)ETS_EFUSE_BLOCK_KEY1, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY2 == (int)ETS_EFUSE_BLOCK_KEY2, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY3 == (int)ETS_EFUSE_BLOCK_KEY3, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY4 == (int)ETS_EFUSE_BLOCK_KEY4, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - _Static_assert((int)EFUSE_BLK_KEY5 == (int)ETS_EFUSE_BLOCK_KEY5, "esp_efuse_block_t doesn't match ets_efuse_block_t"); - - // protect this block against reading after key is set (writing is done by ets_efuse_write_key) - err = esp_efuse_set_read_protect(block); - if(err != ESP_OK) { - ESP_LOGE(TAG, "Failed to set read protect to efuse block %d. Can't continue.", block); - return err; + esp_err_t err = esp_efuse_write_keys(purposes, keys, BLOCKS_NEEDED); + if (err != ESP_OK) { + if (err == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) { + ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED); + } else { + ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", err); } + return err; } ESP_LOGD(TAG, "Key generation complete"); return ESP_OK; @@ -183,7 +145,7 @@ static esp_err_t initialise_flash_encryption(void) esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ esp_err_t key_state = check_and_generate_encryption_keys(); - if(key_state != ESP_OK) { + if (key_state != ESP_OK) { esp_efuse_batch_write_cancel(); return key_state; } @@ -213,6 +175,9 @@ static esp_err_t initialise_flash_encryption(void) esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT); esp_err_t err = esp_efuse_batch_write_commit(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err); + } return err; } diff --git a/components/bootloader_support/src/esp32s3/secure_boot.c b/components/bootloader_support/src/esp32s3/secure_boot.c index bec0c27f34..823fe5d973 100644 --- a/components/bootloader_support/src/esp32s3/secure_boot.c +++ b/components/bootloader_support/src/esp32s3/secure_boot.c @@ -155,15 +155,8 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin return ret; } -esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) +static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t *image_data) { - ESP_LOGI(TAG, "enabling secure boot v2 - ESP32-S2..."); - - if (esp_secure_boot_enabled()) { - ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing.."); - return ESP_OK; - } - esp_err_t ret; /* Verify the bootloader */ esp_image_metadata_t bootloader_data = { 0 }; @@ -174,12 +167,11 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } /* Check if secure boot digests are present */ - bool has_secure_boot_digest = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL); - has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL); - has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL); + bool has_secure_boot_digest = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL); + has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL); + has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL); ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating.."); - ets_efuse_clear_program_registers(); if (!has_secure_boot_digest) { image_sig_public_key_digests_t boot_key_digests = {0}; image_sig_public_key_digests_t app_key_digests = {0}; @@ -197,30 +189,20 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag } ESP_LOGI(TAG, "%d signature block(s) found appended to the bootloader.", boot_key_digests.num_digests); - int unused_key_slots = ets_efuse_count_unused_key_blocks(); - if (boot_key_digests.num_digests > unused_key_slots) { - ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots(%d).", boot_key_digests.num_digests, unused_key_slots); - return ESP_FAIL; - } + esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, + ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, + }; - for (int i = 0; i < boot_key_digests.num_digests; i++) { - ets_efuse_block_t block; - const uint32_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, - ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 }; - - block = ets_efuse_find_unused_key_block(); - if (block == ETS_EFUSE_BLOCK_MAX) { - ESP_LOGE(TAG, "No more unused key blocks available."); - return ESP_FAIL; + ret = esp_efuse_write_keys(secure_boot_key_purpose, boot_key_digests.key_digests, boot_key_digests.num_digests); + if (ret) { + if (ret == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) { + ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots.", boot_key_digests.num_digests); + } else { + ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", ret); } - - int r = ets_efuse_write_key(block, secure_boot_key_purpose[i], boot_key_digests.key_digests[i], DIGEST_LEN); - if (r != 0) { - ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", block, secure_boot_key_purpose[i]); - return ESP_FAIL; - } - - // Note: write key will write protect both the block and the purpose eFuse, always + return ret; } /* Generate the application public key digests */ @@ -243,12 +225,10 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag /* Confirm if at least one public key from the application matches a public key in the bootloader (Also, ensure if that public revoke bit is not set for the matched key) */ bool match = false; - const uint32_t revoke_bits[SECURE_BOOT_NUM_BLOCKS] = { EFUSE_SECURE_BOOT_KEY_REVOKE0, - EFUSE_SECURE_BOOT_KEY_REVOKE1, EFUSE_SECURE_BOOT_KEY_REVOKE2 }; for (int i = 0; i < boot_key_digests.num_digests; i++) { - if (REG_GET_BIT(EFUSE_RD_REPEAT_DATA1_REG, revoke_bits[i])) { + if (esp_efuse_get_digest_revoke(i)) { ESP_LOGI(TAG, "Key block(%d) has been revoked.", i); continue; // skip if the key block is revoked } @@ -271,15 +251,28 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag /* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */ for (uint8_t i = boot_key_digests.num_digests; i < SECURE_BOOT_NUM_BLOCKS; i++) { ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i); - ets_secure_boot_revoke_public_key_digest(i); + esp_efuse_set_digest_revoke(i); } } } + return ESP_OK; +} - esp_err_t err = esp_efuse_batch_write_begin(); - if (err != ESP_OK) { - ESP_LOGI(TAG, "Error batch programming security eFuses."); - return err; +esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data) +{ + ESP_LOGI(TAG, "enabling secure boot v2 - ESP32-S2..."); + + if (esp_secure_boot_enabled()) { + ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing.."); + return ESP_OK; + } + + esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */ + + esp_err_t key_state = check_and_generate_secure_boot_keys(image_data); + if (key_state != ESP_OK) { + esp_efuse_batch_write_cancel(); + return key_state; } __attribute__((unused)) static const uint8_t enable = 1; @@ -307,9 +300,9 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN); - err = esp_efuse_batch_write_commit(); + esp_err_t err = esp_efuse_batch_write_commit(); if (err != ESP_OK) { - ESP_LOGI(TAG, "Error programming security eFuses."); + ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err); return err; }