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-storage",
"gix",
"hmac",
"i-slint-common",
"indoc",
"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" }
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"] }

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::{
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<u8, U32>);
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<CriticalSectionRawMutex, RefCell<Option<Hmac<Sha256>>>> =
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::<Sha256>::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<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)]

View file

@ -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 {