blob: d623ef9fb2ef47dac15385e075713bcecbbfb57b [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001/// Interface wrappers to C API entering to the bootloader
2
David Brown65de6d12019-01-02 11:38:38 -07003use crate::area::AreaDesc;
Fabio Utzigafb2bc92018-11-19 16:11:52 -02004use simflash::SimFlashMap;
David Brown28215642019-01-02 11:42:39 -07005use lazy_static::lazy_static;
David Brownde7729e2017-01-09 10:41:35 -07006use libc;
David Brown65de6d12019-01-02 11:38:38 -07007use crate::api;
David Brown353610d2017-11-06 11:31:31 -07008use std::sync::Mutex;
9
10lazy_static! {
11 /// Mutex to lock the simulation. The C code for the bootloader uses
12 /// global variables, and is therefore non-reentrant.
13 static ref BOOT_LOCK: Mutex<()> = Mutex::new(());
14}
David Brownde7729e2017-01-09 10:41:35 -070015
16/// Invoke the bootloader on this flash device.
Fabio Utzigafb2bc92018-11-19 16:11:52 -020017pub fn boot_go(flashmap: &mut SimFlashMap, areadesc: &AreaDesc,
18 counter: Option<&mut i32>, catch_asserts: bool) -> (i32, u8) {
David Brown353610d2017-11-06 11:31:31 -070019 let _lock = BOOT_LOCK.lock().unwrap();
20
David Brownee61c832017-11-06 11:13:25 -070021 unsafe {
Fabio Utzigafb2bc92018-11-19 16:11:52 -020022 for (&dev_id, flash) in flashmap.iter_mut() {
23 api::set_flash(dev_id, flash);
24 }
Fabio Utzig9b0ee902017-11-23 19:49:00 -020025 raw::c_catch_asserts = if catch_asserts { 1 } else { 0 };
26 raw::c_asserts = 0u8;
David Brownee61c832017-11-06 11:13:25 -070027 raw::flash_counter = match counter {
28 None => 0,
29 Some(ref c) => **c as libc::c_int
30 };
31 }
David Brownbdb6db72017-07-06 10:14:37 -060032 let result = unsafe { raw::invoke_boot_go(&areadesc.get_c() as *const _) as i32 };
Fabio Utzig9b0ee902017-11-23 19:49:00 -020033 let asserts = unsafe { raw::c_asserts };
David Brownee61c832017-11-06 11:13:25 -070034 unsafe {
35 counter.map(|c| *c = raw::flash_counter as i32);
Fabio Utzigafb2bc92018-11-19 16:11:52 -020036 for (&dev_id, _) in flashmap {
37 api::clear_flash(dev_id);
38 }
David Brownee61c832017-11-06 11:13:25 -070039 };
Fabio Utzig9b0ee902017-11-23 19:49:00 -020040 (result, asserts)
David Brownde7729e2017-01-09 10:41:35 -070041}
42
David Brown541860c2017-11-06 11:25:42 -070043pub fn boot_trailer_sz(align: u8) -> u32 {
44 unsafe { raw::boot_slots_trailer_sz(align) }
David Brownde7729e2017-01-09 10:41:35 -070045}
46
Fabio Utziga0bc9b52017-06-28 09:19:55 -030047pub fn boot_magic_sz() -> usize {
48 unsafe { raw::BOOT_MAGIC_SZ as usize }
49}
50
51pub fn boot_max_align() -> usize {
52 unsafe { raw::BOOT_MAX_ALIGN as usize }
53}
54
Fabio Utzig92be3fb2017-12-05 08:52:53 -020055pub fn ecdsa256_sign(privkey: &[u8], hash: &[u8]) -> Result<[u8; 64], &'static str> {
56 unsafe {
57 let mut signature: [u8; 64] = [0; 64];
58 if raw::ecdsa256_sign_(privkey.as_ptr(), hash.as_ptr(),
59 hash.len() as u32, signature.as_mut_ptr()) == 1 {
60 return Ok(signature);
61 }
62 return Err("Failed signature generation");
63 }
64}
65
Fabio Utzig1e48b912018-09-18 09:04:18 -030066pub fn rsa_oaep_encrypt(pubkey: &[u8], seckey: &[u8]) -> Result<[u8; 256], &'static str> {
67 unsafe {
68 let mut encbuf: [u8; 256] = [0; 256];
69 if raw::rsa_oaep_encrypt_(pubkey.as_ptr(), pubkey.len() as u32,
70 seckey.as_ptr(), seckey.len() as u32,
71 encbuf.as_mut_ptr()) == 0 {
72 return Ok(encbuf);
73 }
74 return Err("Failed to encrypt buffer");
75 }
76}
77
78pub fn kw_encrypt(kek: &[u8], seckey: &[u8]) -> Result<[u8; 24], &'static str> {
79 unsafe {
80 let mut encbuf = [0u8; 24];
81 if raw::kw_encrypt_(kek.as_ptr(), seckey.as_ptr(), encbuf.as_mut_ptr()) == 0 {
82 return Ok(encbuf);
83 }
84 return Err("Failed to encrypt buffer");
85 }
86}
87
David Brownde7729e2017-01-09 10:41:35 -070088mod raw {
David Brown65de6d12019-01-02 11:38:38 -070089 use crate::area::CAreaDesc;
David Brownde7729e2017-01-09 10:41:35 -070090 use libc;
91
92 extern "C" {
93 // This generates a warning about `CAreaDesc` not being foreign safe. There doesn't appear to
94 // be any way to get rid of this warning. See https://github.com/rust-lang/rust/issues/34798
95 // for information and tracking.
David Brownbdb6db72017-07-06 10:14:37 -060096 pub fn invoke_boot_go(areadesc: *const CAreaDesc) -> libc::c_int;
David Brownde7729e2017-01-09 10:41:35 -070097 pub static mut flash_counter: libc::c_int;
Fabio Utzig9b0ee902017-11-23 19:49:00 -020098 pub static mut c_asserts: u8;
99 pub static mut c_catch_asserts: u8;
David Brownde7729e2017-01-09 10:41:35 -0700100
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300101 pub fn boot_slots_trailer_sz(min_write_sz: u8) -> u32;
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300102
103 pub static BOOT_MAGIC_SZ: u32;
104 pub static BOOT_MAX_ALIGN: u32;
Fabio Utzig92be3fb2017-12-05 08:52:53 -0200105
106 pub fn ecdsa256_sign_(privkey: *const u8, hash: *const u8,
107 hash_len: libc::c_uint,
108 signature: *mut u8) -> libc::c_int;
Fabio Utzig1e48b912018-09-18 09:04:18 -0300109
110 pub fn rsa_oaep_encrypt_(pubkey: *const u8, pubkey_len: libc::c_uint,
111 seckey: *const u8, seckey_len: libc::c_uint,
112 encbuf: *mut u8) -> libc::c_int;
113
114 pub fn kw_encrypt_(kek: *const u8, seckey: *const u8,
115 encbuf: *mut u8) -> libc::c_int;
David Brownde7729e2017-01-09 10:41:35 -0700116 }
117}