Infineon: Switch to 1.9.0 code base, add xmc7000 family support, refactor memory layer
diff --git a/sim/src/caps.rs b/sim/src/caps.rs
index 3fbf4c3..5b1b8e5 100644
--- a/sim/src/caps.rs
+++ b/sim/src/caps.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2019 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
// Copyright (c) 2019 JUUL Labs
// Copyright (c) 2019-2021 Arm Limited
//
@@ -37,6 +37,11 @@
(caps as u32) & (self as u32) != 0
}
+ /// Does this build have ECDSA of some type enabled for signatures.
+ pub fn has_ecdsa() -> bool {
+ Caps::EcdsaP256.present() || Caps::EcdsaP224.present()
+ }
+
/// Query for the number of images that have been configured into this
/// MCUboot build.
pub fn get_num_images() -> usize {
diff --git a/sim/src/depends.rs b/sim/src/depends.rs
index a67bcd8..229b3e2 100644
--- a/sim/src/depends.rs
+++ b/sim/src/depends.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 Linaro LTD
+// Copyright (c) 2019-2021 Linaro LTD
//
// SPDX-License-Identifier: Apache-2.0
diff --git a/sim/src/image.rs b/sim/src/image.rs
index 29ddedd..dbfb5fe 100644
--- a/sim/src/image.rs
+++ b/sim/src/image.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 Linaro LTD
+// Copyright (c) 2019-2021 Linaro LTD
// Copyright (c) 2019-2020 JUUL Labs
// Copyright (c) 2019-2021 Arm Limited
//
@@ -54,6 +54,7 @@
UpgradeInfo,
};
use crate::tlv::{ManifestGen, TlvGen, TlvFlags};
+use crate::utils::align_up;
use typenum::{U32, U16};
/// For testing, use a non-zero offset for the ram-load, to make sure the offset is getting used
@@ -219,10 +220,12 @@
} else {
Box::new(BoringDep::new(image_num, deps))
};
- let primaries = install_image(&mut flash, &slots[0], 42784, &ram, &*dep, false);
+ let primaries = install_image(&mut flash, &slots[0],
+ 42784, &ram, &*dep, false);
let upgrades = match deps.depends[image_num] {
DepType::NoUpgrade => install_no_image(),
- _ => install_image(&mut flash, &slots[1], 46928, &ram, &*dep, false)
+ _ => install_image(&mut flash, &slots[1],
+ 46928, &ram, &*dep, false)
};
OneImage {
slots,
@@ -270,8 +273,10 @@
let ram = self.ram.clone(); // TODO: Avoid this clone.
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
- let primaries = install_image(&mut bad_flash, &slots[0], 32784, &ram, &dep, false);
- let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &ram, &dep, true);
+ let primaries = install_image(&mut bad_flash, &slots[0],
+ 32784, &ram, &dep, false);
+ let upgrades = install_image(&mut bad_flash, &slots[1],
+ 41928, &ram, &dep, true);
OneImage {
slots,
primaries,
@@ -291,7 +296,8 @@
let ram = self.ram.clone(); // TODO: Avoid this clone.
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
- let primaries = install_image(&mut flash, &slots[0], 32784, &ram, &dep, false);
+ let primaries = install_image(&mut flash, &slots[0],
+ 32784, &ram, &dep, false);
let upgrades = install_no_image();
OneImage {
slots,
@@ -313,7 +319,8 @@
let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
let dep = BoringDep::new(image_num, &NO_DEPS);
let primaries = install_no_image();
- let upgrades = install_image(&mut flash, &slots[1], 32784, &ram, &dep, false);
+ let upgrades = install_image(&mut flash, &slots[1],
+ 32784, &ram, &dep, false);
OneImage {
slots,
primaries,
@@ -333,9 +340,13 @@
match device {
DeviceName::Stm32f4 => {
// STM style flash. Large sectors, with a large scratch area.
- let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
- 64 * 1024,
- 128 * 1024, 128 * 1024, 128 * 1024],
+ // The flash layout as described is not present in any real STM32F4 device, but it
+ // serves to exercise support for sectors of varying sizes inside a single slot,
+ // as long as they are compatible in both slots and all fit in the scratch.
+ let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024, 64 * 1024,
+ 32 * 1024, 32 * 1024, 64 * 1024,
+ 32 * 1024, 32 * 1024, 64 * 1024,
+ 128 * 1024],
align as usize, erased_val);
let dev_id = 0;
let mut areadesc = AreaDesc::new();
@@ -493,7 +504,7 @@
if Caps::Bootstrap.present() {
info!("Try bootstraping image in the primary");
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -674,7 +685,7 @@
info!("Try norevert");
// First do a normal upgrade...
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -707,7 +718,7 @@
fails += 1;
}
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed second boot");
fails += 1;
}
@@ -742,7 +753,7 @@
info!("Try no downgrade");
// First, do a normal upgrade.
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -784,7 +795,7 @@
}
// Run the bootloader...
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -838,7 +849,7 @@
}
// Run the bootloader...
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -878,7 +889,7 @@
self.mark_upgrades(&mut flash, 1);
// Run the bootloader...
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed first boot");
fails += 1;
}
@@ -925,7 +936,7 @@
self.mark_permanent_upgrades(&mut flash, 1);
self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
- let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+ let result = c::boot_go(&mut flash, &self.areadesc, None, None, true);
if !result.success() {
warn!("Failed!");
fails += 1;
@@ -951,7 +962,7 @@
info!("validate primary slot enabled; \
re-run of boot_go should just work");
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Failed!");
fails += 1;
}
@@ -983,7 +994,8 @@
self.mark_bad_status_with_rate(&mut flash, 0, 0.5);
// Should not fail, writing to bad regions does not assert
- let asserts = c::boot_go(&mut flash, &self.areadesc, Some(&mut count), true).asserts();
+ let asserts = c::boot_go(&mut flash, &self.areadesc,
+ Some(&mut count), None, true).asserts();
if asserts != 0 {
warn!("At least one assert() was called");
fails += 1;
@@ -992,7 +1004,8 @@
self.reset_bad_status(&mut flash, 0);
info!("Resuming an interrupted swap operation");
- let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
+ let asserts = c::boot_go(&mut flash, &self.areadesc, None, None,
+ true).asserts();
// This might throw no asserts, for large sector devices, where
// a single failure writing is indistinguishable from no failure,
@@ -1019,7 +1032,8 @@
self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
// This is expected to fail while writing to bad regions...
- let asserts = c::boot_go(&mut flash, &self.areadesc, None, true).asserts();
+ let asserts = c::boot_go(&mut flash, &self.areadesc, None, None,
+ true).asserts();
if asserts == 0 {
warn!("No assert() detected");
fails += 1;
@@ -1039,7 +1053,7 @@
// Clone the flash so we can tell if unchanged.
let mut flash = self.flash.clone();
- let result = c::boot_go(&mut flash, &self.areadesc, None, true);
+ let result = c::boot_go(&mut flash, &self.areadesc, None, None, true);
// Ensure the boot was successful.
let resp = if let Some(resp) = result.resp() {
@@ -1073,7 +1087,8 @@
// println!("Ram: {:#?}", self.ram);
// Verify that the images area loaded into this.
- let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None, true));
+ let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc, None,
+ None, true));
if !result.success() {
error!("Failed to execute ram-load");
return true;
@@ -1101,6 +1116,50 @@
return false;
}
+ /// Test the split ram-loading.
+ pub fn run_split_ram_load(&self) -> bool {
+ if !Caps::RamLoad.present() {
+ return false;
+ }
+
+ // Clone the flash so we can tell if unchanged.
+ let mut flash = self.flash.clone();
+
+ // Setup ram based on the ram configuration we determined earlier for the images.
+ let ram = RamBlock::new(self.ram.total - RAM_LOAD_ADDR, RAM_LOAD_ADDR);
+
+ for (idx, _image) in (&self.images).iter().enumerate() {
+ // Verify that the images area loaded into this.
+ let result = ram.invoke(|| c::boot_go(&mut flash, &self.areadesc,
+ None, Some(idx as i32), true));
+ if !result.success() {
+ error!("Failed to execute ram-load");
+ return true;
+ }
+ }
+
+ // Verify each image.
+ for image in &self.images {
+ let place = self.ram.lookup(&image.slots[0]);
+ let ram_image = ram.borrow_part(place.offset as usize - RAM_LOAD_ADDR as usize,
+ place.size as usize);
+ let src_sz = image.upgrades.size();
+ if src_sz > ram_image.len() {
+ error!("Image ended up too large, nonsensical");
+ return true;
+ }
+ let src_image = &image.upgrades.plain[0..src_sz];
+ let ram_image = &ram_image[0..src_sz];
+ if ram_image != src_image {
+ error!("Image not loaded correctly");
+ return true;
+ }
+
+ }
+
+ return false;
+ }
+
/// Adds a new flash area that fails statistically
fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
rate: f32) {
@@ -1150,7 +1209,10 @@
let mut counter = stop.unwrap_or(0);
- let (first_interrupted, count) = match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
+ let (first_interrupted, count) = match c::boot_go(&mut flash,
+ &self.areadesc,
+ Some(&mut counter),
+ None, false) {
x if x.interrupted() => (true, stop.unwrap()),
x if x.success() => (false, -counter),
x => panic!("Unknown return: {:?}", x),
@@ -1159,7 +1221,8 @@
counter = 0;
if first_interrupted {
// fl.dump();
- match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
+ match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter),
+ None, false) {
x if x.interrupted() => panic!("Shouldn't stop again"),
x if x.success() => (),
x => panic!("Unknown return: {:?}", x),
@@ -1175,7 +1238,7 @@
// fl.write_file("image0.bin").unwrap();
for i in 0 .. count {
info!("Running boot pass {}", i + 1);
- assert!(c::boot_go(&mut flash, &self.areadesc, None, false).success_no_asserts());
+ assert!(c::boot_go(&mut flash, &self.areadesc, None, None, false).success_no_asserts());
}
flash
}
@@ -1185,7 +1248,8 @@
let mut fails = 0;
let mut counter = stop;
- if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
+ if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), None,
+ false).interrupted() {
warn!("Should have stopped test at interruption point");
fails += 1;
}
@@ -1197,7 +1261,7 @@
fails += 1;
}
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Should have finished test upgrade");
fails += 1;
}
@@ -1225,12 +1289,13 @@
// Do Revert
let mut counter = stop;
- if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false).interrupted() {
+ if !c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), None,
+ false).interrupted() {
warn!("Should have stopped revert at interruption point");
fails += 1;
}
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Should have finished revert upgrade");
fails += 1;
}
@@ -1257,7 +1322,7 @@
fails += 1;
}
- if !c::boot_go(&mut flash, &self.areadesc, None, false).success() {
+ if !c::boot_go(&mut flash, &self.areadesc, None, None, false).success() {
warn!("Should have finished 3rd boot");
fails += 1;
}
@@ -1286,7 +1351,8 @@
for reset in &mut resets {
let reset_counter = rng.gen_range(1 ..= remaining_ops / 2);
let mut counter = reset_counter;
- match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
+ match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter),
+ None, false) {
x if x.interrupted() => (),
x => panic!("Unknown return: {:?}", x),
}
@@ -1294,7 +1360,7 @@
*reset = reset_counter;
}
- match c::boot_go(&mut flash, &self.areadesc, None, false) {
+ match c::boot_go(&mut flash, &self.areadesc, None, None, false) {
x if x.interrupted() => panic!("Should not be have been interrupted!"),
x if x.success() => (),
x => panic!("Unknown return: {:?}", x),
@@ -1613,14 +1679,13 @@
}
}
+/// Construct a TLV generator based on how MCUboot is currently configured. The returned
+/// ManifestGen will generate the appropriate entries based on this configuration.
fn make_tlv() -> TlvGen {
if Caps::EcdsaP224.present() {
panic!("Ecdsa P224 not supported in Simulator");
}
- let mut aes_key_size = 128;
- if Caps::Aes256.present() {
- aes_key_size = 256;
- }
+ let aes_key_size = if Caps::Aes256.present() { 256 } else { 128 };
if Caps::EncKw.present() {
if Caps::RSA2048.present() {
@@ -1726,12 +1791,13 @@
failed |= match magic {
Some(v) => {
- if v == 1 && ©[24..] != MAGIC {
+ let magic_off = (c::boot_max_align() * 3) + (c::boot_magic_sz() - MAGIC.len());
+ if v == 1 && ©[magic_off..] != MAGIC {
warn!("\"magic\" mismatch at {:#x}", offset);
true
} else if v == 3 {
let expected = [erased_val; 16];
- if copy[24..] != expected {
+ if copy[magic_off..] != expected {
warn!("\"magic\" mismatch at {:#x}", offset);
true
} else {
@@ -1746,8 +1812,9 @@
failed |= match image_ok {
Some(v) => {
- if (v == 1 && copy[16] != v) || (v == 3 && copy[16] != erased_val) {
- warn!("\"image_ok\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[8]);
+ let image_ok_off = c::boot_max_align() * 2;
+ if (v == 1 && copy[image_ok_off] != v) || (v == 3 && copy[image_ok_off] != erased_val) {
+ warn!("\"image_ok\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[image_ok_off]);
true
} else {
false
@@ -1758,8 +1825,9 @@
failed |= match copy_done {
Some(v) => {
- if (v == 1 && copy[8] != v) || (v == 3 && copy[8] != erased_val) {
- warn!("\"copy_done\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[0]);
+ let copy_done_off = c::boot_max_align();
+ if (v == 1 && copy[copy_done_off] != v) || (v == 3 && copy[copy_done_off] != erased_val) {
+ warn!("\"copy_done\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[copy_done_off]);
true
} else {
false
@@ -1860,11 +1928,18 @@
pub dev_id: u8,
}
+#[cfg(not(feature = "max-align-32"))]
const MAGIC: &[u8] = &[0x77, 0xc2, 0x95, 0xf3,
0x60, 0xd2, 0xef, 0x7f,
0x35, 0x52, 0x50, 0x0f,
0x2c, 0xb6, 0x79, 0x80];
+#[cfg(feature = "max-align-32")]
+const MAGIC: &[u8] = &[0x20, 0x00, 0x2d, 0xe1,
+ 0x5d, 0x29, 0x41, 0x0b,
+ 0x8d, 0x77, 0x67, 0x9c,
+ 0x11, 0x0f, 0x1f, 0x8a];
+
// Replicates defines found in bootutil.h
const BOOT_MAGIC_GOOD: Option<u8> = Some(1);
const BOOT_MAGIC_UNSET: Option<u8> = Some(3);
@@ -1882,8 +1957,9 @@
// The write size is larger than the magic value. Fill a buffer
// with the erased value, put the MAGIC in it, and write it in its
// entirety.
- let mut buf = vec![dev.erased_val(); align];
- buf[(offset % align)..].copy_from_slice(MAGIC);
+ let mut buf = vec![dev.erased_val(); c::boot_max_align()];
+ let magic_off = (offset % align) + (c::boot_magic_sz() - MAGIC.len());
+ buf[magic_off..].copy_from_slice(MAGIC);
dev.write(offset - (offset % align), &buf).unwrap();
} else {
dev.write(offset, MAGIC).unwrap();
@@ -1917,11 +1993,11 @@
}
let dev = flash.get_mut(&slot.dev_id).unwrap();
- let mut ok = [dev.erased_val(); 8];
+ let align = dev.align();
+ let mut ok = vec![dev.erased_val(); align];
ok[0] = 1u8;
let off = slot.trailer_off + c::boot_max_align() * 3;
- let align = dev.align();
- dev.write(off, &ok[..align]).unwrap();
+ dev.write(off, &ok).unwrap();
}
/// Writes the image_ok flag which, guess what, tells the bootloader
@@ -1975,16 +2051,16 @@
}
}
-#[cfg(not(feature = "large-write"))]
#[cfg(not(feature = "swap-status"))]
+#[cfg(not(feature = "max-align-32"))]
fn test_alignments() -> &'static [usize] {
&[1, 2, 4, 8]
}
-#[cfg(feature = "large-write")]
#[cfg(not(feature = "swap-status"))]
+#[cfg(feature = "max-align-32")]
fn test_alignments() -> &'static [usize] {
- &[1, 2, 4, 8, 128, 512]
+ &[32]
}
#[cfg(feature = "swap-status")]
diff --git a/sim/src/lib.rs b/sim/src/lib.rs
index 69f13f1..eec7547 100644
--- a/sim/src/lib.rs
+++ b/sim/src/lib.rs
@@ -16,6 +16,7 @@
mod depends;
mod image;
mod tlv;
+mod utils;
pub mod testlog;
pub use crate::{
@@ -52,8 +53,6 @@
#[derive(Debug, Deserialize)]
struct Args {
- flag_help: bool,
- flag_version: bool,
flag_device: Option<DeviceName>,
flag_align: Option<AlignArg>,
cmd_sizes: bool,
diff --git a/sim/src/tlv.rs b/sim/src/tlv.rs
index 6680b4f..61d56a2 100644
--- a/sim/src/tlv.rs
+++ b/sim/src/tlv.rs
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2020 Linaro LTD
+// Copyright (c) 2017-2021 Linaro LTD
// Copyright (c) 2017-2020 JUUL Labs
// Copyright (c) 2021 Arm Limited
//
@@ -67,8 +67,8 @@
PIC = 0x01,
NON_BOOTABLE = 0x02,
ENCRYPTED_AES128 = 0x04,
- RAM_LOAD = 0x20,
ENCRYPTED_AES256 = 0x08,
+ RAM_LOAD = 0x20,
}
/// A generator for manifests. The format of the manifest can be either a
@@ -96,6 +96,11 @@
/// corrupt the signature.
fn corrupt_sig(&mut self);
+ /// Estimate the size of the TLV. This can be called before the payload is added (but after
+ /// other information is added). Some of the signature algorithms can generate variable sized
+ /// data, and therefore, this can slightly overestimate the size.
+ fn estimate_size(&self) -> usize;
+
/// Construct the manifest for this payload.
fn make_tlv(self: Box<Self>) -> Vec<u8>;
@@ -332,8 +337,67 @@
self.gen_corrupted = true;
}
+ fn estimate_size(&self) -> usize {
+ // Begin the estimate with the 4 byte header.
+ let mut estimate = 4;
+ // A very poor estimate.
+
+ // Estimate the size of the image hash.
+ if self.kinds.contains(&TlvKinds::SHA256) {
+ estimate += 4 + 32;
+ }
+
+ // Add an estimate in for each of the signature algorithms.
+ if self.kinds.contains(&TlvKinds::RSA2048) {
+ estimate += 4 + 32; // keyhash
+ estimate += 4 + 256; // RSA2048
+ }
+ if self.kinds.contains(&TlvKinds::RSA3072) {
+ estimate += 4 + 32; // keyhash
+ estimate += 4 + 384; // RSA3072
+ }
+ if self.kinds.contains(&TlvKinds::ECDSA256) {
+ estimate += 4 + 32; // keyhash
+
+ // ECDSA signatures are encoded as ASN.1 with the x and y values stored as signed
+ // integers. As such, the size can vary by 2 bytes, if the 256-bit value has the high
+ // bit, it takes an extra 0 byte to avoid it being seen as a negative number.
+ estimate += 4 + 72; // ECDSA256 (varies)
+ }
+ if self.kinds.contains(&TlvKinds::ED25519) {
+ estimate += 4 + 32; // keyhash
+ estimate += 4 + 64; // ED25519 signature.
+ }
+
+ // Estimate encryption.
+ let flag = TlvFlags::ENCRYPTED_AES256 as u32;
+ let aes256 = (self.get_flags() & flag) == flag;
+
+ if self.kinds.contains(&TlvKinds::ENCRSA2048) {
+ estimate += 4 + 256;
+ }
+ if self.kinds.contains(&TlvKinds::ENCKW) {
+ estimate += 4 + if aes256 { 40 } else { 24 };
+ }
+ if self.kinds.contains(&TlvKinds::ENCEC256) {
+ estimate += 4 + if aes256 { 129 } else { 113 };
+ }
+ if self.kinds.contains(&TlvKinds::ENCX25519) {
+ estimate += 4 + if aes256 { 96 } else { 80 };
+ }
+
+ // Gather the size of the dependency information.
+ if self.protect_size() > 0 {
+ estimate += 4 + (16 * self.dependencies.len());
+ }
+
+ estimate
+ }
+
/// Compute the TLV given the specified block of data.
fn make_tlv(self: Box<Self>) -> Vec<u8> {
+ let size_estimate = self.estimate_size();
+
let mut protected_tlv: Vec<u8> = vec![];
if self.protect_size() > 0 {
@@ -663,6 +727,25 @@
let mut size_buf = &mut result[npro_pos + 2 .. npro_pos + 4];
size_buf.write_u16::<LittleEndian>(size).unwrap();
+ // ECDSA is stored as an ASN.1 integer. For a 128-bit value, this maximally results in 33
+ // bytes of storage for each of the two values. If the high bit is zero, it will take 32
+ // bytes, if the top 8 bits are zero, it will take 31 bits, and so on. The smaller size
+ // will occur with decreasing likelihood. We'll allow this to get a bit smaller, hopefully
+ // allowing the tests to pass with false failures rare. For this case, we'll handle up to
+ // the top 16 bits of both numbers being all zeros (1 in 2^32).
+ if !Caps::has_ecdsa() {
+ if size_estimate != result.len() {
+ panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
+ }
+ } else {
+ if size_estimate < result.len() || size_estimate > result.len() + 6 {
+ panic!("Incorrect size estimate: {} (actual {})", size_estimate, result.len());
+ }
+ }
+ if size_estimate != result.len() {
+ log::warn!("Size off: {} actual {}", size_estimate, result.len());
+ }
+
result
}
diff --git a/sim/src/utils.rs b/sim/src/utils.rs
new file mode 100644
index 0000000..abbac3c
--- /dev/null
+++ b/sim/src/utils.rs
@@ -0,0 +1,11 @@
+// SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+//
+// SPDX-License-Identifier: Apache-2.0
+
+//! Utility functions used throughout MCUboot
+
+pub fn align_up(num: u32, align: u32) -> u32 {
+ assert!(align.is_power_of_two());
+
+ (num + (align - 1)) & !(align - 1)
+}