pub use filament_cap::ephemeral::*;
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};
struct PendingEnroll {
enroll_seed: [u8; 32],
device_seed: [u8; 32],
device_pub: [u8; 32],
auth_key: AuthKey,
}
static PENDING_ENROLLS: OnceLock<Mutex<HashMap<String, PendingEnroll>>> = OnceLock::new();
pub fn register_enrollment(
peer_id: String,
enroll_seed: [u8; 32],
device_seed: [u8; 32],
device_pub: [u8; 32],
auth_key: AuthKey,
) {
let mut store = PENDING_ENROLLS.get_or_init(|| Mutex::new(HashMap::new())).lock().unwrap();
store.insert(peer_id, PendingEnroll { enroll_seed, device_seed, device_pub, auth_key });
}
pub fn build_enrollment_response(
peer_id: &str,
nonce: [u8; 32],
verifier_pub: [u8; 32],
device_cert: &serde_json::Value,
) -> Option<serde_json::Value> {
let store_ref = PENDING_ENROLLS.get_or_init(|| Mutex::new(HashMap::new()));
let mut store = store_ref.lock().unwrap();
let pe = match store.get(peer_id) {
Some(p) => p,
None => return None,
};
let issuer = pe.auth_key.issuer;
let audience = pe.auth_key.audience.clone();
let cert = crate::identity::DeviceCert::from_json(device_cert)?;
if cert.user_pub != issuer
|| cert.verify(now_secs()).is_err()
|| cert.device_pub != verifier_pub
{
return None;
}
if !(audience.is_empty() || audience.contains(&verifier_pub)) {
return None;
}
let pe = store.remove(peer_id)?;
let ak = pe.auth_key;
let enroll_kp = ring::signature::Ed25519KeyPair::from_seed_unchecked(&pe.enroll_seed).ok()?;
let device_kp = ring::signature::Ed25519KeyPair::from_seed_unchecked(&pe.device_seed).ok()?;
let payload = EnrollmentPayload::build(
ak.clone(),
pe.device_pub,
&enroll_kp,
&device_kp,
nonce,
verifier_pub,
);
Some(serde_json::json!({
"auth_key": payload.auth_key.to_json(),
"device_pub": hex::encode(payload.device_pub),
"enroll_possession_sig": hex::encode(payload.enroll_possession_sig),
"device_possession_sig": hex::encode(payload.device_possession_sig),
}))
}