From 0b86bcd35fae6f75f245fba0a606a88dbec46677 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Tue, 23 May 2023 15:54:37 +0530 Subject: [PATCH] efuse: use esp32 qemu target for a efuses example test. The efuses example test with secure boot v2 and flash encryption enabled can be run on the esp32 qemu image. --- .gitlab-ci.yml | 2 +- examples/system/efuse/main/Kconfig.projbuild | 7 ++ examples/system/efuse/main/efuse_main.c | 11 ++- .../efuse/pytest_system_efuse_example.py | 84 ++++++++++++++++++ .../sdkconfig.ci.virt_sb_v2_and_fe.esp32.qemu | 22 +++++ .../system/efuse/test/esp32eco3_efuses.bin | Bin 0 -> 124 bytes 6 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 examples/system/efuse/main/Kconfig.projbuild create mode 100644 examples/system/efuse/sdkconfig.ci.virt_sb_v2_and_fe.esp32.qemu create mode 100644 examples/system/efuse/test/esp32eco3_efuses.bin diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 17d7678c0a..885260a04c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ variables: ESP_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-env-v5.2:1" CLANG_STATIC_ANALYSIS_IMAGE: "${CI_DOCKER_REGISTRY}/clang-static-analysis-v5.2:1-1" ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env-v5.2:1-1" - QEMU_IMAGE: "${CI_DOCKER_REGISTRY}/qemu-v5.2:1-20220802" + QEMU_IMAGE: "${CI_DOCKER_REGISTRY}/qemu-v5.2:1-20230522" TARGET_TEST_ENV_IMAGE: "$CI_DOCKER_REGISTRY/target-test-env-v5.2:1" SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:3" diff --git a/examples/system/efuse/main/Kconfig.projbuild b/examples/system/efuse/main/Kconfig.projbuild new file mode 100644 index 0000000000..02b7f980e3 --- /dev/null +++ b/examples/system/efuse/main/Kconfig.projbuild @@ -0,0 +1,7 @@ +menu "Example Configuration" + + config EXAMPLE_TEST_RUN_USING_QEMU + bool "Run example test using Qemu" + help + Enabling this option emulates the example test under the QEMU environment. +endmenu diff --git a/examples/system/efuse/main/efuse_main.c b/examples/system/efuse/main/efuse_main.c index 53afd94600..2b6238892f 100644 --- a/examples/system/efuse/main/efuse_main.c +++ b/examples/system/efuse/main/efuse_main.c @@ -78,7 +78,7 @@ static void read_efuse_fields(device_desc_t *desc) } -#ifdef CONFIG_EFUSE_VIRTUAL +#if defined(CONFIG_EFUSE_VIRTUAL) || defined(CONFIG_EXAMPLE_TEST_RUN_USING_QEMU) static void write_efuse_fields(device_desc_t *desc, esp_efuse_coding_scheme_t coding_scheme) { #if CONFIG_IDF_TARGET_ESP32 @@ -104,7 +104,7 @@ static void write_efuse_fields(device_desc_t *desc, esp_efuse_coding_scheme_t co ESP_ERROR_CHECK(esp_efuse_batch_write_commit()); } } -#endif // CONFIG_EFUSE_VIRTUAL +#endif // defined(CONFIG_EFUSE_VIRTUAL) || defined(CONFIG_EXAMPLE_TEST_RUN_USING_QEMU) static esp_efuse_coding_scheme_t get_coding_scheme(void) @@ -154,7 +154,10 @@ void app_main(void) device_desc_t device_desc = { 0 }; read_efuse_fields(&device_desc); +#if !CONFIG_EXAMPLE_TEST_RUN_USING_QEMU ESP_LOGW(TAG, "This example does not burn any efuse in reality only virtually"); +#endif + #if CONFIG_IDF_TARGET_ESP32C2 if (esp_secure_boot_enabled() || esp_flash_encryption_enabled()) { @@ -165,8 +168,10 @@ void app_main(void) } #endif -#ifdef CONFIG_EFUSE_VIRTUAL +#if defined(CONFIG_EFUSE_VIRTUAL) || defined(CONFIG_EXAMPLE_TEST_RUN_USING_QEMU) +#if !CONFIG_EXAMPLE_TEST_RUN_USING_QEMU ESP_LOGW(TAG, "Write operations in efuse fields are performed virtually"); +#endif if (device_desc.device_role == 0) { device_desc.module_version = 1; device_desc.device_role = 2; diff --git a/examples/system/efuse/pytest_system_efuse_example.py b/examples/system/efuse/pytest_system_efuse_example.py index aa3c557d8c..85d854c48e 100644 --- a/examples/system/efuse/pytest_system_efuse_example.py +++ b/examples/system/efuse/pytest_system_efuse_example.py @@ -7,6 +7,7 @@ import os import pytest from pytest_embedded import Dut +from pytest_embedded_qemu.dut import QemuDut @pytest.mark.generic @@ -845,6 +846,89 @@ def test_examples_efuse_with_virt_sb_v2_and_fe(dut: Dut) -> None: dut.expect('example: Done') +@pytest.mark.esp32 +@pytest.mark.host_test +@pytest.mark.qemu +@pytest.mark.parametrize('config', ['virt_sb_v2_and_fe.esp32.qemu',], indirect=True) +@pytest.mark.parametrize( + 'qemu_extra_args', + [ + f'-drive file={os.path.join(os.path.dirname(__file__), "test", "esp32eco3_efuses.bin")},if=none,format=raw,id=efuse ' + '-global driver=nvram.esp32.efuse,property=drive,value=efuse ' + '-global driver=timer.esp32.timg,property=wdt_disable,value=true', + ], + indirect=True, +) +def test_examples_efuse_with_virt_sb_v2_and_fe_qemu(dut: QemuDut) -> None: + try: + dut.expect('secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set') + dut.expect('secure_boot_v2: Verifying with RSA-PSS...') + dut.expect('secure_boot_v2: Signature verified successfully!') + + dut.expect('secure_boot_v2: enabling secure boot v2...') + dut.expect('Verifying image signature...') + dut.expect('secure_boot_v2: Secure boot V2 is not enabled yet and eFuse digest keys are not set') + dut.expect('secure_boot_v2: Verifying with RSA-PSS...') + dut.expect('secure_boot_v2: Signature verified successfully') + dut.expect('secure_boot_v2: Secure boot digests absent, generating..') + dut.expect('secure_boot_v2: Digests successfully calculated, 1 valid signatures') + dut.expect_exact('secure_boot_v2: 1 signature block(s) found appended to the bootloader') + + dut.expect('Writing EFUSE_BLK_KEY1 with purpose 3') + dut.expect('secure_boot_v2: Digests successfully calculated, 1 valid signatures') + dut.expect_exact('secure_boot_v2: 1 signature block(s) found appended to the app') + dut.expect_exact('secure_boot_v2: Application key(0) matches with bootloader key(0)') + + dut.expect('secure_boot_v2: blowing secure boot efuse...') + dut.expect('Disable JTAG...') + dut.expect('Disable ROM BASIC interpreter fallback...') + dut.expect('Disable ROM Download mode...') + dut.expect('secure_boot_v2: Secure boot permanently enabled') + + dut.expect('Checking flash encryption...') + dut.expect('flash_encrypt: Generating new flash encryption key...') + dut.expect('Writing EFUSE_BLK_KEY0 with purpose 2') + dut.expect('flash_encrypt: Setting CRYPT_CONFIG efuse to 0xF') + dut.expect('flash_encrypt: Not disabling UART bootloader encryption') + dut.expect('flash_encrypt: Disable UART bootloader decryption...') + dut.expect('flash_encrypt: Disable UART bootloader MMU cache...') + dut.expect('flash_encrypt: Disable JTAG...') + dut.expect('flash_encrypt: Disable ROM BASIC interpreter fallback...') + + dut.expect('Verifying image signature...') + dut.expect('secure_boot_v2: Verifying with RSA-PSS...') + dut.expect('secure_boot_v2: Signature verified successfully!') + dut.expect('flash_encrypt: bootloader encrypted successfully') + dut.expect('flash_encrypt: partition table encrypted and loaded successfully') + + dut.expect('Verifying image signature...') + dut.expect('secure_boot_v2: Verifying with RSA-PSS...') + dut.expect('secure_boot_v2: Signature verified successfully!') + dut.expect('flash_encrypt: Flash encryption completed', timeout=120) + dut.expect('Resetting with flash encryption enabled...') + + dut.expect('Verifying image signature...', timeout=180) + dut.expect('secure_boot_v2: Verifying with RSA-PSS...') + dut.expect('secure_boot_v2: Signature verified successfully!') + dut.expect('secure_boot_v2: enabling secure boot v2...') + dut.expect('secure_boot_v2: secure boot v2 is already enabled, continuing..') + dut.expect_exact('flash_encrypt: flash encryption is enabled (3 plaintext flashes left)') + dut.expect_exact('flash_encrypt: Flash encryption mode is DEVELOPMENT (not secure)') + dut.expect('main_task: Calling app_main()') + dut.expect('Start eFuse example') + dut.expect('example: Flash Encryption is NOT in RELEASE mode') + dut.expect('example: Secure Boot is in RELEASE mode') + dut.expect('example: Done') + + finally: + # the above example test burns the efuses, and hence the efuses file which the + # qemu uses to emulate the efuses, "test/esp32eco3_efuses.bin", gets modified. + # Thus, restore the efuses file values back to the default ESP32-ECO3 efuses values. + with open(os.path.join(os.path.dirname(__file__), 'test', 'esp32eco3_efuses.bin'), 'wb') as efuse_file: + esp32eco3_efuses = '0' * 26 + '8' + '0' * 17 + '1' + '0' * 203 + efuse_file.write(bytearray.fromhex(esp32eco3_efuses)) + + @pytest.mark.esp32c3 @pytest.mark.esp32c2 @pytest.mark.esp32c6 diff --git a/examples/system/efuse/sdkconfig.ci.virt_sb_v2_and_fe.esp32.qemu b/examples/system/efuse/sdkconfig.ci.virt_sb_v2_and_fe.esp32.qemu new file mode 100644 index 0000000000..e1dde3dd6f --- /dev/null +++ b/examples/system/efuse/sdkconfig.ci.virt_sb_v2_and_fe.esp32.qemu @@ -0,0 +1,22 @@ +# FLASH_ENCRYPTION & SECURE_BOOT_V2 with target QEMU + +CONFIG_IDF_TARGET="esp32" + +CONFIG_EFUSE_VIRTUAL=n +# ESP32 supports SECURE_BOOT_V2 only in ECO3 +CONFIG_ESP32_REV_MIN_3=y +CONFIG_ESP32_REV_MIN=3 + +CONFIG_PARTITION_TABLE_OFFSET=0xD000 +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="test/partitions_efuse_emul.csv" + +CONFIG_SECURE_BOOT=y +CONFIG_SECURE_BOOT_V2_ENABLED=y +CONFIG_SECURE_BOOT_SIGNING_KEY="test/secure_boot_signing_key.pem" +CONFIG_SECURE_DISABLE_ROM_DL_MODE=y + +CONFIG_SECURE_FLASH_ENC_ENABLED=y + +CONFIG_EXAMPLE_TEST_RUN_USING_QEMU=y +CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT=y diff --git a/examples/system/efuse/test/esp32eco3_efuses.bin b/examples/system/efuse/test/esp32eco3_efuses.bin new file mode 100644 index 0000000000000000000000000000000000000000..d60c6c019c6072262880c892eeb1d5cd228dd492 GIT binary patch literal 124 ScmZQzKmrXgwg8MlQyKt1TmX>( literal 0 HcmV?d00001