diff --git a/crates/runner-opentitan/src/board/crypto.rs b/crates/runner-opentitan/src/board/crypto.rs index d8bd3dc75..83229edab 100644 --- a/crates/runner-opentitan/src/board/crypto.rs +++ b/crates/runner-opentitan/src/board/crypto.rs @@ -16,7 +16,7 @@ use wasefire_board_api::crypto; use wasefire_error::{Code, Error}; mod aes; -mod ecdh; +pub mod ecdh; mod ecdsa; #[cfg(feature = "ed25519")] mod ed25519; diff --git a/crates/runner-opentitan/src/board/crypto/ecdh.rs b/crates/runner-opentitan/src/board/crypto/ecdh.rs index 24be089f7..09eadcd13 100644 --- a/crates/runner-opentitan/src/board/crypto/ecdh.rs +++ b/crates/runner-opentitan/src/board/crypto/ecdh.rs @@ -90,7 +90,7 @@ impl Api<32> for Impl { key[.. 32].copy_from_slice(y); key[32 ..].copy_from_slice(x); key.reverse(); - public.checksum = 0; + public.checksum = unsafe { public.borrow()? }.checksum(); Ok(()) } @@ -107,6 +107,24 @@ impl Api<32> for Impl { } } +#[cfg(feature = "test-vendor")] +pub fn syscall( + memory: impl wasefire_board_api::applet::Memory, x: u32, y: u32, z: u32, +) -> Result { + match (x, y, z) { + // Update checksum of private key. + (1, ptr, 0) => { + let key = memory.get_mut(ptr, core::mem::size_of::() as u32)?; + let key = try_from_bytes_mut::(key)?; + key.checksum = unsafe { key.borrow()? }.checksum(); + let key = &mut key.public; + key.checksum = unsafe { key.borrow()? }.checksum(); + Ok(0) + } + _ => Err(wasefire_board_api::Failure::TRAP), + } +} + #[derive(Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] #[repr(C)] struct Public { diff --git a/crates/runner-opentitan/src/board/crypto/ecdsa.rs b/crates/runner-opentitan/src/board/crypto/ecdsa.rs index 36a183bc2..4e32160ce 100644 --- a/crates/runner-opentitan/src/board/crypto/ecdsa.rs +++ b/crates/runner-opentitan/src/board/crypto/ecdsa.rs @@ -114,7 +114,7 @@ impl Api<32> for Impl { key[.. 32].copy_from_slice(y); key[32 ..].copy_from_slice(x); key.reverse(); - public.checksum = 0; + public.checksum = unsafe { public.borrow()? }.checksum(); Ok(()) } } diff --git a/crates/runner-opentitan/src/board/vendor.rs b/crates/runner-opentitan/src/board/vendor.rs index 652328efc..62cde96a0 100644 --- a/crates/runner-opentitan/src/board/vendor.rs +++ b/crates/runner-opentitan/src/board/vendor.rs @@ -39,6 +39,7 @@ impl Api for Impl { let push = |event| state.events.push(Event(event).into()); syscall_test::syscall(memory, handlers, push, x2, x3, x4) }), + (0x80000001, x, y, z) => crate::board::crypto::ecdh::syscall(memory, x, y, z), _ => Err(Failure::TRAP), } } diff --git a/crates/runner-opentitan/src/crypto/common.rs b/crates/runner-opentitan/src/crypto/common.rs index fc4fd80ed..1bf6a88eb 100644 --- a/crates/runner-opentitan/src/crypto/common.rs +++ b/crates/runner-opentitan/src/crypto/common.rs @@ -284,6 +284,10 @@ impl UnblindedKey { unsafe { core::slice::from_raw_parts(self.key, self.key_length / 4) } } + pub fn checksum(&self) -> u32 { + unsafe { integrity_unblinded_checksum(self) } + } + fn layout(key_length: usize) -> Result { Layout::from_size_align(key_length, 4).map_err(|_| Error::user(Code::InvalidArgument)) } @@ -337,6 +341,11 @@ impl BlindedKey { unsafe { core::slice::from_raw_parts(self.keyblob, self.keyblob_length / 4) } } + #[cfg(feature = "test-vendor")] + pub fn checksum(&self) -> u32 { + unsafe { integrity_blinded_checksum(self) } + } + fn layout(keyblob_length: usize) -> Result { Layout::from_size_align(keyblob_length, 4).map_err(|_| Error::user(Code::InvalidArgument)) } @@ -377,4 +386,7 @@ unsafe extern "C" { fn otcrypto_import_blinded_key( share0: ConstWord32Buf, share1: ConstWord32Buf, key: *mut BlindedKey, ) -> i32; + fn integrity_unblinded_checksum(key: *const UnblindedKey) -> u32; + #[cfg(feature = "test-vendor")] + fn integrity_blinded_checksum(key: *const BlindedKey) -> u32; } diff --git a/crates/runner-opentitan/src/error.rs b/crates/runner-opentitan/src/error.rs index bff996e0b..08457bc84 100644 --- a/crates/runner-opentitan/src/error.rs +++ b/crates/runner-opentitan/src/error.rs @@ -42,5 +42,5 @@ pub fn unwrap_status(mut x: i32) -> Result { #[cfg(false)] #[unsafe(no_mangle)] extern "C" fn wasefire_debug_mark(mark: i32) { - wasefire_logger::error!("DEBUG MARK {}", mark); + wasefire_logger::error!("DEBUG MARK {:08x} {}", mark, mark); } diff --git a/examples/rust/ecdh_test/src/lib.rs b/examples/rust/ecdh_test/src/lib.rs index b5fd4683f..d1739b31b 100644 --- a/examples/rust/ecdh_test/src/lib.rs +++ b/examples/rust/ecdh_test/src/lib.rs @@ -17,6 +17,7 @@ #![no_std] wasefire::applet!(); +use alloc::borrow::Cow; use alloc::vec; use ecdh_vectors::{P256_VECTORS, P384_VECTORS, Vector}; @@ -61,11 +62,15 @@ fn test(name: &str, vectors: &[Vector]) { } for &Vector { tc_id, private, otprivate, public_x, public_y, shared } in vectors { debug!("- {tc_id}"); - let private = match () { - () if cfg!(feature = "runner-opentitan") => otprivate, - _ => private, + let private: Cow<[u8]> = match () { + () if cfg!(feature = "runner-opentitan") => { + let mut private = otprivate.to_vec(); + unsafe { vendor::syscall(0x80000001, 1, private.as_mut_ptr().addr(), 0) }.unwrap(); + private.into() + } + _ => private.into(), }; - let private = Private::::import_testonly(private).unwrap(); + let private = Private::::import_testonly(&private).unwrap(); let public = Public::::import(public_x, public_y).unwrap(); let shared_ = Shared::::new(&private, &public).unwrap(); let mut actual = vec![0; C::SIZE];