1 // Copyright (c) 2019 Linaro LTD
2 // Copyright (c) 2019-2020 JUUL Labs
3 // Copyright (c) 2019-2021 Arm Limited
4 //
5 // SPDX-License-Identifier: Apache-2.0
6
7 use byteorder::{
8 LittleEndian, WriteBytesExt,
9 };
10 use log::{
11 Level::Info,
12 error,
13 info,
14 log_enabled,
15 warn,
16 };
17 use rand::{
18 Rng, RngCore, SeedableRng,
19 rngs::SmallRng,
20 };
21 use std::{
22 collections::HashSet,
23 io::{Cursor, Write},
24 mem,
25 slice,
26 };
27 use aes_ctr::{
28 Aes128Ctr,
29 Aes256Ctr,
30 stream_cipher::{
31 generic_array::GenericArray,
32 NewStreamCipher,
33 SyncStreamCipher,
34 },
35 };
36
37 use simflash::{Flash, SimFlash, SimMultiFlash};
38 use mcuboot_sys::{c, AreaDesc, FlashId};
39 use crate::{
40 ALL_DEVICES,
41 DeviceName,
42 };
43 use crate::caps::Caps;
44 use crate::depends::{
45 BoringDep,
46 Depender,
47 DepTest,
48 DepType,
49 NO_DEPS,
50 PairDep,
51 UpgradeInfo,
52 };
53 use crate::tlv::{ManifestGen, TlvGen, TlvFlags};
54 use typenum::{U32, U16};
55
56 /// A builder for Images. This describes a single run of the simulator,
57 /// capturing the configuration of a particular set of devices, including
58 /// the flash simulator(s) and the information about the slots.
59 #[derive(Clone)]
60 pub struct ImagesBuilder {
61 flash: SimMultiFlash,
62 areadesc: AreaDesc,
63 slots: Vec<[SlotInfo; 2]>,
64 }
65
66 /// Images represents the state of a simulation for a given set of images.
67 /// The flash holds the state of the simulated flash, whereas primaries
68 /// and upgrades hold the expected contents of these images.
69 pub struct Images {
70 flash: SimMultiFlash,
71 areadesc: AreaDesc,
72 images: Vec<OneImage>,
73 total_count: Option<i32>,
74 }
75
76 /// When doing multi-image, there is an instance of this information for
77 /// each of the images. Single image there will be one of these.
78 struct OneImage {
79 slots: [SlotInfo; 2],
80 primaries: ImageData,
81 upgrades: ImageData,
82 }
83
84 /// The Rust-side representation of an image. For unencrypted images, this
85 /// is just the unencrypted payload. For encrypted images, we store both
86 /// the encrypted and the plaintext.
87 struct ImageData {
88 plain: Vec<u8>,
89 cipher: Option<Vec<u8>>,
90 }
91
92 impl ImagesBuilder {
93 /// Construct a new image builder for the given device. Returns
94 /// Some(builder) if is possible to test this configuration, or None if
95 /// not possible (for example, if there aren't enough image slots).
new(device: DeviceName, align: usize, erased_val: u8) -> Result<Self, String>96 pub fn new(device: DeviceName, align: usize, erased_val: u8) -> Result<Self, String> {
97 let (flash, areadesc, unsupported_caps) = Self::make_device(device, align, erased_val);
98
99 for cap in unsupported_caps {
100 if cap.present() {
101 return Err(format!("unsupported {:?}", cap));
102 }
103 }
104
105 let num_images = Caps::get_num_images();
106
107 let mut slots = Vec::with_capacity(num_images);
108 for image in 0..num_images {
109 // This mapping must match that defined in
110 // `boot/zephyr/include/sysflash/sysflash.h`.
111 let id0 = match image {
112 0 => FlashId::Image0,
113 1 => FlashId::Image2,
114 _ => panic!("More than 2 images not supported"),
115 };
116 let (primary_base, primary_len, primary_dev_id) = match areadesc.find(id0) {
117 Some(info) => info,
118 None => return Err("insufficient partitions".to_string()),
119 };
120 let id1 = match image {
121 0 => FlashId::Image1,
122 1 => FlashId::Image3,
123 _ => panic!("More than 2 images not supported"),
124 };
125 let (secondary_base, secondary_len, secondary_dev_id) = match areadesc.find(id1) {
126 Some(info) => info,
127 None => return Err("insufficient partitions".to_string()),
128 };
129
130 let offset_from_end = c::boot_magic_sz() + c::boot_max_align() * 4;
131
132 // Construct a primary image.
133 let primary = SlotInfo {
134 base_off: primary_base as usize,
135 trailer_off: primary_base + primary_len - offset_from_end,
136 len: primary_len as usize,
137 dev_id: primary_dev_id,
138 index: 0,
139 };
140
141 // And an upgrade image.
142 let secondary = SlotInfo {
143 base_off: secondary_base as usize,
144 trailer_off: secondary_base + secondary_len - offset_from_end,
145 len: secondary_len as usize,
146 dev_id: secondary_dev_id,
147 index: 1,
148 };
149
150 slots.push([primary, secondary]);
151 }
152
153 Ok(ImagesBuilder {
154 flash,
155 areadesc,
156 slots,
157 })
158 }
159
each_device<F>(f: F) where F: Fn(Self)160 pub fn each_device<F>(f: F)
161 where F: Fn(Self)
162 {
163 for &dev in ALL_DEVICES {
164 for &align in test_alignments() {
165 for &erased_val in &[0, 0xff] {
166 match Self::new(dev, align, erased_val) {
167 Ok(run) => f(run),
168 Err(msg) => warn!("Skipping {}: {}", dev, msg),
169 }
170 }
171 }
172 }
173 }
174
175 /// Construct an `Images` that doesn't expect an upgrade to happen.
make_no_upgrade_image(self, deps: &DepTest) -> Images176 pub fn make_no_upgrade_image(self, deps: &DepTest) -> Images {
177 let num_images = self.num_images();
178 let mut flash = self.flash;
179 let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
180 let dep: Box<dyn Depender> = if num_images > 1 {
181 Box::new(PairDep::new(num_images, image_num, deps))
182 } else {
183 Box::new(BoringDep::new(image_num, deps))
184 };
185 let primaries = install_image(&mut flash, &slots[0], 42784, &*dep, false);
186 let upgrades = match deps.depends[image_num] {
187 DepType::NoUpgrade => install_no_image(),
188 _ => install_image(&mut flash, &slots[1], 46928, &*dep, false)
189 };
190 OneImage {
191 slots,
192 primaries,
193 upgrades,
194 }}).collect();
195 install_ptable(&mut flash, &self.areadesc);
196 Images {
197 flash,
198 areadesc: self.areadesc,
199 images,
200 total_count: None,
201 }
202 }
203
make_image(self, deps: &DepTest, permanent: bool) -> Images204 pub fn make_image(self, deps: &DepTest, permanent: bool) -> Images {
205 let mut images = self.make_no_upgrade_image(deps);
206 for image in &images.images {
207 mark_upgrade(&mut images.flash, &image.slots[1]);
208 }
209
210 // upgrades without fails, counts number of flash operations
211 let total_count = match images.run_basic_upgrade(permanent) {
212 Some(v) => v,
213 None =>
214 if deps.upgrades.iter().any(|u| *u == UpgradeInfo::Held) {
215 0
216 } else {
217 panic!("Unable to perform basic upgrade");
218 }
219 };
220
221 images.total_count = Some(total_count);
222 images
223 }
224
make_bad_secondary_slot_image(self) -> Images225 pub fn make_bad_secondary_slot_image(self) -> Images {
226 let mut bad_flash = self.flash;
227 let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
228 let dep = BoringDep::new(image_num, &NO_DEPS);
229 let primaries = install_image(&mut bad_flash, &slots[0], 32784, &dep, false);
230 let upgrades = install_image(&mut bad_flash, &slots[1], 41928, &dep, true);
231 OneImage {
232 slots,
233 primaries,
234 upgrades,
235 }}).collect();
236 Images {
237 flash: bad_flash,
238 areadesc: self.areadesc,
239 images,
240 total_count: None,
241 }
242 }
243
make_erased_secondary_image(self) -> Images244 pub fn make_erased_secondary_image(self) -> Images {
245 let mut flash = self.flash;
246 let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
247 let dep = BoringDep::new(image_num, &NO_DEPS);
248 let primaries = install_image(&mut flash, &slots[0], 32784, &dep, false);
249 let upgrades = install_no_image();
250 OneImage {
251 slots,
252 primaries,
253 upgrades,
254 }}).collect();
255 Images {
256 flash,
257 areadesc: self.areadesc,
258 images,
259 total_count: None,
260 }
261 }
262
make_bootstrap_image(self) -> Images263 pub fn make_bootstrap_image(self) -> Images {
264 let mut flash = self.flash;
265 let images = self.slots.into_iter().enumerate().map(|(image_num, slots)| {
266 let dep = BoringDep::new(image_num, &NO_DEPS);
267 let primaries = install_no_image();
268 let upgrades = install_image(&mut flash, &slots[1], 32784, &dep, false);
269 OneImage {
270 slots,
271 primaries,
272 upgrades,
273 }}).collect();
274 Images {
275 flash,
276 areadesc: self.areadesc,
277 images,
278 total_count: None,
279 }
280 }
281
282 /// Build the Flash and area descriptor for a given device.
make_device(device: DeviceName, align: usize, erased_val: u8) -> (SimMultiFlash, AreaDesc, &'static [Caps])283 pub fn make_device(device: DeviceName, align: usize, erased_val: u8) -> (SimMultiFlash, AreaDesc, &'static [Caps]) {
284 match device {
285 DeviceName::Stm32f4 => {
286 // STM style flash. Large sectors, with a large scratch area.
287 let dev = SimFlash::new(vec![16 * 1024, 16 * 1024, 16 * 1024, 16 * 1024,
288 64 * 1024,
289 128 * 1024, 128 * 1024, 128 * 1024],
290 align as usize, erased_val);
291 let dev_id = 0;
292 let mut areadesc = AreaDesc::new();
293 areadesc.add_flash_sectors(dev_id, &dev);
294 areadesc.add_image(0x020000, 0x020000, FlashId::Image0, dev_id);
295 areadesc.add_image(0x040000, 0x020000, FlashId::Image1, dev_id);
296 areadesc.add_image(0x060000, 0x020000, FlashId::ImageScratch, dev_id);
297
298 let mut flash = SimMultiFlash::new();
299 flash.insert(dev_id, dev);
300 (flash, areadesc, &[Caps::SwapUsingMove])
301 }
302 DeviceName::K64f => {
303 // NXP style flash. Small sectors, one small sector for scratch.
304 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
305
306 let dev_id = 0;
307 let mut areadesc = AreaDesc::new();
308 areadesc.add_flash_sectors(dev_id, &dev);
309 areadesc.add_image(0x020000, 0x020000, FlashId::Image0, dev_id);
310 areadesc.add_image(0x040000, 0x020000, FlashId::Image1, dev_id);
311 areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch, dev_id);
312
313 let mut flash = SimMultiFlash::new();
314 flash.insert(dev_id, dev);
315 (flash, areadesc, &[])
316 }
317 DeviceName::K64fBig => {
318 // Simulating an STM style flash on top of an NXP style flash. Underlying flash device
319 // uses small sectors, but we tell the bootloader they are large.
320 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
321
322 let dev_id = 0;
323 let mut areadesc = AreaDesc::new();
324 areadesc.add_flash_sectors(dev_id, &dev);
325 areadesc.add_simple_image(0x020000, 0x020000, FlashId::Image0, dev_id);
326 areadesc.add_simple_image(0x040000, 0x020000, FlashId::Image1, dev_id);
327 areadesc.add_simple_image(0x060000, 0x020000, FlashId::ImageScratch, dev_id);
328
329 let mut flash = SimMultiFlash::new();
330 flash.insert(dev_id, dev);
331 (flash, areadesc, &[Caps::SwapUsingMove])
332 }
333 DeviceName::Nrf52840 => {
334 // Simulating the flash on the nrf52840 with partitions set up so that the scratch size
335 // does not divide into the image size.
336 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
337
338 let dev_id = 0;
339 let mut areadesc = AreaDesc::new();
340 areadesc.add_flash_sectors(dev_id, &dev);
341 areadesc.add_image(0x008000, 0x034000, FlashId::Image0, dev_id);
342 areadesc.add_image(0x03c000, 0x034000, FlashId::Image1, dev_id);
343 areadesc.add_image(0x070000, 0x00d000, FlashId::ImageScratch, dev_id);
344
345 let mut flash = SimMultiFlash::new();
346 flash.insert(dev_id, dev);
347 (flash, areadesc, &[])
348 }
349 DeviceName::Nrf52840UnequalSlots => {
350 let dev = SimFlash::new(vec![4096; 128], align as usize, erased_val);
351
352 let dev_id = 0;
353 let mut areadesc = AreaDesc::new();
354 areadesc.add_flash_sectors(dev_id, &dev);
355 areadesc.add_image(0x008000, 0x03c000, FlashId::Image0, dev_id);
356 areadesc.add_image(0x044000, 0x03b000, FlashId::Image1, dev_id);
357
358 let mut flash = SimMultiFlash::new();
359 flash.insert(dev_id, dev);
360 (flash, areadesc, &[Caps::SwapUsingScratch, Caps::OverwriteUpgrade])
361 }
362 DeviceName::Nrf52840SpiFlash => {
363 // Simulate nrf52840 with external SPI flash. The external SPI flash
364 // has a larger sector size so for now store scratch on that flash.
365 let dev0 = SimFlash::new(vec![4096; 128], align as usize, erased_val);
366 let dev1 = SimFlash::new(vec![8192; 64], align as usize, erased_val);
367
368 let mut areadesc = AreaDesc::new();
369 areadesc.add_flash_sectors(0, &dev0);
370 areadesc.add_flash_sectors(1, &dev1);
371
372 areadesc.add_image(0x008000, 0x068000, FlashId::Image0, 0);
373 areadesc.add_image(0x000000, 0x068000, FlashId::Image1, 1);
374 areadesc.add_image(0x068000, 0x018000, FlashId::ImageScratch, 1);
375
376 let mut flash = SimMultiFlash::new();
377 flash.insert(0, dev0);
378 flash.insert(1, dev1);
379 (flash, areadesc, &[Caps::SwapUsingMove])
380 }
381 DeviceName::K64fMulti => {
382 // NXP style flash, but larger, to support multiple images.
383 let dev = SimFlash::new(vec![4096; 256], align as usize, erased_val);
384
385 let dev_id = 0;
386 let mut areadesc = AreaDesc::new();
387 areadesc.add_flash_sectors(dev_id, &dev);
388 areadesc.add_image(0x020000, 0x020000, FlashId::Image0, dev_id);
389 areadesc.add_image(0x040000, 0x020000, FlashId::Image1, dev_id);
390 areadesc.add_image(0x060000, 0x001000, FlashId::ImageScratch, dev_id);
391 areadesc.add_image(0x080000, 0x020000, FlashId::Image2, dev_id);
392 areadesc.add_image(0x0a0000, 0x020000, FlashId::Image3, dev_id);
393
394 let mut flash = SimMultiFlash::new();
395 flash.insert(dev_id, dev);
396 (flash, areadesc, &[])
397 }
398 }
399 }
400
num_images(&self) -> usize401 pub fn num_images(&self) -> usize {
402 self.slots.len()
403 }
404 }
405
406 impl Images {
407 /// A simple upgrade without forced failures.
408 ///
409 /// Returns the number of flash operations which can later be used to
410 /// inject failures at chosen steps. Returns None if it was unable to
411 /// count the operations in a basic upgrade.
run_basic_upgrade(&self, permanent: bool) -> Option<i32>412 pub fn run_basic_upgrade(&self, permanent: bool) -> Option<i32> {
413 let (flash, total_count) = self.try_upgrade(None, permanent);
414 info!("Total flash operation count={}", total_count);
415
416 if !self.verify_images(&flash, 0, 1) {
417 warn!("Image mismatch after first boot");
418 None
419 } else {
420 Some(total_count)
421 }
422 }
423
run_bootstrap(&self) -> bool424 pub fn run_bootstrap(&self) -> bool {
425 let mut flash = self.flash.clone();
426 let mut fails = 0;
427
428 if Caps::Bootstrap.present() {
429 info!("Try bootstraping image in the primary");
430
431 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
432 if result != 0 {
433 warn!("Failed first boot");
434 fails += 1;
435 }
436
437 if !self.verify_images(&flash, 0, 1) {
438 warn!("Image in the first slot was not bootstrapped");
439 fails += 1;
440 }
441
442 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
443 BOOT_FLAG_SET, BOOT_FLAG_SET) {
444 warn!("Mismatched trailer for the primary slot");
445 fails += 1;
446 }
447 }
448
449 if fails > 0 {
450 error!("Expected trailer on secondary slot to be erased");
451 }
452
453 fails > 0
454 }
455
456
457 /// Test a simple upgrade, with dependencies given, and verify that the
458 /// image does as is described in the test.
run_check_deps(&self, deps: &DepTest) -> bool459 pub fn run_check_deps(&self, deps: &DepTest) -> bool {
460 let (flash, _) = self.try_upgrade(None, true);
461
462 self.verify_dep_images(&flash, deps)
463 }
464
is_swap_upgrade(&self) -> bool465 fn is_swap_upgrade(&self) -> bool {
466 Caps::SwapUsingScratch.present() || Caps::SwapUsingMove.present()
467 }
468
run_basic_revert(&self) -> bool469 pub fn run_basic_revert(&self) -> bool {
470 if Caps::OverwriteUpgrade.present() {
471 return false;
472 }
473
474 let mut fails = 0;
475
476 // FIXME: this test would also pass if no swap is ever performed???
477 if self.is_swap_upgrade() {
478 for count in 2 .. 5 {
479 info!("Try revert: {}", count);
480 let flash = self.try_revert(count);
481 if !self.verify_images(&flash, 0, 0) {
482 error!("Revert failure on count {}", count);
483 fails += 1;
484 }
485 }
486 }
487
488 fails > 0
489 }
490
run_perm_with_fails(&self) -> bool491 pub fn run_perm_with_fails(&self) -> bool {
492 let mut fails = 0;
493 let total_flash_ops = self.total_count.unwrap();
494
495 // Let's try an image halfway through.
496 for i in 1 .. total_flash_ops {
497 info!("Try interruption at {}", i);
498 let (flash, count) = self.try_upgrade(Some(i), true);
499 info!("Second boot, count={}", count);
500 if !self.verify_images(&flash, 0, 1) {
501 warn!("FAIL at step {} of {}", i, total_flash_ops);
502 fails += 1;
503 }
504
505 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
506 BOOT_FLAG_SET, BOOT_FLAG_SET) {
507 warn!("Mismatched trailer for the primary slot");
508 fails += 1;
509 }
510
511 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
512 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
513 warn!("Mismatched trailer for the secondary slot");
514 fails += 1;
515 }
516
517 if self.is_swap_upgrade() && !self.verify_images(&flash, 1, 0) {
518 warn!("Secondary slot FAIL at step {} of {}",
519 i, total_flash_ops);
520 fails += 1;
521 }
522 }
523
524 if fails > 0 {
525 error!("{} out of {} failed {:.2}%", fails, total_flash_ops,
526 fails as f32 * 100.0 / total_flash_ops as f32);
527 }
528
529 fails > 0
530 }
531
run_perm_with_random_fails(&self, total_fails: usize) -> bool532 pub fn run_perm_with_random_fails(&self, total_fails: usize) -> bool {
533 let mut fails = 0;
534 let total_flash_ops = self.total_count.unwrap();
535 let (flash, total_counts) = self.try_random_fails(total_flash_ops, total_fails);
536 info!("Random interruptions at reset points={:?}", total_counts);
537
538 let primary_slot_ok = self.verify_images(&flash, 0, 1);
539 let secondary_slot_ok = if self.is_swap_upgrade() {
540 // TODO: This result is ignored.
541 self.verify_images(&flash, 1, 0)
542 } else {
543 true
544 };
545 if !primary_slot_ok || !secondary_slot_ok {
546 error!("Image mismatch after random interrupts: primary slot={} \
547 secondary slot={}",
548 if primary_slot_ok { "ok" } else { "fail" },
549 if secondary_slot_ok { "ok" } else { "fail" });
550 fails += 1;
551 }
552 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
553 BOOT_FLAG_SET, BOOT_FLAG_SET) {
554 error!("Mismatched trailer for the primary slot");
555 fails += 1;
556 }
557 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
558 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
559 error!("Mismatched trailer for the secondary slot");
560 fails += 1;
561 }
562
563 if fails > 0 {
564 error!("Error testing perm upgrade with {} fails", total_fails);
565 }
566
567 fails > 0
568 }
569
run_revert_with_fails(&self) -> bool570 pub fn run_revert_with_fails(&self) -> bool {
571 if Caps::OverwriteUpgrade.present() {
572 return false;
573 }
574
575 let mut fails = 0;
576
577 if self.is_swap_upgrade() {
578 for i in 1 .. self.total_count.unwrap() {
579 info!("Try interruption at {}", i);
580 if self.try_revert_with_fail_at(i) {
581 error!("Revert failed at interruption {}", i);
582 fails += 1;
583 }
584 }
585 }
586
587 fails > 0
588 }
589
run_norevert(&self) -> bool590 pub fn run_norevert(&self) -> bool {
591 if Caps::OverwriteUpgrade.present() {
592 return false;
593 }
594
595 let mut flash = self.flash.clone();
596 let mut fails = 0;
597
598 info!("Try norevert");
599
600 // First do a normal upgrade...
601 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
602 if result != 0 {
603 warn!("Failed first boot");
604 fails += 1;
605 }
606
607 //FIXME: copy_done is written by boot_go, is it ok if no copy
608 // was ever done?
609
610 if !self.verify_images(&flash, 0, 1) {
611 warn!("Primary slot image verification FAIL");
612 fails += 1;
613 }
614 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
615 BOOT_FLAG_UNSET, BOOT_FLAG_SET) {
616 warn!("Mismatched trailer for the primary slot");
617 fails += 1;
618 }
619 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
620 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
621 warn!("Mismatched trailer for the secondary slot");
622 fails += 1;
623 }
624
625 // Marks image in the primary slot as permanent,
626 // no revert should happen...
627 self.mark_permanent_upgrades(&mut flash, 0);
628
629 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
630 BOOT_FLAG_SET, BOOT_FLAG_SET) {
631 warn!("Mismatched trailer for the primary slot");
632 fails += 1;
633 }
634
635 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
636 if result != 0 {
637 warn!("Failed second boot");
638 fails += 1;
639 }
640
641 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
642 BOOT_FLAG_SET, BOOT_FLAG_SET) {
643 warn!("Mismatched trailer for the primary slot");
644 fails += 1;
645 }
646 if !self.verify_images(&flash, 0, 1) {
647 warn!("Failed image verification");
648 fails += 1;
649 }
650
651 if fails > 0 {
652 error!("Error running upgrade without revert");
653 }
654
655 fails > 0
656 }
657
658 // Test that an upgrade is rejected. Assumes that the image was build
659 // such that the upgrade is instead a downgrade.
run_nodowngrade(&self) -> bool660 pub fn run_nodowngrade(&self) -> bool {
661 if !Caps::DowngradePrevention.present() {
662 return false;
663 }
664
665 let mut flash = self.flash.clone();
666 let mut fails = 0;
667
668 info!("Try no downgrade");
669
670 // First, do a normal upgrade.
671 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
672 if result != 0 {
673 warn!("Failed first boot");
674 fails += 1;
675 }
676
677 if !self.verify_images(&flash, 0, 0) {
678 warn!("Failed verification after downgrade rejection");
679 fails += 1;
680 }
681
682 if fails > 0 {
683 error!("Error testing downgrade rejection");
684 }
685
686 fails > 0
687 }
688
689 // Tests a new image written to the primary slot that already has magic and
690 // image_ok set while there is no image on the secondary slot, so no revert
691 // should ever happen...
run_norevert_newimage(&self) -> bool692 pub fn run_norevert_newimage(&self) -> bool {
693 let mut flash = self.flash.clone();
694 let mut fails = 0;
695
696 info!("Try non-revert on imgtool generated image");
697
698 self.mark_upgrades(&mut flash, 0);
699
700 // This simulates writing an image created by imgtool to
701 // the primary slot
702 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
703 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
704 warn!("Mismatched trailer for the primary slot");
705 fails += 1;
706 }
707
708 // Run the bootloader...
709 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
710 if result != 0 {
711 warn!("Failed first boot");
712 fails += 1;
713 }
714
715 // State should not have changed
716 if !self.verify_images(&flash, 0, 0) {
717 warn!("Failed image verification");
718 fails += 1;
719 }
720 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
721 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
722 warn!("Mismatched trailer for the primary slot");
723 fails += 1;
724 }
725 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
726 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
727 warn!("Mismatched trailer for the secondary slot");
728 fails += 1;
729 }
730
731 if fails > 0 {
732 error!("Expected a non revert with new image");
733 }
734
735 fails > 0
736 }
737
738 // Tests a new image written to the primary slot that already has magic and
739 // image_ok set while there is no image on the secondary slot, so no revert
740 // should ever happen...
run_signfail_upgrade(&self) -> bool741 pub fn run_signfail_upgrade(&self) -> bool {
742 let mut flash = self.flash.clone();
743 let mut fails = 0;
744
745 info!("Try upgrade image with bad signature");
746
747 self.mark_upgrades(&mut flash, 0);
748 self.mark_permanent_upgrades(&mut flash, 0);
749 self.mark_upgrades(&mut flash, 1);
750
751 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
752 BOOT_FLAG_SET, BOOT_FLAG_UNSET) {
753 warn!("Mismatched trailer for the primary slot");
754 fails += 1;
755 }
756
757 // Run the bootloader...
758 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
759 if result != 0 {
760 warn!("Failed first boot");
761 fails += 1;
762 }
763
764 // State should not have changed
765 if !self.verify_images(&flash, 0, 0) {
766 warn!("Failed image verification");
767 fails += 1;
768 }
769 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
770 BOOT_FLAG_SET, BOOT_FLAG_UNSET) {
771 warn!("Mismatched trailer for the primary slot");
772 fails += 1;
773 }
774
775 if fails > 0 {
776 error!("Expected an upgrade failure when image has bad signature");
777 }
778
779 fails > 0
780 }
781
782 // Should detect there is a leftover trailer in an otherwise erased
783 // secondary slot and erase its trailer.
run_secondary_leftover_trailer(&self) -> bool784 pub fn run_secondary_leftover_trailer(&self) -> bool {
785 let mut flash = self.flash.clone();
786 let mut fails = 0;
787
788 info!("Try with a leftover trailer in the secondary; must be erased");
789
790 // Add a trailer on the secondary slot
791 self.mark_permanent_upgrades(&mut flash, 1);
792 self.mark_upgrades(&mut flash, 1);
793
794 // Run the bootloader...
795 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
796 if result != 0 {
797 warn!("Failed first boot");
798 fails += 1;
799 }
800
801 // State should not have changed
802 if !self.verify_images(&flash, 0, 0) {
803 warn!("Failed image verification");
804 fails += 1;
805 }
806 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
807 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
808 warn!("Mismatched trailer for the secondary slot");
809 fails += 1;
810 }
811
812 if fails > 0 {
813 error!("Expected trailer on secondary slot to be erased");
814 }
815
816 fails > 0
817 }
818
trailer_sz(&self, align: usize) -> usize819 fn trailer_sz(&self, align: usize) -> usize {
820 c::boot_trailer_sz(align as u32) as usize
821 }
822
status_sz(&self, align: usize) -> usize823 fn status_sz(&self, align: usize) -> usize {
824 c::boot_status_sz(align as u32) as usize
825 }
826
827 /// This test runs a simple upgrade with no fails in the images, but
828 /// allowing for fails in the status area. This should run to the end
829 /// and warn that write fails were detected...
run_with_status_fails_complete(&self) -> bool830 pub fn run_with_status_fails_complete(&self) -> bool {
831 if !Caps::ValidatePrimarySlot.present() {
832 return false;
833 }
834
835 let mut flash = self.flash.clone();
836 let mut fails = 0;
837
838 info!("Try swap with status fails");
839
840 self.mark_permanent_upgrades(&mut flash, 1);
841 self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
842
843 let (result, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
844 if result != 0 {
845 warn!("Failed!");
846 fails += 1;
847 }
848
849 // Failed writes to the marked "bad" region don't assert anymore.
850 // Any detected assert() is happening in another part of the code.
851 if asserts != 0 {
852 warn!("At least one assert() was called");
853 fails += 1;
854 }
855
856 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
857 BOOT_FLAG_SET, BOOT_FLAG_SET) {
858 warn!("Mismatched trailer for the primary slot");
859 fails += 1;
860 }
861
862 if !self.verify_images(&flash, 0, 1) {
863 warn!("Failed image verification");
864 fails += 1;
865 }
866
867 info!("validate primary slot enabled; \
868 re-run of boot_go should just work");
869 let (result, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
870 if result != 0 {
871 warn!("Failed!");
872 fails += 1;
873 }
874
875 if fails > 0 {
876 error!("Error running upgrade with status write fails");
877 }
878
879 fails > 0
880 }
881
882 /// This test runs a simple upgrade with no fails in the images, but
883 /// allowing for fails in the status area. This should run to the end
884 /// and warn that write fails were detected...
run_with_status_fails_with_reset(&self) -> bool885 pub fn run_with_status_fails_with_reset(&self) -> bool {
886 if Caps::OverwriteUpgrade.present() {
887 false
888 } else if Caps::ValidatePrimarySlot.present() {
889
890 let mut flash = self.flash.clone();
891 let mut fails = 0;
892 let mut count = self.total_count.unwrap() / 2;
893
894 //info!("count={}\n", count);
895
896 info!("Try interrupted swap with status fails");
897
898 self.mark_permanent_upgrades(&mut flash, 1);
899 self.mark_bad_status_with_rate(&mut flash, 0, 0.5);
900
901 // Should not fail, writing to bad regions does not assert
902 let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, Some(&mut count), true);
903 if asserts != 0 {
904 warn!("At least one assert() was called");
905 fails += 1;
906 }
907
908 self.reset_bad_status(&mut flash, 0);
909
910 info!("Resuming an interrupted swap operation");
911 let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
912
913 // This might throw no asserts, for large sector devices, where
914 // a single failure writing is indistinguishable from no failure,
915 // or throw a single assert for small sector devices that fail
916 // multiple times...
917 if asserts > 1 {
918 warn!("Expected single assert validating the primary slot, \
919 more detected {}", asserts);
920 fails += 1;
921 }
922
923 if fails > 0 {
924 error!("Error running upgrade with status write fails");
925 }
926
927 fails > 0
928 } else {
929 let mut flash = self.flash.clone();
930 let mut fails = 0;
931
932 info!("Try interrupted swap with status fails");
933
934 self.mark_permanent_upgrades(&mut flash, 1);
935 self.mark_bad_status_with_rate(&mut flash, 0, 1.0);
936
937 // This is expected to fail while writing to bad regions...
938 let (_, asserts) = c::boot_go(&mut flash, &self.areadesc, None, true);
939 if asserts == 0 {
940 warn!("No assert() detected");
941 fails += 1;
942 }
943
944 fails > 0
945 }
946 }
947
948 /// Adds a new flash area that fails statistically
mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize, rate: f32)949 fn mark_bad_status_with_rate(&self, flash: &mut SimMultiFlash, slot: usize,
950 rate: f32) {
951 if Caps::OverwriteUpgrade.present() {
952 return;
953 }
954
955 // Set this for each image.
956 for image in &self.images {
957 let dev_id = &image.slots[slot].dev_id;
958 let dev = flash.get_mut(&dev_id).unwrap();
959 let align = dev.align();
960 let off = &image.slots[slot].base_off;
961 let len = &image.slots[slot].len;
962 let status_off = off + len - self.trailer_sz(align);
963
964 // Mark the status area as a bad area
965 let _ = dev.add_bad_region(status_off, self.status_sz(align), rate);
966 }
967 }
968
reset_bad_status(&self, flash: &mut SimMultiFlash, slot: usize)969 fn reset_bad_status(&self, flash: &mut SimMultiFlash, slot: usize) {
970 if !Caps::ValidatePrimarySlot.present() {
971 return;
972 }
973
974 for image in &self.images {
975 let dev_id = &image.slots[slot].dev_id;
976 let dev = flash.get_mut(&dev_id).unwrap();
977 dev.reset_bad_regions();
978
979 // Disabling write verification the only assert triggered by
980 // boot_go should be checking for integrity of status bytes.
981 dev.set_verify_writes(false);
982 }
983 }
984
985 /// Test a boot, optionally stopping after 'n' flash options. Returns a count
986 /// of the number of flash operations done total.
try_upgrade(&self, stop: Option<i32>, permanent: bool) -> (SimMultiFlash, i32)987 fn try_upgrade(&self, stop: Option<i32>, permanent: bool) -> (SimMultiFlash, i32) {
988 // Clone the flash to have a new copy.
989 let mut flash = self.flash.clone();
990
991 if permanent {
992 self.mark_permanent_upgrades(&mut flash, 1);
993 }
994
995 let mut counter = stop.unwrap_or(0);
996
997 let (first_interrupted, count) = match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
998 (-0x13579, _) => (true, stop.unwrap()),
999 (0, _) => (false, -counter),
1000 (x, _) => panic!("Unknown return: {}", x),
1001 };
1002
1003 counter = 0;
1004 if first_interrupted {
1005 // fl.dump();
1006 match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
1007 (-0x13579, _) => panic!("Shouldn't stop again"),
1008 (0, _) => (),
1009 (x, _) => panic!("Unknown return: {}", x),
1010 }
1011 }
1012
1013 (flash, count - counter)
1014 }
1015
try_revert(&self, count: usize) -> SimMultiFlash1016 fn try_revert(&self, count: usize) -> SimMultiFlash {
1017 let mut flash = self.flash.clone();
1018
1019 // fl.write_file("image0.bin").unwrap();
1020 for i in 0 .. count {
1021 info!("Running boot pass {}", i + 1);
1022 assert_eq!(c::boot_go(&mut flash, &self.areadesc, None, false), (0, 0));
1023 }
1024 flash
1025 }
1026
try_revert_with_fail_at(&self, stop: i32) -> bool1027 fn try_revert_with_fail_at(&self, stop: i32) -> bool {
1028 let mut flash = self.flash.clone();
1029 let mut fails = 0;
1030
1031 let mut counter = stop;
1032 let (x, _) = c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false);
1033 if x != -0x13579 {
1034 warn!("Should have stopped test at interruption point");
1035 fails += 1;
1036 }
1037
1038 // In a multi-image setup, copy done might be set if any number of
1039 // images was already successfully swapped.
1040 if !self.verify_trailers_loose(&flash, 0, None, None, BOOT_FLAG_UNSET) {
1041 warn!("copy_done should be unset");
1042 fails += 1;
1043 }
1044
1045 let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
1046 if x != 0 {
1047 warn!("Should have finished test upgrade");
1048 fails += 1;
1049 }
1050
1051 if !self.verify_images(&flash, 0, 1) {
1052 warn!("Image in the primary slot before revert is invalid at stop={}",
1053 stop);
1054 fails += 1;
1055 }
1056 if !self.verify_images(&flash, 1, 0) {
1057 warn!("Image in the secondary slot before revert is invalid at stop={}",
1058 stop);
1059 fails += 1;
1060 }
1061 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
1062 BOOT_FLAG_UNSET, BOOT_FLAG_SET) {
1063 warn!("Mismatched trailer for the primary slot before revert");
1064 fails += 1;
1065 }
1066 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
1067 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
1068 warn!("Mismatched trailer for the secondary slot before revert");
1069 fails += 1;
1070 }
1071
1072 // Do Revert
1073 let mut counter = stop;
1074 let (x, _) = c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false);
1075 if x != -0x13579 {
1076 warn!("Should have stopped revert at interruption point");
1077 fails += 1;
1078 }
1079
1080 let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
1081 if x != 0 {
1082 warn!("Should have finished revert upgrade");
1083 fails += 1;
1084 }
1085
1086 if !self.verify_images(&flash, 0, 0) {
1087 warn!("Image in the primary slot after revert is invalid at stop={}",
1088 stop);
1089 fails += 1;
1090 }
1091 if !self.verify_images(&flash, 1, 1) {
1092 warn!("Image in the secondary slot after revert is invalid at stop={}",
1093 stop);
1094 fails += 1;
1095 }
1096
1097 if !self.verify_trailers(&flash, 0, BOOT_MAGIC_GOOD,
1098 BOOT_FLAG_SET, BOOT_FLAG_SET) {
1099 warn!("Mismatched trailer for the primary slot after revert");
1100 fails += 1;
1101 }
1102 if !self.verify_trailers(&flash, 1, BOOT_MAGIC_UNSET,
1103 BOOT_FLAG_UNSET, BOOT_FLAG_UNSET) {
1104 warn!("Mismatched trailer for the secondary slot after revert");
1105 fails += 1;
1106 }
1107
1108 let (x, _) = c::boot_go(&mut flash, &self.areadesc, None, false);
1109 if x != 0 {
1110 warn!("Should have finished 3rd boot");
1111 fails += 1;
1112 }
1113
1114 if !self.verify_images(&flash, 0, 0) {
1115 warn!("Image in the primary slot is invalid on 1st boot after revert");
1116 fails += 1;
1117 }
1118 if !self.verify_images(&flash, 1, 1) {
1119 warn!("Image in the secondary slot is invalid on 1st boot after revert");
1120 fails += 1;
1121 }
1122
1123 fails > 0
1124 }
1125
1126
try_random_fails(&self, total_ops: i32, count: usize) -> (SimMultiFlash, Vec<i32>)1127 fn try_random_fails(&self, total_ops: i32, count: usize) -> (SimMultiFlash, Vec<i32>) {
1128 let mut flash = self.flash.clone();
1129
1130 self.mark_permanent_upgrades(&mut flash, 1);
1131
1132 let mut rng = rand::thread_rng();
1133 let mut resets = vec![0i32; count];
1134 let mut remaining_ops = total_ops;
1135 for reset in &mut resets {
1136 let reset_counter = rng.gen_range(1, remaining_ops / 2);
1137 let mut counter = reset_counter;
1138 match c::boot_go(&mut flash, &self.areadesc, Some(&mut counter), false) {
1139 (0, _) | (-0x13579, _) => (),
1140 (x, _) => panic!("Unknown return: {}", x),
1141 }
1142 remaining_ops -= reset_counter;
1143 *reset = reset_counter;
1144 }
1145
1146 match c::boot_go(&mut flash, &self.areadesc, None, false) {
1147 (-0x13579, _) => panic!("Should not be have been interrupted!"),
1148 (0, _) => (),
1149 (x, _) => panic!("Unknown return: {}", x),
1150 }
1151
1152 (flash, resets)
1153 }
1154
1155 /// Verify the image in the given flash device, the specified slot
1156 /// against the expected image.
verify_images(&self, flash: &SimMultiFlash, slot: usize, against: usize) -> bool1157 fn verify_images(&self, flash: &SimMultiFlash, slot: usize, against: usize) -> bool {
1158 self.images.iter().all(|image| {
1159 verify_image(flash, &image.slots[slot],
1160 match against {
1161 0 => &image.primaries,
1162 1 => &image.upgrades,
1163 _ => panic!("Invalid 'against'")
1164 })
1165 })
1166 }
1167
1168 /// Verify the images, according to the dependency test.
verify_dep_images(&self, flash: &SimMultiFlash, deps: &DepTest) -> bool1169 fn verify_dep_images(&self, flash: &SimMultiFlash, deps: &DepTest) -> bool {
1170 for (image_num, (image, upgrade)) in self.images.iter().zip(deps.upgrades.iter()).enumerate() {
1171 info!("Upgrade: slot:{}, {:?}", image_num, upgrade);
1172 if !verify_image(flash, &image.slots[0],
1173 match upgrade {
1174 UpgradeInfo::Upgraded => &image.upgrades,
1175 UpgradeInfo::Held => &image.primaries,
1176 }) {
1177 error!("Failed to upgrade properly: image: {}, upgrade: {:?}", image_num, upgrade);
1178 return true;
1179 }
1180 }
1181
1182 false
1183 }
1184
1185 /// Verify that at least one of the trailers of the images have the
1186 /// specified values.
verify_trailers_loose(&self, flash: &SimMultiFlash, slot: usize, magic: Option<u8>, image_ok: Option<u8>, copy_done: Option<u8>) -> bool1187 fn verify_trailers_loose(&self, flash: &SimMultiFlash, slot: usize,
1188 magic: Option<u8>, image_ok: Option<u8>,
1189 copy_done: Option<u8>) -> bool {
1190 self.images.iter().any(|image| {
1191 verify_trailer(flash, &image.slots[slot],
1192 magic, image_ok, copy_done)
1193 })
1194 }
1195
1196 /// Verify that the trailers of the images have the specified
1197 /// values.
verify_trailers(&self, flash: &SimMultiFlash, slot: usize, magic: Option<u8>, image_ok: Option<u8>, copy_done: Option<u8>) -> bool1198 fn verify_trailers(&self, flash: &SimMultiFlash, slot: usize,
1199 magic: Option<u8>, image_ok: Option<u8>,
1200 copy_done: Option<u8>) -> bool {
1201 self.images.iter().all(|image| {
1202 verify_trailer(flash, &image.slots[slot],
1203 magic, image_ok, copy_done)
1204 })
1205 }
1206
1207 /// Mark each of the images for permanent upgrade.
mark_permanent_upgrades(&self, flash: &mut SimMultiFlash, slot: usize)1208 fn mark_permanent_upgrades(&self, flash: &mut SimMultiFlash, slot: usize) {
1209 for image in &self.images {
1210 mark_permanent_upgrade(flash, &image.slots[slot]);
1211 }
1212 }
1213
1214 /// Mark each of the images for permanent upgrade.
mark_upgrades(&self, flash: &mut SimMultiFlash, slot: usize)1215 fn mark_upgrades(&self, flash: &mut SimMultiFlash, slot: usize) {
1216 for image in &self.images {
1217 mark_upgrade(flash, &image.slots[slot]);
1218 }
1219 }
1220
1221 /// Dump out the flash image(s) to one or more files for debugging
1222 /// purposes. The names will be written as either "{prefix}.mcubin" or
1223 /// "{prefix}-001.mcubin" depending on how many images there are.
debug_dump(&self, prefix: &str)1224 pub fn debug_dump(&self, prefix: &str) {
1225 for (id, fdev) in &self.flash {
1226 let name = if self.flash.len() == 1 {
1227 format!("{}.mcubin", prefix)
1228 } else {
1229 format!("{}-{:>0}.mcubin", prefix, id)
1230 };
1231 fdev.write_file(&name).unwrap();
1232 }
1233 }
1234 }
1235
1236 /// Show the flash layout.
1237 #[allow(dead_code)]
show_flash(flash: &dyn Flash)1238 fn show_flash(flash: &dyn Flash) {
1239 println!("---- Flash configuration ----");
1240 for sector in flash.sector_iter() {
1241 println!(" {:3}: 0x{:08x}, 0x{:08x}",
1242 sector.num, sector.base, sector.size);
1243 }
1244 println!();
1245 }
1246
1247 /// Install a "program" into the given image. This fakes the image header, or at least all of the
1248 /// fields used by the given code. Returns a copy of the image that was written.
install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: usize, deps: &dyn Depender, bad_sig: bool) -> ImageData1249 fn install_image(flash: &mut SimMultiFlash, slot: &SlotInfo, len: usize,
1250 deps: &dyn Depender, bad_sig: bool) -> ImageData {
1251 let offset = slot.base_off;
1252 let slot_len = slot.len;
1253 let dev_id = slot.dev_id;
1254
1255 let mut tlv: Box<dyn ManifestGen> = Box::new(make_tlv());
1256
1257 // Add the dependencies early to the tlv.
1258 for dep in deps.my_deps(offset, slot.index) {
1259 tlv.add_dependency(deps.other_id(), &dep);
1260 }
1261
1262 const HDR_SIZE: usize = 32;
1263
1264 // Generate a boot header. Note that the size doesn't include the header.
1265 let header = ImageHeader {
1266 magic: tlv.get_magic(),
1267 load_addr: 0,
1268 hdr_size: HDR_SIZE as u16,
1269 protect_tlv_size: tlv.protect_size(),
1270 img_size: len as u32,
1271 flags: tlv.get_flags(),
1272 ver: deps.my_version(offset, slot.index),
1273 _pad2: 0,
1274 };
1275
1276 let mut b_header = [0; HDR_SIZE];
1277 b_header[..32].clone_from_slice(header.as_raw());
1278 assert_eq!(b_header.len(), HDR_SIZE);
1279
1280 tlv.add_bytes(&b_header);
1281
1282 // The core of the image itself is just pseudorandom data.
1283 let mut b_img = vec![0; len];
1284 splat(&mut b_img, offset);
1285
1286 // Add some information at the start of the payload to make it easier
1287 // to see what it is. This will fail if the image itself is too small.
1288 {
1289 let mut wr = Cursor::new(&mut b_img);
1290 writeln!(&mut wr, "offset: {:#x}, dev_id: {:#x}, slot_info: {:?}",
1291 offset, dev_id, slot).unwrap();
1292 writeln!(&mut wr, "version: {:?}", deps.my_version(offset, slot.index)).unwrap();
1293 }
1294
1295 // TLV signatures work over plain image
1296 tlv.add_bytes(&b_img);
1297
1298 // Generate encrypted images
1299 let flag = TlvFlags::ENCRYPTED_AES128 as u32 | TlvFlags::ENCRYPTED_AES256 as u32;
1300 let is_encrypted = (tlv.get_flags() & flag) != 0;
1301 let mut b_encimg = vec![];
1302 if is_encrypted {
1303 let flag = TlvFlags::ENCRYPTED_AES256 as u32;
1304 let aes256 = (tlv.get_flags() & flag) == flag;
1305 tlv.generate_enc_key();
1306 let enc_key = tlv.get_enc_key();
1307 let nonce = GenericArray::from_slice(&[0; 16]);
1308 b_encimg = b_img.clone();
1309 if aes256 {
1310 let key: &GenericArray<u8, U32> = GenericArray::from_slice(enc_key.as_slice());
1311 let mut cipher = Aes256Ctr::new(&key, &nonce);
1312 cipher.apply_keystream(&mut b_encimg);
1313 } else {
1314 let key: &GenericArray<u8, U16> = GenericArray::from_slice(enc_key.as_slice());
1315 let mut cipher = Aes128Ctr::new(&key, &nonce);
1316 cipher.apply_keystream(&mut b_encimg);
1317 }
1318 }
1319
1320 // Build the TLV itself.
1321 if bad_sig {
1322 tlv.corrupt_sig();
1323 }
1324 let mut b_tlv = tlv.make_tlv();
1325
1326 let dev = flash.get_mut(&dev_id).unwrap();
1327
1328 let mut buf = vec![];
1329 buf.append(&mut b_header.to_vec());
1330 buf.append(&mut b_img);
1331 buf.append(&mut b_tlv.clone());
1332
1333 // Pad the buffer to a multiple of the flash alignment.
1334 let align = dev.align();
1335 while buf.len() % align != 0 {
1336 buf.push(dev.erased_val());
1337 }
1338
1339 let mut encbuf = vec![];
1340 if is_encrypted {
1341 encbuf.append(&mut b_header.to_vec());
1342 encbuf.append(&mut b_encimg);
1343 encbuf.append(&mut b_tlv);
1344
1345 while encbuf.len() % align != 0 {
1346 encbuf.push(dev.erased_val());
1347 }
1348 }
1349
1350 // Since images are always non-encrypted in the primary slot, we first write
1351 // an encrypted image, re-read to use for verification, erase + flash
1352 // un-encrypted. In the secondary slot the image is written un-encrypted,
1353 // and if encryption is requested, it follows an erase + flash encrypted.
1354
1355 if slot.index == 0 {
1356 let enc_copy: Option<Vec<u8>>;
1357
1358 if is_encrypted {
1359 dev.write(offset, &encbuf).unwrap();
1360
1361 let mut enc = vec![0u8; encbuf.len()];
1362 dev.read(offset, &mut enc).unwrap();
1363
1364 enc_copy = Some(enc);
1365
1366 dev.erase(offset, slot_len).unwrap();
1367 } else {
1368 enc_copy = None;
1369 }
1370
1371 dev.write(offset, &buf).unwrap();
1372
1373 let mut copy = vec![0u8; buf.len()];
1374 dev.read(offset, &mut copy).unwrap();
1375
1376 ImageData {
1377 plain: copy,
1378 cipher: enc_copy,
1379 }
1380 } else {
1381
1382 dev.write(offset, &buf).unwrap();
1383
1384 let mut copy = vec![0u8; buf.len()];
1385 dev.read(offset, &mut copy).unwrap();
1386
1387 let enc_copy: Option<Vec<u8>>;
1388
1389 if is_encrypted {
1390 dev.erase(offset, slot_len).unwrap();
1391
1392 dev.write(offset, &encbuf).unwrap();
1393
1394 let mut enc = vec![0u8; encbuf.len()];
1395 dev.read(offset, &mut enc).unwrap();
1396
1397 enc_copy = Some(enc);
1398 } else {
1399 enc_copy = None;
1400 }
1401
1402 ImageData {
1403 plain: copy,
1404 cipher: enc_copy,
1405 }
1406 }
1407 }
1408
1409 /// Install no image. This is used when no upgrade happens.
install_no_image() -> ImageData1410 fn install_no_image() -> ImageData {
1411 ImageData {
1412 plain: vec![],
1413 cipher: None,
1414 }
1415 }
1416
make_tlv() -> TlvGen1417 fn make_tlv() -> TlvGen {
1418 if Caps::EcdsaP224.present() {
1419 panic!("Ecdsa P224 not supported in Simulator");
1420 }
1421 let mut aes_key_size = 128;
1422 if Caps::Aes256.present() {
1423 aes_key_size = 256;
1424 }
1425
1426 if Caps::EncKw.present() {
1427 if Caps::RSA2048.present() {
1428 TlvGen::new_rsa_kw(aes_key_size)
1429 } else if Caps::EcdsaP256.present() {
1430 TlvGen::new_ecdsa_kw(aes_key_size)
1431 } else {
1432 TlvGen::new_enc_kw(aes_key_size)
1433 }
1434 } else if Caps::EncRsa.present() {
1435 if Caps::RSA2048.present() {
1436 TlvGen::new_sig_enc_rsa(aes_key_size)
1437 } else {
1438 TlvGen::new_enc_rsa(aes_key_size)
1439 }
1440 } else if Caps::EncEc256.present() {
1441 if Caps::EcdsaP256.present() {
1442 TlvGen::new_ecdsa_ecies_p256(aes_key_size)
1443 } else {
1444 TlvGen::new_ecies_p256(aes_key_size)
1445 }
1446 } else if Caps::EncX25519.present() {
1447 if Caps::Ed25519.present() {
1448 TlvGen::new_ed25519_ecies_x25519(aes_key_size)
1449 } else {
1450 TlvGen::new_ecies_x25519(aes_key_size)
1451 }
1452 } else {
1453 // The non-encrypted configuration.
1454 if Caps::RSA2048.present() {
1455 TlvGen::new_rsa_pss()
1456 } else if Caps::RSA3072.present() {
1457 TlvGen::new_rsa3072_pss()
1458 } else if Caps::EcdsaP256.present() {
1459 TlvGen::new_ecdsa()
1460 } else if Caps::Ed25519.present() {
1461 TlvGen::new_ed25519()
1462 } else {
1463 TlvGen::new_hash_only()
1464 }
1465 }
1466 }
1467
1468 impl ImageData {
1469 /// Find the image contents for the given slot. This assumes that slot 0
1470 /// is unencrypted, and slot 1 is encrypted.
find(&self, slot: usize) -> &Vec<u8>1471 fn find(&self, slot: usize) -> &Vec<u8> {
1472 let encrypted = Caps::EncRsa.present() || Caps::EncKw.present() ||
1473 Caps::EncEc256.present() || Caps::EncX25519.present();
1474 match (encrypted, slot) {
1475 (false, _) => &self.plain,
1476 (true, 0) => &self.plain,
1477 (true, 1) => self.cipher.as_ref().expect("Invalid image"),
1478 _ => panic!("Invalid slot requested"),
1479 }
1480 }
1481 }
1482
1483 /// Verify that given image is present in the flash at the given offset.
verify_image(flash: &SimMultiFlash, slot: &SlotInfo, images: &ImageData) -> bool1484 fn verify_image(flash: &SimMultiFlash, slot: &SlotInfo, images: &ImageData) -> bool {
1485 let image = images.find(slot.index);
1486 let buf = image.as_slice();
1487 let dev_id = slot.dev_id;
1488
1489 let mut copy = vec![0u8; buf.len()];
1490 let offset = slot.base_off;
1491 let dev = flash.get(&dev_id).unwrap();
1492 dev.read(offset, &mut copy).unwrap();
1493
1494 if buf != ©[..] {
1495 for i in 0 .. buf.len() {
1496 if buf[i] != copy[i] {
1497 info!("First failure for slot{} at {:#x} ({:#x} within) {:#x}!={:#x}",
1498 slot.index, offset + i, i, buf[i], copy[i]);
1499 break;
1500 }
1501 }
1502 false
1503 } else {
1504 true
1505 }
1506 }
1507
verify_trailer(flash: &SimMultiFlash, slot: &SlotInfo, magic: Option<u8>, image_ok: Option<u8>, copy_done: Option<u8>) -> bool1508 fn verify_trailer(flash: &SimMultiFlash, slot: &SlotInfo,
1509 magic: Option<u8>, image_ok: Option<u8>,
1510 copy_done: Option<u8>) -> bool {
1511 if Caps::OverwriteUpgrade.present() {
1512 return true;
1513 }
1514
1515 let offset = slot.trailer_off + c::boot_max_align();
1516 let dev_id = slot.dev_id;
1517 let mut copy = vec![0u8; c::boot_magic_sz() + c::boot_max_align() * 3];
1518 let mut failed = false;
1519
1520 let dev = flash.get(&dev_id).unwrap();
1521 let erased_val = dev.erased_val();
1522 dev.read(offset, &mut copy).unwrap();
1523
1524 failed |= match magic {
1525 Some(v) => {
1526 if v == 1 && ©[24..] != MAGIC {
1527 warn!("\"magic\" mismatch at {:#x}", offset);
1528 true
1529 } else if v == 3 {
1530 let expected = [erased_val; 16];
1531 if copy[24..] != expected {
1532 warn!("\"magic\" mismatch at {:#x}", offset);
1533 true
1534 } else {
1535 false
1536 }
1537 } else {
1538 false
1539 }
1540 },
1541 None => false,
1542 };
1543
1544 failed |= match image_ok {
1545 Some(v) => {
1546 if (v == 1 && copy[16] != v) || (v == 3 && copy[16] != erased_val) {
1547 warn!("\"image_ok\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[8]);
1548 true
1549 } else {
1550 false
1551 }
1552 },
1553 None => false,
1554 };
1555
1556 failed |= match copy_done {
1557 Some(v) => {
1558 if (v == 1 && copy[8] != v) || (v == 3 && copy[8] != erased_val) {
1559 warn!("\"copy_done\" mismatch at {:#x} v={} val={:#x}", offset, v, copy[0]);
1560 true
1561 } else {
1562 false
1563 }
1564 },
1565 None => false,
1566 };
1567
1568 !failed
1569 }
1570
1571 /// Install a partition table. This is a simplified partition table that
1572 /// we write at the beginning of flash so make it easier for external tools
1573 /// to analyze these images.
install_ptable(flash: &mut SimMultiFlash, areadesc: &AreaDesc)1574 fn install_ptable(flash: &mut SimMultiFlash, areadesc: &AreaDesc) {
1575 let ids: HashSet<u8> = areadesc.iter_areas().map(|area| area.device_id).collect();
1576 for &id in &ids {
1577 // If there are any partitions in this device that start at 0, and
1578 // aren't marked as the BootLoader partition, avoid adding the
1579 // partition table. This makes it harder to view the image, but
1580 // avoids messing up images already written.
1581 let skip_ptable = areadesc
1582 .iter_areas()
1583 .any(|area| {
1584 area.device_id == id &&
1585 area.off == 0 &&
1586 area.flash_id != FlashId::BootLoader
1587 });
1588 if skip_ptable {
1589 if log_enabled!(Info) {
1590 let special: Vec<FlashId> = areadesc.iter_areas()
1591 .filter(|area| area.device_id == id && area.off == 0)
1592 .map(|area| area.flash_id)
1593 .collect();
1594 info!("Skipping partition table: {:?}", special);
1595 }
1596 break;
1597 }
1598
1599 let mut buf: Vec<u8> = vec![];
1600 write!(&mut buf, "mcuboot\0").unwrap();
1601
1602 // Iterate through all of the partitions in that device, and encode
1603 // into the table.
1604 let count = areadesc.iter_areas().filter(|area| area.device_id == id).count();
1605 buf.write_u32::<LittleEndian>(count as u32).unwrap();
1606
1607 for area in areadesc.iter_areas().filter(|area| area.device_id == id) {
1608 buf.write_u32::<LittleEndian>(area.flash_id as u32).unwrap();
1609 buf.write_u32::<LittleEndian>(area.off).unwrap();
1610 buf.write_u32::<LittleEndian>(area.size).unwrap();
1611 buf.write_u32::<LittleEndian>(0).unwrap();
1612 }
1613
1614 let dev = flash.get_mut(&id).unwrap();
1615
1616 // Pad to alignment.
1617 while buf.len() % dev.align() != 0 {
1618 buf.push(0);
1619 }
1620
1621 dev.write(0, &buf).unwrap();
1622 }
1623 }
1624
1625 /// The image header
1626 #[repr(C)]
1627 #[derive(Debug)]
1628 pub struct ImageHeader {
1629 magic: u32,
1630 load_addr: u32,
1631 hdr_size: u16,
1632 protect_tlv_size: u16,
1633 img_size: u32,
1634 flags: u32,
1635 ver: ImageVersion,
1636 _pad2: u32,
1637 }
1638
1639 impl AsRaw for ImageHeader {}
1640
1641 #[repr(C)]
1642 #[derive(Clone, Debug)]
1643 pub struct ImageVersion {
1644 pub major: u8,
1645 pub minor: u8,
1646 pub revision: u16,
1647 pub build_num: u32,
1648 }
1649
1650 #[derive(Clone, Debug)]
1651 pub struct SlotInfo {
1652 pub base_off: usize,
1653 pub trailer_off: usize,
1654 pub len: usize,
1655 // Which slot within this device.
1656 pub index: usize,
1657 pub dev_id: u8,
1658 }
1659
1660 const MAGIC: &[u8] = &[0x77, 0xc2, 0x95, 0xf3,
1661 0x60, 0xd2, 0xef, 0x7f,
1662 0x35, 0x52, 0x50, 0x0f,
1663 0x2c, 0xb6, 0x79, 0x80];
1664
1665 // Replicates defines found in bootutil.h
1666 const BOOT_MAGIC_GOOD: Option<u8> = Some(1);
1667 const BOOT_MAGIC_UNSET: Option<u8> = Some(3);
1668
1669 const BOOT_FLAG_SET: Option<u8> = Some(1);
1670 const BOOT_FLAG_UNSET: Option<u8> = Some(3);
1671
1672 /// Write out the magic so that the loader tries doing an upgrade.
mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo)1673 pub fn mark_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
1674 let dev = flash.get_mut(&slot.dev_id).unwrap();
1675 let align = dev.align();
1676 let offset = slot.trailer_off + c::boot_max_align() * 4;
1677 if offset % align != 0 || MAGIC.len() % align != 0 {
1678 // The write size is larger than the magic value. Fill a buffer
1679 // with the erased value, put the MAGIC in it, and write it in its
1680 // entirety.
1681 let mut buf = vec![dev.erased_val(); align];
1682 buf[(offset % align)..].copy_from_slice(MAGIC);
1683 dev.write(offset - (offset % align), &buf).unwrap();
1684 } else {
1685 dev.write(offset, MAGIC).unwrap();
1686 }
1687 }
1688
1689 /// Writes the image_ok flag which, guess what, tells the bootloader
1690 /// the this image is ok (not a test, and no revert is to be performed).
mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo)1691 fn mark_permanent_upgrade(flash: &mut SimMultiFlash, slot: &SlotInfo) {
1692 // Overwrite mode always is permanent, and only the magic is used in
1693 // the trailer. To avoid problems with large write sizes, don't try to
1694 // set anything in this case.
1695 if Caps::OverwriteUpgrade.present() {
1696 return;
1697 }
1698
1699 let dev = flash.get_mut(&slot.dev_id).unwrap();
1700 let mut ok = [dev.erased_val(); 8];
1701 ok[0] = 1u8;
1702 let off = slot.trailer_off + c::boot_max_align() * 3;
1703 let align = dev.align();
1704 dev.write(off, &ok[..align]).unwrap();
1705 }
1706
1707 // Drop some pseudo-random gibberish onto the data.
splat(data: &mut [u8], seed: usize)1708 fn splat(data: &mut [u8], seed: usize) {
1709 let mut seed_block = [0u8; 16];
1710 let mut buf = Cursor::new(&mut seed_block[..]);
1711 buf.write_u32::<LittleEndian>(0x135782ea).unwrap();
1712 buf.write_u32::<LittleEndian>(0x92184728).unwrap();
1713 buf.write_u32::<LittleEndian>(data.len() as u32).unwrap();
1714 buf.write_u32::<LittleEndian>(seed as u32).unwrap();
1715 let mut rng: SmallRng = SeedableRng::from_seed(seed_block);
1716 rng.fill_bytes(data);
1717 }
1718
1719 /// Return a read-only view into the raw bytes of this object
1720 trait AsRaw : Sized {
as_raw(&self) -> &[u8]1721 fn as_raw(&self) -> &[u8] {
1722 unsafe { slice::from_raw_parts(self as *const _ as *const u8,
1723 mem::size_of::<Self>()) }
1724 }
1725 }
1726
show_sizes()1727 pub fn show_sizes() {
1728 // This isn't panic safe.
1729 for min in &[1, 2, 4, 8] {
1730 let msize = c::boot_trailer_sz(*min);
1731 println!("{:2}: {} (0x{:x})", min, msize, msize);
1732 }
1733 }
1734
1735 #[cfg(not(feature = "large-write"))]
test_alignments() -> &'static [usize]1736 fn test_alignments() -> &'static [usize] {
1737 &[1, 2, 4, 8]
1738 }
1739
1740 #[cfg(feature = "large-write")]
test_alignments() -> &'static [usize]1741 fn test_alignments() -> &'static [usize] {
1742 &[1, 2, 4, 8, 128, 512]
1743 }
1744