use super::{ObjectWrapper, TransientKeyContext};
use crate::{
abstraction::{ek, AsymmetricAlgorithmSelection},
constants::SessionType,
handles::{AuthHandle, KeyHandle, SessionHandle},
interface_types::{
algorithm::HashingAlgorithm,
key_bits::RsaKeyBits,
session_handles::{AuthSession, PolicySession},
},
structures::{EncryptedSecret, IdObject, SymmetricDefinition},
traits::Marshall,
utils::PublicKey,
Result,
};
use std::convert::TryFrom;
#[derive(Debug)]
pub struct MakeCredParams {
pub name: Vec<u8>,
pub public: Vec<u8>,
pub attesting_key_pub: PublicKey,
}
impl TransientKeyContext {
pub fn get_make_cred_params(
&mut self,
object: ObjectWrapper,
key: Option<ObjectWrapper>,
) -> Result<MakeCredParams> {
let object_handle = self.load_key(object.params, object.material, None)?;
let (object_public, object_name, _) =
self.context.read_public(object_handle).or_else(|e| {
self.context.flush_context(object_handle.into())?;
Err(e)
})?;
self.context.flush_context(object_handle.into())?;
let public = object_public.marshall()?;
let attesting_key_pub = match key {
None => get_ek_object_public(&mut self.context)?,
Some(key) => key.material.public,
};
Ok(MakeCredParams {
name: object_name.value().to_vec(),
public,
attesting_key_pub,
})
}
pub fn activate_credential(
&mut self,
object: ObjectWrapper,
key: Option<ObjectWrapper>,
credential_blob: Vec<u8>,
secret: Vec<u8>,
) -> Result<Vec<u8>> {
let credential_blob = IdObject::try_from(credential_blob)?;
let secret = EncryptedSecret::try_from(secret)?;
let object_handle = self.load_key(object.params, object.material, object.auth)?;
let (key_handle, session_2) = match key {
Some(key) => self.prepare_key_activate_cred(key),
None => self.prepare_ek_activate_cred(),
}
.or_else(|e| {
self.context.flush_context(object_handle.into())?;
Err(e)
})?;
let (session_1, _, _) = self.context.sessions();
let credential = self
.context
.execute_with_sessions((session_1, session_2, None), |ctx| {
ctx.activate_credential(object_handle, key_handle, credential_blob, secret)
})
.or_else(|e| {
self.context.flush_context(object_handle.into())?;
self.context.flush_context(key_handle.into())?;
self.context
.flush_context(SessionHandle::from(session_2).into())?;
Err(e)
})?;
self.context.flush_context(object_handle.into())?;
self.context.flush_context(key_handle.into())?;
self.context
.flush_context(SessionHandle::from(session_2).into())?;
Ok(credential.value().to_vec())
}
fn prepare_ek_activate_cred(&mut self) -> Result<(KeyHandle, Option<AuthSession>)> {
let session = self.context.start_auth_session(
None,
None,
None,
SessionType::Policy,
SymmetricDefinition::AES_128_CFB,
HashingAlgorithm::Sha256,
)?;
let _ = self.context.policy_secret(
PolicySession::try_from(session.unwrap())
.expect("Failed to convert auth session to policy session"),
AuthHandle::Endorsement,
Default::default(),
Default::default(),
Default::default(),
None,
);
Ok((
ek::create_ek_object_2(
&mut self.context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)
.or_else(|e| {
self.context
.flush_context(SessionHandle::from(session).into())?;
Err(e)
})?,
session,
))
}
fn prepare_key_activate_cred(
&mut self,
key: ObjectWrapper,
) -> Result<(KeyHandle, Option<AuthSession>)> {
let session = self.context.start_auth_session(
None,
None,
None,
SessionType::Hmac,
SymmetricDefinition::AES_128_CFB,
HashingAlgorithm::Sha256,
)?;
Ok((
self.load_key(key.params, key.material, key.auth)
.or_else(|e| {
self.context
.flush_context(SessionHandle::from(session).into())?;
Err(e)
})?,
session,
))
}
}
fn get_ek_object_public(context: &mut crate::Context) -> Result<PublicKey> {
let key_handle = ek::create_ek_object_2(
context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)?;
let (attesting_key_pub, _, _) = context.read_public(key_handle).or_else(|e| {
context.flush_context(key_handle.into())?;
Err(e)
})?;
context.flush_context(key_handle.into())?;
PublicKey::try_from(attesting_key_pub)
}