diff options
| author | Rasmus Melchior Jacobsen <[email protected]> | 2023-04-03 14:59:55 +0200 |
|---|---|---|
| committer | Rasmus Melchior Jacobsen <[email protected]> | 2023-04-03 14:59:55 +0200 |
| commit | 8aaffe82e71dfb2b3845c95bbf59ef4a34c7096c (patch) | |
| tree | 804cafc382c665cde9e9b67b323e0b0b91f8524b | |
| parent | 0909a6cd3ff6fb953aa2d83fb5da37384ad7dae2 (diff) | |
Add incremental hash to FirmwareUpdater
This adds support for computing any hash over the update in the dtu area by providing a closure to the hash update function.
| -rw-r--r-- | embassy-boot/boot/src/firmware_updater.rs | 67 | ||||
| -rw-r--r-- | embassy-boot/boot/src/lib.rs | 2 |
2 files changed, 43 insertions, 26 deletions
diff --git a/embassy-boot/boot/src/firmware_updater.rs b/embassy-boot/boot/src/firmware_updater.rs index af1ba114a..90157036a 100644 --- a/embassy-boot/boot/src/firmware_updater.rs +++ b/embassy-boot/boot/src/firmware_updater.rs | |||
| @@ -118,13 +118,13 @@ impl FirmwareUpdater { | |||
| 118 | _state_and_dfu_flash: &mut F, | 118 | _state_and_dfu_flash: &mut F, |
| 119 | _public_key: &[u8], | 119 | _public_key: &[u8], |
| 120 | _signature: &[u8], | 120 | _signature: &[u8], |
| 121 | _update_len: usize, | 121 | _update_len: u32, |
| 122 | _aligned: &mut [u8], | 122 | _aligned: &mut [u8], |
| 123 | ) -> Result<(), FirmwareUpdaterError> { | 123 | ) -> Result<(), FirmwareUpdaterError> { |
| 124 | let _read_size = _aligned.len(); | 124 | let _read_size = _aligned.len(); |
| 125 | 125 | ||
| 126 | assert_eq!(_aligned.len(), F::WRITE_SIZE); | 126 | assert_eq!(_aligned.len(), F::WRITE_SIZE); |
| 127 | assert!(_update_len <= self.dfu.len()); | 127 | assert!(_update_len <= self.dfu.len() as u32); |
| 128 | 128 | ||
| 129 | #[cfg(feature = "ed25519-dalek")] | 129 | #[cfg(feature = "ed25519-dalek")] |
| 130 | { | 130 | { |
| @@ -136,11 +136,8 @@ impl FirmwareUpdater { | |||
| 136 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; | 136 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; |
| 137 | 137 | ||
| 138 | let mut digest = Sha512::new(); | 138 | let mut digest = Sha512::new(); |
| 139 | for offset in (0.._update_len).step_by(_aligned.len()) { | 139 | self.incremental_hash(_state_and_dfu_flash, _update_len, _aligned, |x| digest.update(x)) |
| 140 | self.dfu.read(_state_and_dfu_flash, offset as u32, _aligned).await?; | 140 | .await?; |
| 141 | let len = core::cmp::min(_update_len - offset, _aligned.len()); | ||
| 142 | digest.update(&_aligned[..len]); | ||
| 143 | } | ||
| 144 | 141 | ||
| 145 | public_key | 142 | public_key |
| 146 | .verify(&digest.finalize(), &signature) | 143 | .verify(&digest.finalize(), &signature) |
| @@ -161,11 +158,8 @@ impl FirmwareUpdater { | |||
| 161 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; | 158 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; |
| 162 | 159 | ||
| 163 | let mut digest = Sha512::new(); | 160 | let mut digest = Sha512::new(); |
| 164 | for offset in (0.._update_len).step_by(_aligned.len()) { | 161 | self.incremental_hash(_state_and_dfu_flash, _update_len, _aligned, |x| digest.update(x)) |
| 165 | self.dfu.read(_state_and_dfu_flash, offset as u32, _aligned).await?; | 162 | .await?; |
| 166 | let len = core::cmp::min(_update_len - offset, _aligned.len()); | ||
| 167 | digest.update(&_aligned[..len]); | ||
| 168 | } | ||
| 169 | 163 | ||
| 170 | let message = digest.finalize(); | 164 | let message = digest.finalize(); |
| 171 | let r = public_key.verify(&message, &signature); | 165 | let r = public_key.verify(&message, &signature); |
| @@ -182,6 +176,22 @@ impl FirmwareUpdater { | |||
| 182 | self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await | 176 | self.set_magic(_aligned, SWAP_MAGIC, _state_and_dfu_flash).await |
| 183 | } | 177 | } |
| 184 | 178 | ||
| 179 | /// Iterate through the DFU and process all bytes with the provided closure. | ||
| 180 | pub async fn incremental_hash<F: AsyncNorFlash>( | ||
| 181 | &mut self, | ||
| 182 | dfu_flash: &mut F, | ||
| 183 | update_len: u32, | ||
| 184 | aligned: &mut [u8], | ||
| 185 | mut update: impl FnMut(&[u8]), | ||
| 186 | ) -> Result<(), FirmwareUpdaterError> { | ||
| 187 | for offset in (0..update_len).step_by(aligned.len()) { | ||
| 188 | self.dfu.read(dfu_flash, offset, aligned).await?; | ||
| 189 | let len = core::cmp::min((update_len - offset) as usize, aligned.len()); | ||
| 190 | update(&aligned[..len]); | ||
| 191 | } | ||
| 192 | Ok(()) | ||
| 193 | } | ||
| 194 | |||
| 185 | /// Mark to trigger firmware swap on next boot. | 195 | /// Mark to trigger firmware swap on next boot. |
| 186 | /// | 196 | /// |
| 187 | /// # Safety | 197 | /// # Safety |
| @@ -317,14 +327,13 @@ impl FirmwareUpdater { | |||
| 317 | _state_and_dfu_flash: &mut F, | 327 | _state_and_dfu_flash: &mut F, |
| 318 | _public_key: &[u8], | 328 | _public_key: &[u8], |
| 319 | _signature: &[u8], | 329 | _signature: &[u8], |
| 320 | _update_len: usize, | 330 | _update_len: u32, |
| 321 | _aligned: &mut [u8], | 331 | _aligned: &mut [u8], |
| 322 | ) -> Result<(), FirmwareUpdaterError> { | 332 | ) -> Result<(), FirmwareUpdaterError> { |
| 323 | let _end = self.dfu.from + _update_len; | ||
| 324 | let _read_size = _aligned.len(); | 333 | let _read_size = _aligned.len(); |
| 325 | 334 | ||
| 326 | assert_eq!(_aligned.len(), F::WRITE_SIZE); | 335 | assert_eq!(_aligned.len(), F::WRITE_SIZE); |
| 327 | assert!(_end <= self.dfu.to); | 336 | assert!(_update_len <= self.dfu.len() as u32); |
| 328 | 337 | ||
| 329 | #[cfg(feature = "ed25519-dalek")] | 338 | #[cfg(feature = "ed25519-dalek")] |
| 330 | { | 339 | { |
| @@ -336,11 +345,7 @@ impl FirmwareUpdater { | |||
| 336 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; | 345 | let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; |
| 337 | 346 | ||
| 338 | let mut digest = Sha512::new(); | 347 | let mut digest = Sha512::new(); |
| 339 | for offset in (0.._update_len).step_by(_aligned.len()) { | 348 | self.incremental_hash_blocking(_state_and_dfu_flash, _update_len, _aligned, |x| digest.update(x))?; |
| 340 | self.dfu.read_blocking(_state_and_dfu_flash, offset as u32, _aligned)?; | ||
| 341 | let len = core::cmp::min(_update_len - offset, _aligned.len()); | ||
| 342 | digest.update(&_aligned[..len]); | ||
| 343 | } | ||
| 344 | 349 | ||
| 345 | public_key | 350 | public_key |
| 346 | .verify(&digest.finalize(), &signature) | 351 | .verify(&digest.finalize(), &signature) |
| @@ -361,11 +366,7 @@ impl FirmwareUpdater { | |||
| 361 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; | 366 | let signature = Signature::try_from(&signature).map_err(into_signature_error)?; |
| 362 | 367 | ||
| 363 | let mut digest = Sha512::new(); | 368 | let mut digest = Sha512::new(); |
| 364 | for offset in (0.._update_len).step_by(_aligned.len()) { | 369 | self.incremental_hash_blocking(_state_and_dfu_flash, _update_len, _aligned, |x| digest.update(x))?; |
| 365 | self.dfu.read_blocking(_state_and_dfu_flash, offset as u32, _aligned)?; | ||
| 366 | let len = core::cmp::min(_update_len - offset, _aligned.len()); | ||
| 367 | digest.update(&_aligned[..len]); | ||
| 368 | } | ||
| 369 | 370 | ||
| 370 | let message = digest.finalize(); | 371 | let message = digest.finalize(); |
| 371 | let r = public_key.verify(&message, &signature); | 372 | let r = public_key.verify(&message, &signature); |
| @@ -382,6 +383,22 @@ impl FirmwareUpdater { | |||
| 382 | self.set_magic_blocking(_aligned, SWAP_MAGIC, _state_and_dfu_flash) | 383 | self.set_magic_blocking(_aligned, SWAP_MAGIC, _state_and_dfu_flash) |
| 383 | } | 384 | } |
| 384 | 385 | ||
| 386 | /// Iterate through the DFU and process all bytes with the provided closure. | ||
| 387 | pub fn incremental_hash_blocking<F: NorFlash>( | ||
| 388 | &mut self, | ||
| 389 | dfu_flash: &mut F, | ||
| 390 | update_len: u32, | ||
| 391 | aligned: &mut [u8], | ||
| 392 | mut update: impl FnMut(&[u8]), | ||
| 393 | ) -> Result<(), FirmwareUpdaterError> { | ||
| 394 | for offset in (0..update_len).step_by(aligned.len()) { | ||
| 395 | self.dfu.read_blocking(dfu_flash, offset, aligned)?; | ||
| 396 | let len = core::cmp::min((update_len - offset) as usize, aligned.len()); | ||
| 397 | update(&aligned[..len]); | ||
| 398 | } | ||
| 399 | Ok(()) | ||
| 400 | } | ||
| 401 | |||
| 385 | /// Mark to trigger firmware swap on next boot. | 402 | /// Mark to trigger firmware swap on next boot. |
| 386 | /// | 403 | /// |
| 387 | /// # Safety | 404 | /// # Safety |
diff --git a/embassy-boot/boot/src/lib.rs b/embassy-boot/boot/src/lib.rs index 4c28d7aa4..6d0e2d8c2 100644 --- a/embassy-boot/boot/src/lib.rs +++ b/embassy-boot/boot/src/lib.rs | |||
| @@ -308,7 +308,7 @@ mod tests { | |||
| 308 | &mut flash, | 308 | &mut flash, |
| 309 | &public_key.to_bytes(), | 309 | &public_key.to_bytes(), |
| 310 | &signature.to_bytes(), | 310 | &signature.to_bytes(), |
| 311 | firmware_len, | 311 | firmware_len as u32, |
| 312 | &mut aligned, | 312 | &mut aligned, |
| 313 | )) | 313 | )) |
| 314 | .is_ok()); | 314 | .is_ok()); |
