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 != &copy[..] {
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 && &copy[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