From 3c695be99661447edd7b0a7065cf14d66e67d877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hlusi=C4=8Dka?= Date: Tue, 20 Jan 2026 21:32:37 +0100 Subject: [PATCH] Implement Spectre site key derivation --- firmware2/Cargo.lock | 1 + firmware2/Cargo.toml | 1 + firmware2/src/ffi/crypto.rs | 69 ++++++++++++++++++++++++++++++++----- firmware2/src/ui/mod.rs | 1 - 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/firmware2/Cargo.lock b/firmware2/Cargo.lock index 6035a8a..7e6c16f 100644 --- a/firmware2/Cargo.lock +++ b/firmware2/Cargo.lock @@ -30,6 +30,7 @@ dependencies = [ "esp-rtos", "esp-storage", "gix", + "hmac", "i-slint-common", "indoc", "itertools 0.14.0", diff --git a/firmware2/Cargo.toml b/firmware2/Cargo.toml index 4c86812..e09a696 100644 --- a/firmware2/Cargo.toml +++ b/firmware2/Cargo.toml @@ -78,6 +78,7 @@ printf-compat = { version = "0.2.1", default-features = false } spectre-api-sys = { git = "https://github.com/Limeth/spectre-api-sys" } sha2 = { version = "0.10.9", default-features = false } password-hash = { path = "password-hash", default-features = false } +hmac = "0.12.1" # Crates for serial UART CLI embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] } diff --git a/firmware2/src/ffi/crypto.rs b/firmware2/src/ffi/crypto.rs index f59ccdf..3484a42 100644 --- a/firmware2/src/ffi/crypto.rs +++ b/firmware2/src/ffi/crypto.rs @@ -1,12 +1,20 @@ -use core::ffi::{c_char, c_int, c_size_t, c_uchar, c_ulonglong}; +use core::{ + cell::RefCell, + ffi::{c_char, c_int, c_size_t, c_uchar, c_ulonglong}, +}; +use embassy_sync::blocking_mutex::{self, raw::CriticalSectionRawMutex}; +use hmac::{ + Hmac, SimpleHmac, + digest::{FixedOutput, KeyInit, Update}, +}; use sha2::{ Digest, Sha256, digest::{consts::U32, generic_array::GenericArray}, }; use spectre_api_sys::{SpectreKeyPurpose, spectre_purpose_scope}; -use crate::PSRAM_ALLOCATOR; +use crate::{PSRAM_ALLOCATOR, SHA}; // Just a way to mark non-null pointers. // Rust's `NonNull` is for mutable pointers only. @@ -22,7 +30,7 @@ unsafe extern "C" fn __spre_crypto_hash_sha256( let data_out = &mut *(data_out as *mut GenericArray); let data_in = core::slice::from_raw_parts(data_in, data_in_len as usize); let mut digest = Sha256::new(); - digest.update(data_in); + Digest::update(&mut digest, data_in); digest.finalize_into_reset(data_out); } @@ -88,22 +96,56 @@ struct crypto_auth_hmacsha256_state { octx: crypto_hash_sha256_state, } +static HMAC: blocking_mutex::Mutex>>> = + blocking_mutex::Mutex::new(RefCell::new(None)); + #[unsafe(no_mangle)] unsafe extern "C" fn __spre_crypto_auth_hmacsha256_init( state: NonNullPtr<*mut crypto_auth_hmacsha256_state>, key: NonNullPtr<*const c_uchar>, - keylen: c_size_t, + key_len: c_size_t, ) -> c_int { - todo!() + let key: &[u8] = unsafe { core::slice::from_raw_parts(key, key_len) }; + // TODO: Hardware-accelerated hashing via the SHA peripheral. + // SHA.lock(|sha| { + // let sha = sha + // .borrow_mut() + // .as_mut() + // .expect("HMAC peripheral not initialized."); + + // sha. + // }); + HMAC.lock(|hmac| { + let mut hmac = hmac.borrow_mut(); + + if hmac.is_some() { + panic!("HMAC already initialized. Cannot handle multiple HMAC's at once."); + } + + *hmac = Some(Hmac::::new_from_slice(key).unwrap()); + }); + + 0 } #[unsafe(no_mangle)] unsafe extern "C" fn __spre_crypto_auth_hmacsha256_update( state: NonNullPtr<*mut crypto_auth_hmacsha256_state>, data_in: *const c_uchar, - inlen: c_ulonglong, + data_in_len: c_ulonglong, ) -> c_int { - todo!() + let data_in: &[u8] = unsafe { core::slice::from_raw_parts(data_in, data_in_len as usize) }; + + HMAC.lock(|hmac| { + let mut hmac = hmac.borrow_mut(); + let hmac = hmac + .as_mut() + .expect("HMAC must first be initialized before it is updated."); + + hmac.update(data_in); + }); + + 0 } #[unsafe(no_mangle)] @@ -111,7 +153,18 @@ unsafe extern "C" fn __spre_crypto_auth_hmacsha256_final( state: NonNullPtr<*mut crypto_auth_hmacsha256_state>, out: NonNullPtr<*mut c_uchar>, ) -> c_int { - todo!() + let out = unsafe { &mut *(out as *mut GenericArray) }; + + HMAC.lock(|hmac| { + let mut hmac = hmac.borrow_mut(); + let hmac = hmac + .take() + .expect("HMAC must first be initialized before it is updated."); + + hmac.finalize_into(out); + }); + + 0 } #[unsafe(no_mangle)] diff --git a/firmware2/src/ui/mod.rs b/firmware2/src/ui/mod.rs index 675fb8e..d1ab6a1 100644 --- a/firmware2/src/ui/mod.rs +++ b/firmware2/src/ui/mod.rs @@ -20,7 +20,6 @@ pub async fn run_renderer_task(backend: SlintBackend) { let main = AppWindow::new().unwrap(); - let mut buffer = CString::default(); main.on_accepted(|string| { warn!("Accepted: {string}"); let Ok(c_string) = CString::new(&*string) else {