Implement Spectre site key derivation

This commit is contained in:
Jakub Hlusička 2026-01-20 21:32:37 +01:00
parent b5535d6f52
commit 3c695be996
4 changed files with 63 additions and 9 deletions

1
firmware2/Cargo.lock generated
View file

@ -30,6 +30,7 @@ dependencies = [
"esp-rtos", "esp-rtos",
"esp-storage", "esp-storage",
"gix", "gix",
"hmac",
"i-slint-common", "i-slint-common",
"indoc", "indoc",
"itertools 0.14.0", "itertools 0.14.0",

View file

@ -78,6 +78,7 @@ printf-compat = { version = "0.2.1", default-features = false }
spectre-api-sys = { git = "https://github.com/Limeth/spectre-api-sys" } spectre-api-sys = { git = "https://github.com/Limeth/spectre-api-sys" }
sha2 = { version = "0.10.9", default-features = false } sha2 = { version = "0.10.9", default-features = false }
password-hash = { path = "password-hash", default-features = false } password-hash = { path = "password-hash", default-features = false }
hmac = "0.12.1"
# Crates for serial UART CLI # Crates for serial UART CLI
embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] } embedded-cli = { version = "0.2.1", default-features = false, features = ["help", "macros"] }

View file

@ -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::{ use sha2::{
Digest, Sha256, Digest, Sha256,
digest::{consts::U32, generic_array::GenericArray}, digest::{consts::U32, generic_array::GenericArray},
}; };
use spectre_api_sys::{SpectreKeyPurpose, spectre_purpose_scope}; 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. // Just a way to mark non-null pointers.
// Rust's `NonNull` is for mutable pointers only. // 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<u8, U32>); let data_out = &mut *(data_out as *mut GenericArray<u8, U32>);
let data_in = core::slice::from_raw_parts(data_in, data_in_len as usize); let data_in = core::slice::from_raw_parts(data_in, data_in_len as usize);
let mut digest = Sha256::new(); let mut digest = Sha256::new();
digest.update(data_in); Digest::update(&mut digest, data_in);
digest.finalize_into_reset(data_out); digest.finalize_into_reset(data_out);
} }
@ -88,22 +96,56 @@ struct crypto_auth_hmacsha256_state {
octx: crypto_hash_sha256_state, octx: crypto_hash_sha256_state,
} }
static HMAC: blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<Option<Hmac<Sha256>>>> =
blocking_mutex::Mutex::new(RefCell::new(None));
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_auth_hmacsha256_init( unsafe extern "C" fn __spre_crypto_auth_hmacsha256_init(
state: NonNullPtr<*mut crypto_auth_hmacsha256_state>, state: NonNullPtr<*mut crypto_auth_hmacsha256_state>,
key: NonNullPtr<*const c_uchar>, key: NonNullPtr<*const c_uchar>,
keylen: c_size_t, key_len: c_size_t,
) -> c_int { ) -> 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::<Sha256>::new_from_slice(key).unwrap());
});
0
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
unsafe extern "C" fn __spre_crypto_auth_hmacsha256_update( unsafe extern "C" fn __spre_crypto_auth_hmacsha256_update(
state: NonNullPtr<*mut crypto_auth_hmacsha256_state>, state: NonNullPtr<*mut crypto_auth_hmacsha256_state>,
data_in: *const c_uchar, data_in: *const c_uchar,
inlen: c_ulonglong, data_in_len: c_ulonglong,
) -> c_int { ) -> 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)] #[unsafe(no_mangle)]
@ -111,7 +153,18 @@ unsafe extern "C" fn __spre_crypto_auth_hmacsha256_final(
state: NonNullPtr<*mut crypto_auth_hmacsha256_state>, state: NonNullPtr<*mut crypto_auth_hmacsha256_state>,
out: NonNullPtr<*mut c_uchar>, out: NonNullPtr<*mut c_uchar>,
) -> c_int { ) -> c_int {
todo!() let out = unsafe { &mut *(out as *mut GenericArray<u8, U32>) };
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)] #[unsafe(no_mangle)]

View file

@ -20,7 +20,6 @@ pub async fn run_renderer_task(backend: SlintBackend) {
let main = AppWindow::new().unwrap(); let main = AppWindow::new().unwrap();
let mut buffer = CString::default();
main.on_accepted(|string| { main.on_accepted(|string| {
warn!("Accepted: {string}"); warn!("Accepted: {string}");
let Ok(c_string) = CString::new(&*string) else { let Ok(c_string) = CString::new(&*string) else {