Update OTA example to demonstate anti_rollback feature

Add example_test for anti_rollback feature
This commit is contained in:
Shubham Kulkarni 2020-10-23 21:52:51 +05:30 committed by bot
parent e2716690bc
commit cda61a87da
5 changed files with 137 additions and 0 deletions

View File

@ -0,0 +1,8 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
nvs, data, nvs, , 0x4000,
otadata, data, ota, , 0x2000,
phy_init, data, phy, , 0x1000,
ota_0, app, ota_0, , 3584K,
ota_1, app, ota_1, , 3584K,
emul_efuse, data, 5, , 0x2000
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
3 nvs, data, nvs, , 0x4000,
4 otadata, data, ota, , 0x2000,
5 phy_init, data, phy, , 0x1000,
6 ota_0, app, ota_0, , 3584K,
7 ota_1, app, ota_1, , 3584K,
8 emul_efuse, data, 5, , 0x2000

View File

@ -453,6 +453,70 @@ def test_examples_protocol_advanced_https_ota_example_redirect_url(env, extra_da
dut1.reset()
@ttfw_idf.idf_example_test(env_tag="Example_8Mflash_Ethernet")
def test_examples_protocol_advanced_https_ota_example_anti_rollback(env, extra_data):
"""
Working of OTA when anti_rollback is enabled and security version of new image is less than current one.
Application should return with error message in this case.
steps: |
1. join AP
2. Generate binary file with lower security version
3. Fetch OTA image over HTTPS
4. Check working of anti_rollback feature
"""
dut1 = env.get_dut("advanced_https_ota_example", "examples/system/ota/advanced_https_ota", dut_class=ttfw_idf.ESP32DUT, app_config_name='anti_rollback')
server_port = 8001
# Original binary file generated after compilation
bin_name = "advanced_https_ota.bin"
# Modified firmware image to lower security version in its header. This is to enable negative test case
anti_rollback_bin_name = "advanced_https_ota_lower_sec_version.bin"
# check and log bin size
binary_file = os.path.join(dut1.app.binary_path, bin_name)
file_size = os.path.getsize(binary_file)
f = open(binary_file, "rb+")
fo = open(os.path.join(dut1.app.binary_path, anti_rollback_bin_name), "wb+")
fo.write(f.read(file_size))
# Change security_version to 0 for negative test case
fo.seek(36)
fo.write(b'\x00')
fo.close()
f.close()
binary_file = os.path.join(dut1.app.binary_path, anti_rollback_bin_name)
bin_size = os.path.getsize(binary_file)
ttfw_idf.log_performance("advanced_https_ota_bin_size", "{}KB".format(bin_size // 1024))
ttfw_idf.check_performance("advanced_https_ota_bin_size", bin_size // 1024, dut1.TARGET)
# start test
host_ip = get_my_ip()
if (get_server_status(host_ip, server_port) is False):
thread1 = Thread(target=start_https_server, args=(dut1.app.binary_path, host_ip, server_port))
thread1.daemon = True
thread1.start()
dut1.start_app()
# Positive Case
dut1.expect("Loaded app from partition at offset", timeout=30)
try:
ip_address = dut1.expect(re.compile(r" eth ip: ([^,]+),"), timeout=30)
print("Connected to AP with IP: {}".format(ip_address))
except DUT.ExpectTimeout:
raise ValueError('ENV_TEST_FAILURE: Cannot connect to AP')
dut1.expect("Starting Advanced OTA example", timeout=30)
# Use originally generated image with secure_version=1
print("writing to device: {}".format("https://" + host_ip + ":" + str(server_port) + "/" + bin_name))
dut1.write("https://" + host_ip + ":" + str(server_port) + "/" + bin_name)
dut1.expect("Loaded app from partition at offset", timeout=60)
dut1.expect(re.compile(r" eth ip: ([^,]+),"), timeout=30)
dut1.expect("App is valid, rollback cancelled successfully", 30)
# Negative Case
dut1.expect("Starting Advanced OTA example", timeout=30)
# Use modified image with secure_version=0
print("writing to device: {}".format("https://" + host_ip + ":" + str(server_port) + "/" + anti_rollback_bin_name))
dut1.write("https://" + host_ip + ":" + str(server_port) + "/" + anti_rollback_bin_name)
dut1.expect("New firmware security version is less than eFuse programmed, 0 < 1", timeout=30)
os.remove(anti_rollback_bin_name)
if __name__ == '__main__':
test_examples_protocol_advanced_https_ota_example()
test_examples_protocol_advanced_https_ota_example_chunked()
@ -460,3 +524,4 @@ if __name__ == '__main__':
test_examples_protocol_advanced_https_ota_example_truncated_bin()
test_examples_protocol_advanced_https_ota_example_truncated_header()
test_examples_protocol_advanced_https_ota_example_random()
test_examples_protocol_advanced_https_ota_example_anti_rollback()

View File

@ -20,6 +20,10 @@
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#if CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
#include "esp_efuse.h"
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI
#include "esp_wifi.h"
#endif
@ -49,6 +53,19 @@ static esp_err_t validate_image_header(esp_app_desc_t *new_app_info)
}
#endif
#ifdef CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK
/**
* Secure version check from firmware image header prevents subsequent download and flash write of
* entire firmware image. However this is optional because it is also taken care in API
* esp_https_ota_finish at the end of OTA update procedure.
*/
const uint32_t hw_sec_version = esp_efuse_read_secure_version();
if (new_app_info->secure_version < hw_sec_version) {
ESP_LOGW(TAG, "New firmware security version is less than eFuse programmed, %d < %d", new_app_info->secure_version, hw_sec_version);
return ESP_FAIL;
}
#endif
return ESP_OK;
}
@ -167,6 +184,25 @@ void app_main(void)
*/
ESP_ERROR_CHECK(example_connect());
#if defined(CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE) && defined(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK)
/**
* We are treating successful WiFi connection as a checkpoint to cancel rollback
* process and mark newly updated firmware image as active. For production cases,
* please tune the checkpoint behavior per end application requirement.
*/
const esp_partition_t *running = esp_ota_get_running_partition();
esp_ota_img_states_t ota_state;
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
if (esp_ota_mark_app_valid_cancel_rollback() == ESP_OK) {
ESP_LOGI(TAG, "App is valid, rollback cancelled successfully");
} else {
ESP_LOGE(TAG, "Failed to cancel rollback");
}
}
}
#endif
#if CONFIG_EXAMPLE_CONNECT_WIFI
/* Ensure to disable any WiFi power save mode, this allows best throughput
* and hence timings for overall OTA operation.

View File

@ -0,0 +1,22 @@
CONFIG_EXAMPLE_FIRMWARE_UPGRADE_URL="FROM_STDIN"
CONFIG_EXAMPLE_SKIP_COMMON_NAME_CHECK=y
CONFIG_EXAMPLE_SKIP_VERSION_CHECK=y
CONFIG_EXAMPLE_OTA_RECV_TIMEOUT=3000
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="anti_rollback_partition.csv"
CONFIG_PARTITION_TABLE_FILENAME="anti_rollback_partition.csv"
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK=y
CONFIG_BOOTLOADER_APP_SECURE_VERSION=1
CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE=y
CONFIG_EXAMPLE_CONNECT_ETHERNET=y
CONFIG_EXAMPLE_CONNECT_WIFI=n
CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y
CONFIG_EXAMPLE_ETH_PHY_IP101=y
CONFIG_EXAMPLE_ETH_MDC_GPIO=23
CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
CONFIG_EXAMPLE_CONNECT_IPV6=y

View File

@ -163,6 +163,12 @@ example_test_001C:
- ESP32
- Example_GENERIC
example_test_001D:
extends: .example_test_template
tags:
- ESP32
- Example_8Mflash_Ethernet
example_test_002:
extends: .example_test_template
image: $CI_DOCKER_REGISTRY/ubuntu-test-env$BOT_DOCKER_IMAGE_TAG