use zeroize::Zeroizing;
use crate::grant::WrappingKey;
use crate::primitives::{Aead, Authenticator, Csprng, KeyWrap, PrimitiveSuite, WrapBinding};
use crate::state::{ProtectedState, Registry, SealedCredential, SealedState, CURRENT_VERSION};
use crate::Result;
pub struct SetupInputs<A: Authenticator> {
pub protected: ProtectedState,
pub enrollment: A::Enrollment,
pub prf_salt: Vec<u8>,
pub wrapping_key: WrappingKey,
}
pub struct SetupOutputs {
pub sealed: SealedState,
}
pub fn run<S: PrimitiveSuite, A: Authenticator>(
inputs: SetupInputs<A>,
auth_context: &A::Context,
) -> Result<SetupOutputs> {
let SetupInputs {
mut protected,
enrollment,
prf_salt,
wrapping_key,
} = inputs;
let credential = A::verify_enrollment(&enrollment, auth_context)?;
let k = Zeroizing::new(S::Csprng::random_32());
let cid_b64 = base64::engine::general_purpose::STANDARD.encode(&credential.credential_id);
protected.peers.insert(cid_b64, wrapping_key.clone());
let m_bytes = protected.to_canonical()?;
let nonce = S::Aead::fresh_nonce();
let mut ciphertext = Vec::with_capacity(nonce.len() + m_bytes.len() + S::Aead::TAG_LEN);
ciphertext.extend_from_slice(&nonce);
let mut ct = S::Aead::encrypt(
&k[..],
&nonce,
&m_bytes,
seal_ad(CURRENT_VERSION).as_slice(),
)?;
ciphertext.append(&mut ct);
let binding = WrapBinding {
credential_id: &credential.credential_id,
version: CURRENT_VERSION,
};
let wrapped_key = S::Wrap::wrap(wrapping_key.as_bytes(), &k[..], &binding)?;
let mut registry = Registry::new();
registry.insert::<A>(&credential.credential_id, &credential.public_key)?;
let sealed_cred = SealedCredential {
credential_id: credential.credential_id,
prf_salt,
wrapped_key,
};
let sealed = SealedState {
version: CURRENT_VERSION,
registry,
credentials: vec![sealed_cred],
ciphertext,
};
Ok(SetupOutputs { sealed })
}
pub(crate) fn seal_ad(version: u16) -> Vec<u8> {
let mut ad = Vec::with_capacity(crate::primitives::domain::DS_SEAL.len() + 2);
ad.extend_from_slice(crate::primitives::domain::DS_SEAL);
ad.extend_from_slice(&version.to_be_bytes());
ad
}
use base64::Engine;