pub use filament_cap::ephemeral::*;
use std::collections::HashMap;
use std::sync::{Mutex, OnceLock};
use zeroize::Zeroize;
struct PendingEnroll {
enroll_seed: [u8; 32],
device_pub: [u8; 32],
auth_key: AuthKey,
}
impl Drop for PendingEnroll {
fn drop(&mut self) {
self.enroll_seed.zeroize();
}
}
static PENDING_ENROLLS: OnceLock<Mutex<HashMap<String, PendingEnroll>>> = OnceLock::new();
pub fn register_enrollment(
peer_id: String,
enroll_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_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.clone();
let enroll_kp = ring::signature::Ed25519KeyPair::from_seed_unchecked(&pe.enroll_seed).ok()?;
let message = enrollment_possession_msg(&nonce, &pe.device_pub, &verifier_pub);
let enroll_signature = enroll_kp.sign(&message);
let mut enroll_possession_sig = [0u8; 64];
enroll_possession_sig.copy_from_slice(enroll_signature.as_ref());
let device_possession_sig = crate::overlay::overlay_sign_possession(&message).ok()?;
let payload = EnrollmentPayload {
auth_key: ak.clone(),
device_pub: pe.device_pub,
enroll_possession_sig,
device_possession_sig,
};
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),
}))
}