Merge branch 'fix/anti-rollback-update' into 'master'

fix(efuse): Reliably update anti-rollback secure version

Closes IDF-16141

See merge request espressif/esp-idf!52406
This commit is contained in:
Mahavir Jain
2026-09-04 18:09:02 +05:30
2 changed files with 26 additions and 5 deletions

View File

@@ -81,11 +81,11 @@ esp_err_t esp_efuse_update_secure_version(uint32_t secure_version)
uint32_t sec_ver_hw = esp_efuse_read_secure_version();
// If secure_version is the same as in eFuse field than it is ok just go out.
if (sec_ver_hw < secure_version) {
uint32_t num_bit_hw = (1ULL << sec_ver_hw) - 1;
uint32_t num_bit_app = (1ULL << secure_version) - 1;
// Repeated programming of programmed bits is strictly forbidden
uint32_t new_bits = num_bit_app - num_bit_hw; // get only new bits
esp_efuse_write_field_blob(ESP_EFUSE_SECURE_VERSION, &new_bits, size);
esp_err_t err = esp_efuse_write_field_cnt(ESP_EFUSE_SECURE_VERSION, secure_version - sec_ver_hw);
if (err != ESP_OK || esp_efuse_read_secure_version() < secure_version) {
ESP_LOGE(TAG, "Failed to update secure version in eFuse");
return ESP_FAIL;
}
ESP_LOGI(TAG, "Anti-rollback is set. eFuse field is updated(%"PRIu32").", secure_version);
} else if (sec_ver_hw > secure_version) {
ESP_LOGE(TAG, "Anti-rollback is not set. secure_version of app is lower that eFuse field(%"PRIu32").", sec_ver_hw);

View File

@@ -282,6 +282,27 @@ TEST_CASE("efuse test write_field_cnt", "[efuse]")
test_write_cnt();
}
TEST_CASE("secure version update handles sparse efuse field", "[efuse]")
{
const uint32_t sparse_secure_version = 1U << 2;
const uint32_t expected_secure_version = 3;
size_t field_size = esp_efuse_get_field_size(ESP_EFUSE_SECURE_VERSION);
// Preload a non-sequential state that may remain after an earlier incomplete update:
// initial: bitmap 0b100, secure version 1;
esp_efuse_utility_erase_virt_blocks();
TEST_ESP_OK(esp_efuse_write_field_blob(ESP_EFUSE_SECURE_VERSION, &sparse_secure_version, field_size));
TEST_ASSERT_EQUAL_UINT32(1, esp_efuse_read_secure_version());
// update to 3: bitmap 0b111, secure version 3;
TEST_ESP_OK(esp_efuse_update_secure_version(expected_secure_version));
TEST_ASSERT_EQUAL_UINT32(expected_secure_version, esp_efuse_read_secure_version());
// repeated update: bitmap 0b111, secure version 3 (no change).
TEST_ESP_OK(esp_efuse_update_secure_version(expected_secure_version));
TEST_ASSERT_EQUAL_UINT32(expected_secure_version, esp_efuse_read_secure_version());
}
TEST_CASE("efuse test single bit functions", "[efuse]")
{
esp_efuse_utility_erase_virt_blocks();