-
Notifications
You must be signed in to change notification settings - Fork 136
Improve ARMORED code + minor fixes #665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR enhances fault mitigation in ARMORED mode with improved redundancy checks, adds ARMORED support for ML_DSA signature verification, fixes rollback handling bugs, and reconfigures STM32 TrustZone SAU regions to set the UPDATE partition as secure.
Changes:
- Enhanced ARMORED mode with additional redundancy in signature verification and version checking
- Added redundant verification checks for ML_DSA signatures when ARMORED=1
- Fixed rollback logic to properly handle version checks and state transitions with ARMORED enabled
- Reconfigured STM32_TZ SAU to mark UPDATE partition as secure and adjusted flash region mappings
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/test.mk | Updated size limits for test targets to accommodate increased code size from ARMORED enhancements |
| src/update_flash.c | Added rollback detection logic, refactored version check to work with ARMORED, and improved rollback state handling |
| src/image.c | Added ARMORED redundancy checks to ML_DSA verification and updated signature verification macros |
| include/image.h | Refactored VERIFY_VERSION_ALLOWED macro for both GCC and IAR with improved redundancy and changed signed to unsigned comparisons |
| hal/stm32_tz.c | Reconfigured SAU regions to mark UPDATE partition as secure with dynamic flash_top_secure calculation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "b .\n" \ | ||
| "2:\n" \ | ||
| "pop {r4, r5, r6, r7}\n" \ | ||
| : /* No output operands */ \ |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The clobbered registers list for the IAR version is missing 'lr', 'cc', and 'memory' compared to the GCC version on line 620. Since this inline assembly calls functions with 'bl' instructions (which modifies 'lr') and performs comparisons (which modifies condition codes), these should be included in the clobber list to ensure the compiler preserves these registers correctly.
| "mov r0, %0\n" \ | ||
| "mov r4, %0\n" \ | ||
| "cmp r0, #1\n" \ | ||
| "bne do_check\n" \ | ||
| "cmp r4, #1\n" \ | ||
| "bne do_check\n" \ | ||
| "cmp r0, r4\n" \ | ||
| "bne do_check\n" \ | ||
| "cmp r0, #1\n" \ | ||
| "bne do_check\n" \ | ||
| "b end_check\n" \ |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IAR version includes additional validation checks (lines 641-651) that trigger breakpoints if fb_ok is neither 0 nor 1, while the GCC version (lines 546-556) does not have equivalent validation. This inconsistency means the two compiler paths have different security hardening levels. Consider adding similar validation to the GCC version for consistency.
| /* Non-secure flash alias (entire NS flash window) */ | ||
| sau_init_region(1, 0x08000000, FLASH_TOP, 0); | ||
|
|
||
| /* Secure: update partition in secure alias (use matching FLASH_TOP base) */ | ||
| uint32_t flash_top_secure = FLASH_TOP; | ||
| if ((WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) != | ||
| (FLASH_TOP & 0xFF000000u)) { | ||
| flash_top_secure = | ||
| (WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) | | ||
| (FLASH_TOP & 0x00FFFFFFu); | ||
| } | ||
| sau_init_region(2, WOLFBOOT_PARTITION_UPDATE_ADDRESS, flash_top_secure, 1); |
Copilot
AI
Jan 12, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SAU configuration has been significantly changed. Region 1 now covers the entire flash window (0x08000000 to FLASH_TOP) as non-secure, while Region 2 marks only the UPDATE partition as secure. This means the BOOT partition is now accessible as non-secure via Region 1. Verify this is the intended behavior and that the BOOT partition doesn't need secure access protection during runtime. The description states the UPDATE partition is only accessed via NSC, but this configuration change may have broader security implications.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| /* Secure: application flash area (second bank) */ | ||
| sau_init_region(2, WOLFBOOT_PARTITION_UPDATE_ADDRESS, FLASH_TOP, 0); | ||
| /* Non-secure flash alias (entire NS flash window) */ | ||
| sau_init_region(1, 0x08000000, FLASH_TOP, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: can you use a constant instead of 0x08000000?
| uint32_t flash_top_secure = FLASH_TOP; | ||
| if ((WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) != | ||
| (FLASH_TOP & 0xFF000000u)) { | ||
| flash_top_secure = | ||
| (WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) | | ||
| (FLASH_TOP & 0x00FFFFFFu); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I"m slightly confused here, if the FLASH_TOP is also the top of WOLFBOOT_PARTITION_UPDATE_ADDRESS then flash_top_secure stores the top bit only, otherwise it stores the full address. Is it on purpose?
| (WOLFBOOT_PARTITION_UPDATE_ADDRESS & 0xFF000000u) | | ||
| (FLASH_TOP & 0x00FFFFFFu); | ||
| } | ||
| sau_init_region(2, WOLFBOOT_PARTITION_UPDATE_ADDRESS, flash_top_secure, 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes the region NSC, not secure as mentioned by the comment on line 307
| "bhs ver_panic\n" \ | ||
| "b end_check\n" \ | ||
| "ver_panic:\n" \ | ||
| "b .\n" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need multiple b. here
| "bhs 3f\n" \ | ||
| "b 2f\n" \ | ||
| "3:\n" \ | ||
| "b .\n" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
| "beq 4f\n" \ | ||
| "bkpt 0xE1\n" \ | ||
| "4:\n" \ | ||
| "cmp r4, #0\n" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you think cmp cmp cmp cmp beq beq beq beq is a more robust pattern?
| #endif | ||
| int fallback_image = 0; | ||
| #ifndef DISABLE_BACKUP | ||
| int rollback = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: do you think it make sense to call it fallback or in_fallback to match fallback_allowed?
| { | ||
| uint32_t fb_ok = (fallback_allowed == 1); | ||
| VERIFY_VERSION_ALLOWED(fb_ok); | ||
| (void)fb_ok; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you elaborate the reason of the fb_ok aliasing here?
| if (updateRet != 0) { | ||
| hal_flash_unlock(); | ||
| #ifdef EXT_FLASH | ||
| ext_flash_unlock(); | ||
| #endif | ||
| wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_UPDATING); | ||
| #ifdef EXT_FLASH | ||
| ext_flash_lock(); | ||
| #endif | ||
| hal_flash_lock(); | ||
| updateRet = 0; | ||
| updateState = IMG_STATE_UPDATING; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the reason of this?
ARMORED=1
STM32_TZ SAU:
Fixes: