diff --git a/Cargo.lock b/Cargo.lock index ab7528927..c5d5227bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1527,6 +1527,7 @@ dependencies = [ "root-keys", "sha2", "spinor", + "subtle", "susres", "ticktimer-server", "trng", @@ -2278,9 +2279,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "susres" diff --git a/services/pddb/Cargo.toml b/services/pddb/Cargo.toml index 099634370..97c4e6257 100644 --- a/services/pddb/Cargo.toml +++ b/services/pddb/Cargo.toml @@ -27,6 +27,7 @@ cipher = "0.3.0" bitfield = "0.13.2" aes-gcm-siv = "0.10.3" llio = {path="../llio"} +subtle = {version = "2.4.1", default-features = false} # passwords sha2 = {path = "../engine-sha512"} diff --git a/services/pddb/src/backend/hw.rs b/services/pddb/src/backend/hw.rs index a587a8faf..67bd64d3d 100644 --- a/services/pddb/src/backend/hw.rs +++ b/services/pddb/src/backend/hw.rs @@ -7,6 +7,7 @@ use aes::{Aes256, Block, BLOCK_SIZE}; use aes::cipher::{BlockDecrypt, BlockEncrypt, NewBlockCipher, generic_array::GenericArray}; use root_keys::api::AesRootkeyType; use spinor::SPINOR_BULK_ERASE_SIZE; +use subtle::ConstantTimeEq; use core::ops::{Deref, DerefMut}; use core::mem::size_of; @@ -1171,33 +1172,21 @@ impl PddbOs { let (kenc, kcom) = self.kcom_func(key.try_into().unwrap(), &nonce_comm); let cipher = Aes256GcmSiv::new(Key::from_slice(&kenc)); - match cipher.decrypt( + + // Attempt decryption. This is None on failure + let plaintext = cipher.decrypt( Nonce::from_slice(nonce), Payload { aad, msg: &ct_plus_mac, } - ) { - Ok(data) => { - assert!(data.len() == KCOM_CT_LEN, "authentication successful, but wrong amount of data was recovered"); - if kcom == key_comm_stored { - Some(data) - } else { - log::debug!("Key commitment failed to match on a reputed basis root block"); - None - } - }, - Err(e) => { - // do the commit check again at the same point, even if there is an error, for some semblance of constant time - // (of course the error messages leak information, if they are forced on) - if kcom == key_comm_stored { - log::trace!("Error decrypting page: {:?}", e); // sometimes this is totally "normal", like when we're testing for valid data. - None - } else { - log::trace!("Error decrypting page + commitment error: {:?}", e); - None - } - } + ).ok(); + + // Only return the plaintext if the stored key commitment agrees with the computed one + if kcom.ct_eq(&key_comm_stored).into() { + plaintext + } else { + None } } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 25022994d..324360e7d 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -166,11 +166,35 @@ fn main() -> Result<(), Box> { let kkey = args.nth(4); match task.as_deref() { Some("renode-image") => { - generate_app_menus(&vec!["ball".to_string()]); + let mut args = env::args(); + args.nth(1); + let mut pkgs = hw_pkgs.to_vec(); + let mut apps: Vec = args.collect(); + if apps.len() == 0 { // add the standard demo apps if none are specified + println!("No apps specified, adding default apps..."); + apps.push("ball".to_string()); + apps.push("repl".to_string()); + } + for app in &apps { + pkgs.push(app); + } + generate_app_menus(&apps); renode_image(false, &hw_pkgs, &[])? }, Some("renode-test") => { - generate_app_menus(&vec!["ball".to_string()]); + let mut args = env::args(); + args.nth(1); + let mut pkgs = hw_pkgs.to_vec(); + let mut apps: Vec = args.collect(); + if apps.len() == 0 { // add the standard demo apps if none are specified + println!("No apps specified, adding default apps..."); + apps.push("ball".to_string()); + apps.push("repl".to_string()); + } + for app in &apps { + pkgs.push(app); + } + generate_app_menus(&apps); renode_image(false, &cbtest_pkgs, &[])? }, Some("libstd-test") => {