blob: 45624ede53f4f5d29049ddb9059321e20a306c1b [file] [log] [blame]
David Brownde7729e2017-01-09 10:41:35 -07001/// Interface wrappers to C API entering to the bootloader
2
3use area::AreaDesc;
David Brown2cbc4702017-07-06 14:18:58 -06004use simflash::Flash;
David Brownde7729e2017-01-09 10:41:35 -07005use libc;
David Brownbdb6db72017-07-06 10:14:37 -06006use api;
David Brown353610d2017-11-06 11:31:31 -07007use std::sync::Mutex;
8
9lazy_static! {
10 /// Mutex to lock the simulation. The C code for the bootloader uses
11 /// global variables, and is therefore non-reentrant.
12 static ref BOOT_LOCK: Mutex<()> = Mutex::new(());
13}
David Brownde7729e2017-01-09 10:41:35 -070014
15/// Invoke the bootloader on this flash device.
Fabio Utzig9b0ee902017-11-23 19:49:00 -020016pub fn boot_go(flash: &mut Flash, areadesc: &AreaDesc, counter: Option<&mut i32>,
17 align: u8, catch_asserts: bool) -> (i32, u8) {
David Brown353610d2017-11-06 11:31:31 -070018 let _lock = BOOT_LOCK.lock().unwrap();
19
David Brownee61c832017-11-06 11:13:25 -070020 unsafe {
21 api::set_flash(flash);
Fabio Utzig9b0ee902017-11-23 19:49:00 -020022 raw::c_catch_asserts = if catch_asserts { 1 } else { 0 };
23 raw::c_asserts = 0u8;
David Brown541860c2017-11-06 11:25:42 -070024 raw::sim_flash_align = align;
Fabio Utzigea0290b2018-08-09 14:23:01 -030025 raw::sim_flash_erased_val = flash.erased_val();
David Brownee61c832017-11-06 11:13:25 -070026 raw::flash_counter = match counter {
27 None => 0,
28 Some(ref c) => **c as libc::c_int
29 };
30 }
David Brownbdb6db72017-07-06 10:14:37 -060031 let result = unsafe { raw::invoke_boot_go(&areadesc.get_c() as *const _) as i32 };
Fabio Utzig9b0ee902017-11-23 19:49:00 -020032 let asserts = unsafe { raw::c_asserts };
David Brownee61c832017-11-06 11:13:25 -070033 unsafe {
34 counter.map(|c| *c = raw::flash_counter as i32);
35 api::clear_flash();
36 };
Fabio Utzig9b0ee902017-11-23 19:49:00 -020037 (result, asserts)
David Brownde7729e2017-01-09 10:41:35 -070038}
39
David Brown541860c2017-11-06 11:25:42 -070040pub fn boot_trailer_sz(align: u8) -> u32 {
41 unsafe { raw::boot_slots_trailer_sz(align) }
David Brownde7729e2017-01-09 10:41:35 -070042}
43
Fabio Utziga0bc9b52017-06-28 09:19:55 -030044pub fn boot_magic_sz() -> usize {
45 unsafe { raw::BOOT_MAGIC_SZ as usize }
46}
47
48pub fn boot_max_align() -> usize {
49 unsafe { raw::BOOT_MAX_ALIGN as usize }
50}
51
Fabio Utzig92be3fb2017-12-05 08:52:53 -020052pub fn ecdsa256_sign(privkey: &[u8], hash: &[u8]) -> Result<[u8; 64], &'static str> {
53 unsafe {
54 let mut signature: [u8; 64] = [0; 64];
55 if raw::ecdsa256_sign_(privkey.as_ptr(), hash.as_ptr(),
56 hash.len() as u32, signature.as_mut_ptr()) == 1 {
57 return Ok(signature);
58 }
59 return Err("Failed signature generation");
60 }
61}
62
Fabio Utzig1e48b912018-09-18 09:04:18 -030063pub fn rsa_oaep_encrypt(pubkey: &[u8], seckey: &[u8]) -> Result<[u8; 256], &'static str> {
64 unsafe {
65 let mut encbuf: [u8; 256] = [0; 256];
66 if raw::rsa_oaep_encrypt_(pubkey.as_ptr(), pubkey.len() as u32,
67 seckey.as_ptr(), seckey.len() as u32,
68 encbuf.as_mut_ptr()) == 0 {
69 return Ok(encbuf);
70 }
71 return Err("Failed to encrypt buffer");
72 }
73}
74
75pub fn kw_encrypt(kek: &[u8], seckey: &[u8]) -> Result<[u8; 24], &'static str> {
76 unsafe {
77 let mut encbuf = [0u8; 24];
78 if raw::kw_encrypt_(kek.as_ptr(), seckey.as_ptr(), encbuf.as_mut_ptr()) == 0 {
79 return Ok(encbuf);
80 }
81 return Err("Failed to encrypt buffer");
82 }
83}
84
David Brownde7729e2017-01-09 10:41:35 -070085mod raw {
86 use area::CAreaDesc;
87 use libc;
88
89 extern "C" {
90 // This generates a warning about `CAreaDesc` not being foreign safe. There doesn't appear to
91 // be any way to get rid of this warning. See https://github.com/rust-lang/rust/issues/34798
92 // for information and tracking.
David Brownbdb6db72017-07-06 10:14:37 -060093 pub fn invoke_boot_go(areadesc: *const CAreaDesc) -> libc::c_int;
David Brownde7729e2017-01-09 10:41:35 -070094 pub static mut flash_counter: libc::c_int;
Fabio Utzig9b0ee902017-11-23 19:49:00 -020095 pub static mut c_asserts: u8;
96 pub static mut c_catch_asserts: u8;
David Brownde7729e2017-01-09 10:41:35 -070097
98 pub static mut sim_flash_align: u8;
Fabio Utzigea0290b2018-08-09 14:23:01 -030099 pub static mut sim_flash_erased_val: u8;
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300100 pub fn boot_slots_trailer_sz(min_write_sz: u8) -> u32;
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300101
102 pub static BOOT_MAGIC_SZ: u32;
103 pub static BOOT_MAX_ALIGN: u32;
Fabio Utzig92be3fb2017-12-05 08:52:53 -0200104
105 pub fn ecdsa256_sign_(privkey: *const u8, hash: *const u8,
106 hash_len: libc::c_uint,
107 signature: *mut u8) -> libc::c_int;
Fabio Utzig1e48b912018-09-18 09:04:18 -0300108
109 pub fn rsa_oaep_encrypt_(pubkey: *const u8, pubkey_len: libc::c_uint,
110 seckey: *const u8, seckey_len: libc::c_uint,
111 encbuf: *mut u8) -> libc::c_int;
112
113 pub fn kw_encrypt_(kek: *const u8, seckey: *const u8,
114 encbuf: *mut u8) -> libc::c_int;
David Brownde7729e2017-01-09 10:41:35 -0700115 }
116}