From ebd06827d09aca71093d585070aac9ae65abb5c7 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 6 Mar 2024 18:55:05 -0500 Subject: [PATCH] improved glitch resistance for starting post boot --- application_processor/src/boot.rs | 120 ++++++++++++------------------ application_processor/src/main.rs | 13 ++-- component/src/main.rs | 21 +++--- design_macros/Cargo.lock | 67 +++++++++++++++++ 4 files changed, 130 insertions(+), 91 deletions(-) diff --git a/application_processor/src/boot.rs b/application_processor/src/boot.rs index e8e32ee..5febc03 100644 --- a/application_processor/src/boot.rs +++ b/application_processor/src/boot.rs @@ -28,6 +28,7 @@ use crate::ectf_params::{ COMPONENT_KEYS }; use crate::ap_driver::ApDriver; +use crate::post_boot; const COMPONENT_COUNT: usize = 2; @@ -45,37 +46,13 @@ impl ComponentBootState { } } -#[inline(always)] -fn boot_send_m1(driver: &mut ApDriver, state: &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError> { - for component in state { - // send enc(m1 || cid || ra) - let ap_nonce = driver.gen_nonce(); - let message = BootMessageStart { - m: MessageStage::M1, - component_id: component.component_id, - nonce: ap_nonce, - }; - - let req = StartProtocolMessage::Boot( - EncryptedMessage::new_encrypted(message, &BOOT_CR_KEY, driver.gen_bytes())?, - ); - - driver.send_struct(component.i2c_addr(), req)?; - - // TODO: determine when this should be true, this might not be true if component answers with error - component.protocol_in_progress = true; - - component.expected_reply_nonce = ap_nonce + 1; - } - - Ok(()) -} - // sends final message telling components to boot -fn boot_send_m3( - driver: &mut ApDriver, +fn send_m3_and_boot( + driver_option: &mut Option, state: &mut [ComponentBootState; COMPONENT_COUNT], ) -> Result<(), ApError> { + let driver = driver_option.as_mut().unwrap(); + for component in state { // send enc(m3 || cid || rb + 1 || signature) let message = BootMessageFinalize { @@ -87,31 +64,53 @@ fn boot_send_m3( let signed_message = SignedMessage::new_signed(message, &AP_PRIVKEY)?; let enc_message = EncryptedMessage::new_encrypted(signed_message, &BOOT_CR_KEY, driver.gen_bytes())?; - driver.send_struct(component.i2c_addr(), enc_message)?; + let mut encrypted_boot_message: EncryptedData = driver.send_and_receive_struct(component.i2c_addr(), enc_message)?; + // recieved encrypted boot message component.protocol_in_progress = false; + + let boot_message = decrypt(&mut encrypted_boot_message, &BOOT_DATA_ENC_KEY)?; + let boot_message = str::from_utf8(boot_message.as_slice())?; + + // Print boot message from component + // TODO: maybe only print these messages after both components have sent them back + uprintln_info!("0x{:x}>{}", component.component_id, boot_message); } - Ok(()) + uprintln_info!("AP>{}", AP_BOOT_MSG); + + post_boot::boot(driver_option.take().unwrap()); } -#[inline(always)] -fn boot_recv_m2_send_m3( - driver: &mut ApDriver, - state: &mut [ComponentBootState; COMPONENT_COUNT] -) -> Result<(), ApError> { +fn boot_components(driver_option: &mut Option, state: &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError> { + let driver = driver_option.as_mut().unwrap(); + + // verify components by sending m1 and verifiying their m2 response for component in state.iter_mut() { - let mut enc_response: EncryptedMessage> = driver.receive_struct(component.i2c_addr())?; + // send enc(m1 || cid || ra) + let ap_nonce = driver.gen_nonce(); + let message = BootMessageStart { + m: MessageStage::M1, + component_id: component.component_id, + nonce: ap_nonce, + }; + + let req = StartProtocolMessage::Boot( + EncryptedMessage::new_encrypted(message, &BOOT_CR_KEY, driver.gen_bytes())?, + ); + + let mut enc_response: EncryptedMessage> = + driver.send_and_receive_struct(component.i2c_addr(), req)?; + component.protocol_in_progress = true; // received enc(m2 || cid || bid || ra + 1 || rb || signature) let signed_response = enc_response.get_decrypted_data(&BOOT_CR_KEY)?; - let response: BootMessageComponentReply = postcard::from_bytes(&signed_response.message_data)?; // glitch protect these checks multi_if!( response.m == MessageStage::M2 && response.component_id == component.component_id - && response.start_nonce_plus_one == component.expected_reply_nonce, + && response.start_nonce_plus_one == ap_nonce + 1, (), { return Err(ApError::SuspiciousActivity) }, driver.get_chacha(), @@ -130,47 +129,21 @@ fn boot_recv_m2_send_m3( component.expected_reply_nonce = response.reply_nonce + 1; } - // verify components are using different build ids + // verify components are using different build ids then tell components to boot and boot check_or_error_jump_table!( state[0].key_index != state[1].key_index, - fn(&mut ApDriver, &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError>, - boot_send_m3, - (driver, state), + fn(&mut Option, &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError>, + send_m3_and_boot, + (driver_option, state), Err(ApError::SuspiciousActivity), driver.get_chacha(), ) } -#[inline(always)] -fn boot_recv_messages(driver: &mut ApDriver, state: &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError> { - for component in state { - let mut encrypted_boot_message: EncryptedData = driver.receive_struct(component.i2c_addr())?; - - let boot_message = decrypt(&mut encrypted_boot_message, &BOOT_DATA_ENC_KEY)?; - let boot_message = str::from_utf8(boot_message.as_slice())?; - - // Print boot message from component - // TODO: maybe only print these messages after both components have sent them back - uprintln_info!("0x{:x}>{}", component.component_id, boot_message); - } - - Ok(()) -} - -fn boot_components(driver: &mut ApDriver, state: &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError> { - boot_send_m1(driver, state)?; - boot_recv_m2_send_m3(driver, state)?; - boot_recv_messages(driver, state)?; - - // Print boot message - // This always needs to be printed when booting - uprintln_info!("AP>{}", AP_BOOT_MSG); - - Ok(()) -} - // Boot the components and board if the components validate -pub fn attempt_boot(driver: &mut ApDriver) -> Result<(), ApError> { +pub fn attempt_boot(driver_option: &mut Option) -> Result<(), ApError> { + let driver = driver_option.as_mut().unwrap(); + let mut flash_data = driver.get_flash_data(); if flash_data.components_len != COMPONENT_COUNT { // not enough components to boot @@ -185,13 +158,14 @@ pub fn attempt_boot(driver: &mut ApDriver) -> Result<(), ApError> { // make sure we are booting with distinct component ids (with glitch hardened check) let result = check_or_error_jump_table!( boot_state[0].component_id != boot_state[1].component_id, - fn(&mut ApDriver, &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError>, + fn(&mut Option, &mut [ComponentBootState; COMPONENT_COUNT]) -> Result<(), ApError>, boot_components, - (driver, &mut boot_state), + (driver_option, &mut boot_state), Err(ApError::SuspiciousActivity), driver.get_chacha(), ); + let driver = driver_option.as_mut().unwrap(); if let Err(err) = result { // send error message to components which were still expecting a message for component in boot_state { diff --git a/application_processor/src/main.rs b/application_processor/src/main.rs index c9f7687..939003c 100644 --- a/application_processor/src/main.rs +++ b/application_processor/src/main.rs @@ -64,8 +64,8 @@ fn main() -> ! { } let mut driver = ApDriver::new(); - driver.sleep(Duration::from_secs(1)); + let mut driver = Some(driver); uprintln_info!("Application Processor Started"); @@ -84,13 +84,10 @@ fn main() -> ! { uprintln_debug!("running command: {command}"); let result = match command { - "list" => list::scan_components(&mut driver), - "attest" => attest::attest(&mut driver), - "replace" => replace::replace(&mut driver), - "boot" => match boot::attempt_boot(&mut driver) { - Ok(()) => post_boot::boot(driver), - Err(err) => Err(err), - }, + "list" => list::scan_components(driver.as_mut().unwrap()), + "attest" => attest::attest(driver.as_mut().unwrap()), + "replace" => replace::replace(driver.as_mut().unwrap()), + "boot" => boot::attempt_boot(&mut driver), &_ => Err(ApError::InvalidCommand), }; diff --git a/component/src/main.rs b/component/src/main.rs index f1b1561..a69be5b 100644 --- a/component/src/main.rs +++ b/component/src/main.rs @@ -60,29 +60,28 @@ fn main() -> ! { } let mut driver = ComponentDriver::new(); - driver.sleep(Duration::from_secs(1)); + let mut driver = Some(driver); uprint_info!("Component Started"); led_on(Led::Green); loop { - let Ok(command) = driver.recv_struct() else { + let Ok(command) = driver.as_mut().unwrap().recv_struct() else { uprintln_error!("invalid command received"); continue; }; let result = match command { - StartProtocolMessage::ScanId => process_scan(&mut driver), - StartProtocolMessage::Attest => process_attest(&mut driver), - StartProtocolMessage::Boot(mut boot_data) => match process_boot(&mut driver, &mut boot_data) { - Ok(()) => post_boot::boot(driver), - Err(err) => Err(err), - }, + StartProtocolMessage::ScanId => process_scan(driver.as_mut().unwrap()), + StartProtocolMessage::Attest => process_attest(driver.as_mut().unwrap()), + StartProtocolMessage::Boot(mut boot_data) => process_boot(&mut driver, &mut boot_data), }; if let Err(error) = result { + let driver = driver.as_mut().unwrap(); + // FIXME: figure out how to handle this error // i2c state will be all messed up if this fails // FIXME: not all errors require sending component an error @@ -142,9 +141,11 @@ fn process_attest(driver: &mut ComponentDriver) -> Result<(), ComponentError> { } fn process_boot( - driver: &mut ComponentDriver, + driver_option: &mut Option, encrypted_message: &mut EncryptedMessage ) -> Result<(), ComponentError> { + let driver = driver_option.as_mut().unwrap(); + // received enc(m1 || cid || ra) let message = encrypted_message.get_decrypted_data(&BOOT_CR_KEY)?; @@ -186,5 +187,5 @@ fn process_boot( // reply with encrypted boot message driver.send_struct(encrypted_boot_message())?; - Ok(()) + post_boot::boot(driver_option.take().unwrap()); } diff --git a/design_macros/Cargo.lock b/design_macros/Cargo.lock index 88694b5..0c7fa17 100644 --- a/design_macros/Cargo.lock +++ b/design_macros/Cargo.lock @@ -2,14 +2,45 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "design_macros" version = "0.1.0" dependencies = [ + "proc-macro2", "quote", + "rand", "syn", ] +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro2" version = "1.0.78" @@ -28,6 +59,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "syn" version = "2.0.52" @@ -44,3 +105,9 @@ name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"