فهرست منبع

bootloader/esp32s2: Add using of efuse APIs for keys, purposes, wr/rd-protection bits for flash encryption, secure boot

Konstantin Kondrashov 5 سال پیش
والد
کامیت
fbba2cb356

+ 34 - 66
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;
-
-    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);
+    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   = 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;
 }

+ 38 - 45
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;
-        }
-
-        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;
+        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,
+        };
+
+        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;
     }
 

+ 34 - 69
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;
-
-    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);
+    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   = 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;
 }

+ 38 - 45
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;
-        }
-
-        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;
+        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,
+        };
+
+        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;
     }