From 4ac351247d3fdc98ed2e5a8ef42ad22b3099be86 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Wed, 27 Oct 2021 17:51:01 +0530 Subject: [PATCH 1/2] secure_boot_v2: fix issue in pre-flashed digest (manual) workflow This commit fixes issue where empty (unprogrammed) digest slot out of multiple supported (e.g. 3 for ESP32-C3) could cause issue in workflow enablement process. Notes: 1. This issue was applicable for chips supporting "secure-boot-v2" scheme with multiple digests slots 2. This issue was affecting only manual workflow, where digest of public was pre-flashed in efuse 3. Change in "flash_encrypt.c" is only for additional safety purpose --- .../src/flash_encryption/flash_encrypt.c | 3 ++- .../src/secure_boot_v2/secure_boot.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/components/bootloader_support/src/flash_encryption/flash_encrypt.c b/components/bootloader_support/src/flash_encryption/flash_encrypt.c index e61922e19d..4ca3fbc368 100644 --- a/components/bootloader_support/src/flash_encryption/flash_encrypt.c +++ b/components/bootloader_support/src/flash_encryption/flash_encrypt.c @@ -104,7 +104,8 @@ static esp_err_t check_and_generate_encryption_keys(void) #endif // CONFIG_SECURE_FLASH_ENCRYPTION_AES256 #endif // CONFIG_IDF_TARGET_ESP32 - esp_efuse_block_t blocks[BLOCKS_NEEDED]; + /* Initialize all efuse block entries to invalid (max) value */ + esp_efuse_block_t blocks[BLOCKS_NEEDED] = {[0 ... BLOCKS_NEEDED-1] = EFUSE_BLK_KEY_MAX}; bool has_key = true; for (unsigned i = 0; i < BLOCKS_NEEDED; i++) { bool tmp_has_key = esp_efuse_find_purpose(purposes[i], &blocks[i]); diff --git a/components/bootloader_support/src/secure_boot_v2/secure_boot.c b/components/bootloader_support/src/secure_boot_v2/secure_boot.c index 650fa7fcce..37223a89b6 100644 --- a/components/bootloader_support/src/secure_boot_v2/secure_boot.c +++ b/components/bootloader_support/src/secure_boot_v2/secure_boot.c @@ -156,11 +156,11 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t return ret; } + /* Initialize all efuse block entries to invalid (max) value */ + esp_efuse_block_t blocks[SECURE_BOOT_NUM_BLOCKS] = {[0 ... SECURE_BOOT_NUM_BLOCKS-1] = EFUSE_BLK_KEY_MAX}; /* Check if secure boot digests are present */ - esp_efuse_block_t blocks[SECURE_BOOT_NUM_BLOCKS]; bool has_secure_boot_digest = false; for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { - blocks[i] = EFUSE_BLK_KEY_MAX; bool tmp_has_key = esp_efuse_find_purpose(secure_boot_key_purpose[i], &blocks[i]); if (tmp_has_key) { // For ESP32: esp_efuse_find_purpose() always returns True, need to check whether the key block is used or not. tmp_has_key &= !esp_efuse_key_block_unused(blocks[i]); @@ -198,6 +198,12 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t } } else { for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) { + /* Check if corresponding digest slot is used or not */ + if (blocks[i] == EFUSE_BLK_KEY_MAX) { + ESP_LOGD(TAG, "SECURE_BOOT_DIGEST%d slot is not used", i); + continue; + } + #if SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS if (esp_efuse_get_digest_revoke(i)) { continue; From 4d0e72dc5fc4e65c00c590788d13c2f46471956a Mon Sep 17 00:00:00 2001 From: KonstantinKondrashov Date: Wed, 27 Oct 2021 23:02:07 +0800 Subject: [PATCH 2/2] efuse example: Fix pre-load SB test for S2, C3 (erase revoke bits) --- examples/system/efuse/example_test.py | 57 +++++++++++++++++++-------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/examples/system/efuse/example_test.py b/examples/system/efuse/example_test.py index ddb2a2557c..1d430c8ba4 100644 --- a/examples/system/efuse/example_test.py +++ b/examples/system/efuse/example_test.py @@ -6,17 +6,21 @@ import re import ttfw_idf -def erase_field_on_emul_efuse(dut, bit_pos): # type: (ttfw_idf.TinyFW.Env, int) -> None +def erase_field_on_emul_efuse(dut, pos_of_bits): # type: (ttfw_idf.TinyFW.Env, list) -> None emul_efuse_bin_path = os.path.join(dut.app.binary_path, 'emul_efuse.bin') dut.dump_flash(emul_efuse_bin_path, partition='emul_efuse') - nbytes, nbits = divmod(bit_pos, 8) - with open(emul_efuse_bin_path, 'r+b') as f: - f.seek(nbytes, 0) - c = f.read(1) - toggled = bytes([ord(c) ^ (1 << nbits)]) - f.seek(-1, 1) # or absolute: f.seek(nbytes, 0) - f.write(toggled) + def erase_bit(pos_of_bit): # type: (int) -> None + nbytes, nbits = divmod(pos_of_bit, 8) + with open(emul_efuse_bin_path, 'r+b') as f: + f.seek(nbytes) + data = ord(f.read(1)) + data &= ~(1 << nbits) + f.seek(-1, os.SEEK_CUR) + f.write(bytes([data])) + + for pos_of_bit in sorted(pos_of_bits): + erase_bit(pos_of_bit) offs = dut.app.partition_table['emul_efuse']['offset'] flash_files = [(offs, emul_efuse_bin_path)] @@ -153,10 +157,16 @@ def test_examples_efuse_with_virt_flash_enc_pre_loaded(env, _): # type: (ttfw_i if dut.TARGET == 'esp32': print(' - Flash emul_efuse with pre-loaded efuses (FLASH_CRYPT_CNT 1 -> 0)') - erase_field_on_emul_efuse(dut, 0 * 32 + 20) + # offset of this eFuse is taken from components/efuse/esp32/esp_efuse_table.csv + FLASH_CRYPT_CNT = 20 + # Resets eFuse, which enables Flash encryption feature + erase_field_on_emul_efuse(dut, [FLASH_CRYPT_CNT]) else: + # offset of this eFuse is taken from components/efuse/{target}/esp_efuse_table.csv print(' - Flash emul_efuse with pre-loaded efuses (SPI_BOOT_CRYPT_CNT 1 -> 0)') - erase_field_on_emul_efuse(dut, 2 * 32 + 18) + SPI_BOOT_CRYPT_CNT = 82 + # Resets eFuse, which enables Flash encryption feature + erase_field_on_emul_efuse(dut, [SPI_BOOT_CRYPT_CNT]) print(' - Start app (flash partition_table and app)') dut.start_app_no_enc() @@ -298,7 +308,10 @@ def test_examples_efuse_with_virt_secure_boot_v1_pre_loaded(env, _): # type: (t dut.expect('example: Done') print(' - Flash emul_efuse with pre-loaded efuses (ABS_DONE_0 1 -> 0)') - erase_field_on_emul_efuse(dut, 6 * 32 + 4) + # offset of this eFuse is taken from components/efuse/esp32/esp_efuse_table.csv + ABS_DONE_0 = 196 + # Resets eFuse, which enables Secure boot (V1) feature + erase_field_on_emul_efuse(dut, [ABS_DONE_0]) print(' - Start app (flash partition_table and app)') dut.start_app() @@ -410,7 +423,10 @@ def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(env, _): # type: (t dut.expect('example: Done') print(' - Flash emul_efuse with pre-loaded efuses (ABS_DONE_1 1 -> 0)') - erase_field_on_emul_efuse(dut, 6 * 32 + 5) + # offset of this eFuse is taken from components/efuse/esp32/esp_efuse_table.csv + ABS_DONE_1 = 197 + # Resets eFuse, which enables Secure boot (V2) feature + erase_field_on_emul_efuse(dut, [ABS_DONE_1]) print(' - Start app (flash partition_table and app)') dut.start_app() @@ -453,7 +469,7 @@ def test_examples_efuse_with_virt_secure_boot_v2_pre_loaded(env, _): # type: (t dut.expect('example: Done') -@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2']) +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2', 'esp32c3']) def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None dut = env.get_dut('efuse', 'examples/system/efuse', app_config_name='virt_secure_boot_v2') # check and log bin size @@ -512,7 +528,7 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx(env, _): # type: (ttfw dut.expect('example: Done') -@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2']) +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2', 'esp32c3']) def test_examples_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None dut = env.get_dut('efuse', 'examples/system/efuse', app_config_name='virt_secure_boot_v2') @@ -528,8 +544,15 @@ def test_examples_efuse_with_virt_secure_boot_v2_esp32xx_pre_loaded(env, _): # dut.expect('Start eFuse example') dut.expect('example: Done') - print(' - Flash emul_efuse with pre-loaded efuses (SECURE_BOOT_EN 1 -> 0)') - erase_field_on_emul_efuse(dut, 3 * 32 + 20) + print(' - Flash emul_efuse with pre-loaded efuses (SECURE_BOOT_EN 1 -> 0, SECURE_BOOT_KEY_REVOKE[0..2] -> 0)') + # offsets of eFuses are taken from components/efuse/{target}/esp_efuse_table.csv + SECURE_BOOT_EN = 116 + SECURE_BOOT_KEY_REVOKE0 = 85 + SECURE_BOOT_KEY_REVOKE1 = 86 + SECURE_BOOT_KEY_REVOKE2 = 87 + # Resets eFuse, which enables Secure boot feature + # Resets eFuses, which control digest slots + erase_field_on_emul_efuse(dut, [SECURE_BOOT_EN, SECURE_BOOT_KEY_REVOKE0, SECURE_BOOT_KEY_REVOKE1, SECURE_BOOT_KEY_REVOKE2]) print(' - Start app (flash partition_table and app)') dut.start_app() @@ -707,7 +730,7 @@ def test_examples_efuse_with_virt_sb_v2_and_fe(env, _): # type: (ttfw_idf.TinyF dut.expect('example: Done') -@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2']) +@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32s2', 'esp32c3']) def test_examples_efuse_with_virt_sb_v2_and_fe_esp32xx(env, _): # type: (ttfw_idf.TinyFW.Env, None) -> None dut = env.get_dut('efuse', 'examples/system/efuse', app_config_name='virt_sb_v2_and_fe') # check and log bin size