-
Notifications
You must be signed in to change notification settings - Fork 147
Description
When generating a project with secure boot v2, the bootloader is padded: https://docs.espressif.com/projects/esp-idf/en/v5.3.2/esp32c3/security/secure-boot-v2.html#secure-padding
Using a padded image with espflash save-image --bootloader path-to-bootloader ... will read the file into a buffer:
flasher/mod.rs:
impl FlashData {
pub fn new(...) -> Result<Self, Error> {
// If the '--bootloader' option is provided, load the binary file at the
// specified path.
let bootloader = if let Some(path) = bootloader {
let data = fs::canonicalize(path)
.and_then(fs::read)
.map_err(|e| Error::FileOpenError(path.display().to_string(), e))?;
Some(data)
} else {
None
};
Then that bootloader buffer gets passed to image_format.rs IdfBootloaderFormat. From there, the header is updated to match the args so the sha256 needs updating. However, the location of the sha256 is naively calculated as being the last 32 bytes of the bootloader file. However, it's actually the last 32 bytes of the bootloader without padding.
image_format.rs:
// re-calculate hash of the bootloader - needed since we modified the header
let bootloader_len = bootloader.len(); // <- size of the file including padding
let mut hasher = Sha256::new();
hasher.update(&bootloader[..bootloader_len - 32]); // <-- wrong location of sha256
let hash = hasher.finalize();
bootloader.to_mut()[bootloader_len - 32..].copy_from_slice(&hash);
One approach, which I'm not sure is the correct one due to all the different environments but worked in my specific case, was to walk through the bootloader segments while adding up the length. Then adding width the 16-byte aligned 1-byte checksum at the end. Maybe a better approach can be derived by referencing esptool/bin_image.py directly.
The image has a single checksum byte after the last segment. This byte is written on a sixteen byte padded boundary, so the application image might need padding.
Without this, secure-boot-enabled ESPs will not boot because the first-stage bootloader will detect the mismatch between the actual and old unchanged SHA256.
This appears to be related but not the same as #713
Metadata
Metadata
Assignees
Labels
Type
Projects
Status