blob: ccfeefa0691d5b07d24ecf05924e61790d7dc5fe [file] [edit]
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//! Tests for dpe.rs
#[cfg(test)]
mod tests {
use crate::cbor::{
cbor_decoder_from_message, cbor_encoder_from_message,
encode_bytes_prefix, DecoderExt,
};
use crate::commands::DeriveContextOptions;
use crate::commands_test::CommandClient;
use crate::constants::*;
use crate::crypto::test::CryptoForTesting;
use crate::crypto::{
Counter, Crypto, HandshakeMessage, SealingPublicKey, SigningPublicKey,
};
use crate::dice::test::{check_cert, get_fake_dice_input, DiceForTesting};
use crate::dice::{
Cdi, Certificate, CertificateInfoList, Dice, DiceInput,
InternalInputType, Uds,
};
use crate::dpe::{find_context_by_handle, ContextIndex, Dpe, DpeContext};
use crate::encode::{
ContextHandle, InitTypeSelector, LocalityId, SessionId,
};
use crate::encode_test::{
decode_certificate_chain, decode_error_response, encode_init_seed,
encode_unseal_policy,
};
use crate::error::{DpeResult, ErrCode};
use crate::memory::{Message, SmallMessage};
use crate::noise::test::{get_dh_public_key, SessionClientForTesting};
use heapless::Vec;
use log::debug;
use rand_chacha::ChaCha12Rng;
use rand_core::SeedableRng;
type DpeForTesting = Dpe<CryptoForTesting, DiceForTesting, ChaCha12Rng>;
const fn num_handle_contexts() -> usize {
DPE_MAX_CONTEXTS - (DPE_MAX_SESSIONS + DPE_NUM_LOCALITIES - 1)
}
fn check_context_policies(
context: &DpeContext,
allows_derive: bool,
allows_export: bool,
max_versions: &[u64; DPE_MAX_VERSION_SLOTS],
) -> () {
assert!(context.initialized);
assert_eq!(context.is_derive_allowed, allows_derive,);
assert_eq!(context.is_export_allowed, allows_export,);
for i in 0..DPE_MAX_VERSION_SLOTS {
assert_eq!(max_versions[i], context.max_versions[i]);
}
}
fn check_initial_context_policies(context: &DpeContext) -> () {
check_context_policies(context, true, true, &Default::default())
}
fn check_cert_counts(
context: &DpeContext,
expected_certs: usize,
expected_staged_cert_infos: usize,
) -> () {
assert_eq!(expected_certs, context.certificates.0.len());
let num_staged = match context.staged_certificate_info {
Some(ref staged) => staged.certificate_info.0.len(),
None => 0,
};
assert_eq!(expected_staged_cert_infos, num_staged);
}
fn get_empty_unseal_policy() -> SmallMessage {
encode_unseal_policy(&[0; DPE_MAX_VERSION_SLOTS])
}
struct DpeClientForTesting {
locality_id: LocalityId,
session_id: SessionId,
session_client: SessionClientForTesting,
current_context_handle: ContextHandle,
dpe: DpeForTesting,
}
impl DpeClientForTesting {
fn get_context_by_index<'a>(
&'a self,
index: ContextIndex,
) -> &'a DpeContext {
&self.dpe.state_manager.get_state().contexts[index]
}
fn get_context_by_index_mut<'a>(
&'a mut self,
index: ContextIndex,
) -> &'a mut DpeContext {
&mut self.dpe.state_manager.get_state_mut_for_testing().contexts
[index]
}
fn get_default_context_index(&self) -> ContextIndex {
ContextIndex::get_default(self.session_id, self.locality_id)
.unwrap()
}
fn get_default_context<'a>(&'a self) -> &'a DpeContext {
self.get_context_by_index(self.get_default_context_index())
}
fn get_default_context_mut<'a>(&'a mut self) -> &'a mut DpeContext {
self.get_context_by_index_mut(self.get_default_context_index())
}
fn get_context_index_by_handle(
&self,
handle: &ContextHandle,
) -> ContextIndex {
let state = &self.dpe.state_manager.get_state();
find_context_by_handle(state, handle).unwrap()
}
fn get_context_by_handle<'a>(
&'a self,
handle: &ContextHandle,
) -> &'a DpeContext {
self.get_context_by_index(self.get_context_index_by_handle(handle))
}
fn check_context_depth(
&self,
index: ContextIndex,
expected_depth: usize,
) -> () {
let mut depth: usize = 0;
let contexts = &self.dpe.state_manager.get_state().contexts;
let mut current_index = index;
debug!(
"parent: {:?} -> {:?}",
current_index, contexts[current_index].parent
);
while let Some(parent_index) = contexts[current_index].parent {
current_index = parent_index;
debug!(
"parent: {:?} -> {:?}",
current_index, contexts[current_index].parent
);
depth += 1;
}
assert_eq!(depth, expected_depth);
}
fn is_handle_valid(&self, handle: &ContextHandle) -> bool {
let state = &self.dpe.state_manager.get_state();
find_context_by_handle(state, handle).is_ok()
}
fn has_context_changed(
&self,
index: ContextIndex,
old_index: ContextIndex,
) -> bool {
let context = self.get_context_by_index(index);
let old_context =
&self.dpe.state_manager.get_previous_state().contexts
[old_index];
context.cdi_sign != old_context.cdi_sign
&& context.cdi_seal != old_context.cdi_seal
}
fn send_command(
&mut self,
message_buffer: &mut Message,
) -> DpeResult<()> {
self.send_command_with_session_info(None, message_buffer)
}
fn send_command_plaintext(
&mut self,
message_buffer: &mut Message,
) -> DpeResult<()> {
let mut prefix = SmallMessage::new();
let _ = cbor_encoder_from_message(&mut prefix)
.array(2)
.unwrap()
.u16(0)
.unwrap();
encode_bytes_prefix(&mut prefix, message_buffer.len()).unwrap();
message_buffer.insert_prefix(prefix.as_slice()).unwrap();
self.dpe.handle_session_message_infallible(
self.locality_id,
message_buffer,
);
let mut decoder = cbor_decoder_from_message(message_buffer);
assert_eq!(decoder.array().unwrap().unwrap(), 2);
assert_eq!(decoder.u16().unwrap(), 0);
let position = decoder.decode_bytes_prefix()?;
message_buffer.remove_prefix(position).unwrap();
Ok(())
}
fn send_command_with_session_info(
&mut self,
session_info: Option<(SessionId, &mut SessionClientForTesting)>,
message_buffer: &mut Message,
) -> DpeResult<()> {
let (session_id, session_client) = match session_info {
None => (self.session_id, &mut self.session_client),
Some(s) => s,
};
if session_id == SessionId::get_plain_text() {
return self.send_command_plaintext(message_buffer);
}
session_client.encrypt(message_buffer).unwrap();
let mut prefix = SmallMessage::new();
let _ = cbor_encoder_from_message(&mut prefix)
.array(2)
.unwrap()
.u32(session_id.into())
.unwrap();
encode_bytes_prefix(&mut prefix, message_buffer.len()).unwrap();
message_buffer.insert_prefix(prefix.as_slice()).unwrap();
self.dpe.handle_session_message_infallible(
self.locality_id,
message_buffer,
);
let mut decoder = cbor_decoder_from_message(message_buffer);
assert_eq!(decoder.array().unwrap().unwrap(), 2);
let session_id_out =
SessionId::new(decoder.u16().unwrap().into()).unwrap();
if session_id_out.is_plain_text() {
// Plaintext error response
return Err(decode_error_response(decoder.bytes().unwrap())
.unwrap_err());
}
assert_eq!(session_id_out, session_id);
let response_position = decoder.decode_bytes_prefix().unwrap();
message_buffer.remove_prefix(response_position).unwrap();
session_client.decrypt(message_buffer)?;
Ok(())
}
fn any_command(&mut self) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::get_profile_in(&mut buffer);
self.send_command(&mut buffer)?;
CommandClient::get_profile_out(&buffer, &mut Default::default())
}
fn any_command_with_locality(
&mut self,
target_locality: LocalityId,
) -> DpeResult<()> {
let old_locality = self.locality_id;
self.locality_id = target_locality;
let mut buffer = Message::new();
CommandClient::get_profile_in(&mut buffer);
self.send_command(&mut buffer)?;
CommandClient::get_profile_out(&buffer, &mut Default::default())?;
self.locality_id = old_locality;
Ok(())
}
fn any_command_with_session_info(
&mut self,
session_id: SessionId,
session_client: &mut SessionClientForTesting,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::get_profile_in(&mut buffer);
self.send_command_with_session_info(
Some((session_id, session_client)),
&mut buffer,
)?;
CommandClient::get_profile_out(&buffer, &mut Default::default())
}
fn any_command_with_handle(
&mut self,
context_handle: &ContextHandle,
) -> DpeResult<ContextHandle> {
let mut buffer = Message::new();
CommandClient::rotate_context_handle_in(
Some(context_handle),
false,
None,
&mut buffer,
);
self.send_command(&mut buffer)?;
CommandClient::rotate_context_handle_out(&buffer)
.transpose()
.unwrap()
}
fn any_command_with_handle_and_session_info(
&mut self,
context_handle: &ContextHandle,
session_id: SessionId,
session_client: &mut SessionClientForTesting,
) -> DpeResult<ContextHandle> {
let mut buffer = Message::new();
CommandClient::rotate_context_handle_in(
Some(context_handle),
false,
None,
&mut buffer,
);
self.send_command_with_session_info(
Some((session_id, session_client)),
&mut buffer,
)?;
CommandClient::rotate_context_handle_out(&buffer)
.transpose()
.unwrap()
}
fn get_profile(&mut self, descriptor: &mut Message) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::get_profile_in(&mut buffer);
self.send_command(&mut buffer)?;
CommandClient::get_profile_out(&buffer, descriptor)
}
fn open_session_with_session_info(
&mut self,
current_session_info: Option<(
SessionId,
&mut SessionClientForTesting,
)>,
) -> DpeResult<(SessionId, SessionClientForTesting)> {
debug!("open_session");
let mut new_session = SessionClientForTesting::new();
let public_key = get_dh_public_key::<noise_rust_crypto::X25519>(
&self.dpe.static_dh_key,
)
.unwrap();
let initiator_handshake = new_session
.start_handshake_with_known_public_key(&public_key)
.unwrap();
let mut buffer = Message::new();
CommandClient::open_session_in(&initiator_handshake, &mut buffer);
self.send_command_with_session_info(
current_session_info,
&mut buffer,
)?;
let responder_handshake = CommandClient::open_session_out(&buffer)?;
let payload =
new_session.finish_handshake(&responder_handshake).unwrap();
let new_session_id = SessionId::new(
cbor_decoder_from_message(&payload)
.u32()
.unwrap()
.try_into()
.unwrap(),
)
.unwrap();
Ok((new_session_id, new_session))
}
fn open_session(&mut self) -> DpeResult<()> {
(self.session_id, self.session_client) =
self.open_session_with_session_info(None)?;
Ok(())
}
fn close_session(&mut self) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::close_session_in(&mut buffer);
self.send_command(&mut buffer)?;
CommandClient::close_session_out(&buffer)?;
self.session_id = SessionId::get_plain_text();
self.session_client = Default::default();
Ok(())
}
fn sync_session(&mut self) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::sync_session_in(
self.session_id,
self.session_client.encrypt_cipher_state.n(),
&mut buffer,
);
self.send_command_plaintext(&mut buffer)?;
let new_n = CommandClient::sync_session_out(&buffer)?;
if self.session_client.decrypt_cipher_state.n() > new_n {
return Err(ErrCode::InvalidArgument);
}
self.session_client.decrypt_cipher_state.set_n(new_n);
Ok(())
}
fn initialize_context(
&mut self,
simulation: bool,
use_default_context: bool,
seed: &[u8],
) -> DpeResult<Option<ContextHandle>> {
let mut buffer = Message::new();
CommandClient::initialize_context_in(
simulation,
use_default_context,
seed,
&mut buffer,
);
self.send_command(&mut buffer)?;
CommandClient::initialize_context_out(&buffer)
}
fn derive_context(
&mut self,
options: &DeriveContextOptions,
handle: Option<&ContextHandle>,
new_session_initiator_handshake: Option<&HandshakeMessage>,
version_info: Option<(usize, u64)>,
dice_input: &DiceInput,
internal_inputs: Option<&[InternalInputType]>,
target_locality: Option<LocalityId>,
new_context_handle: &mut Option<ContextHandle>,
new_session_responder_handshake: &mut Option<HandshakeMessage>,
new_parent_context_handle: &mut Option<ContextHandle>,
new_certificate: &mut Option<Certificate>,
exported_cdi: &mut Option<SmallMessage>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::derive_context_in(
options,
handle,
new_session_initiator_handshake,
version_info,
dice_input,
internal_inputs,
target_locality,
&mut buffer,
);
self.send_command(&mut buffer)?;
CommandClient::derive_context_out(
&buffer,
new_context_handle,
new_session_responder_handshake,
new_parent_context_handle,
new_certificate,
exported_cdi,
)
}
fn derive_context2(
&mut self,
options: &DeriveContextOptions,
handle: Option<&ContextHandle>,
new_session_initiator_handshake: Option<&HandshakeMessage>,
version_info: Option<(usize, u64)>,
dice_input: &DiceInput,
internal_inputs: Option<&[InternalInputType]>,
target_locality: Option<LocalityId>,
) -> DpeResult<(
Option<ContextHandle>,
Option<HandshakeMessage>,
Option<ContextHandle>,
Option<Certificate>,
Option<SmallMessage>,
)> {
let mut new_context_handle: Option<ContextHandle> = None;
let mut handshake_out: Option<HandshakeMessage> = None;
let mut parent_handle: Option<ContextHandle> = None;
let mut new_certificate: Option<Certificate> = None;
let mut exported_cdi: Option<SmallMessage> = None;
self.derive_context(
options,
handle,
new_session_initiator_handshake,
version_info,
dice_input,
internal_inputs,
target_locality,
&mut new_context_handle,
&mut handshake_out,
&mut parent_handle,
&mut new_certificate,
&mut exported_cdi,
)?;
Ok((
new_context_handle,
handshake_out,
parent_handle,
new_certificate,
exported_cdi,
))
}
fn derive_context3(
&mut self,
options: &DeriveContextOptions,
) -> DpeResult<()> {
let _ = self.derive_context2(
options,
None,
None,
None,
&get_fake_dice_input(),
None,
None,
)?;
Ok(())
}
fn derive_context4(
&mut self,
options: &DeriveContextOptions,
handle: &ContextHandle,
) -> DpeResult<(ContextHandle, ContextHandle)> {
let (derived_handle, _, parent_handle, _, _) = self
.derive_context2(
options,
Some(handle),
None,
None,
&get_fake_dice_input(),
None,
None,
)?;
let derived_handle = derived_handle.unwrap();
let parent_handle = match parent_handle {
None => Default::default(),
Some(handle) => handle,
};
Ok((derived_handle, parent_handle))
}
fn get_certificate_chain(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
clear_from_context: bool,
encoded_certificate_chain: &mut Message,
new_handle: &mut Option<ContextHandle>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::get_certificate_chain_in(
handle,
retain_context,
clear_from_context,
&mut buffer,
);
self.send_command(&mut buffer)?;
*new_handle = CommandClient::get_certificate_chain_out(
&buffer,
encoded_certificate_chain,
)?;
Ok(())
}
fn get_certificate_chain2(
&mut self,
retain_context: bool,
clear_from_context: bool,
) -> DpeResult<Message> {
let mut handle_not_used = Default::default();
let mut encoded_certificate_chain = Default::default();
self.get_certificate_chain(
None,
retain_context,
clear_from_context,
&mut encoded_certificate_chain,
&mut handle_not_used,
)?;
assert!(handle_not_used.is_none());
Ok(encoded_certificate_chain)
}
fn certify_key(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
public_key: Option<&SigningPublicKey>,
label: &[u8],
additional_input: &[u8],
certificate: &mut Certificate,
derived_public_key: &mut Option<SigningPublicKey>,
new_handle: &mut Option<ContextHandle>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::certify_key_in(
handle,
retain_context,
public_key,
label,
additional_input,
&mut buffer,
);
self.send_command(&mut buffer)?;
*new_handle = CommandClient::certify_key_out(
&buffer,
certificate,
derived_public_key,
)?;
Ok(())
}
fn certify_key2(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
public_key: Option<&SigningPublicKey>,
label: &[u8],
additional_input: &[u8],
) -> DpeResult<(
Certificate,
Option<SigningPublicKey>,
Option<ContextHandle>,
)> {
let mut cert = Default::default();
let mut pubkey = Default::default();
let mut new_handle = Default::default();
self.certify_key(
handle,
retain_context,
public_key,
label,
additional_input,
&mut cert,
&mut pubkey,
&mut new_handle,
)?;
Ok((cert, pubkey, new_handle))
}
fn sign(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
label: &[u8],
is_symmetric: bool,
to_be_signed: &[u8],
signature: &mut SmallMessage,
new_handle: &mut Option<ContextHandle>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::sign_in(
handle,
retain_context,
label,
is_symmetric,
to_be_signed,
&mut buffer,
);
self.send_command(&mut buffer)?;
*new_handle = CommandClient::sign_out(&buffer, signature)?;
Ok(())
}
fn sign2(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
label: &[u8],
is_symmetric: bool,
to_be_signed: &[u8],
) -> DpeResult<(SmallMessage, Option<ContextHandle>)> {
let mut signature = Default::default();
let mut new_handle = Default::default();
self.sign(
handle,
retain_context,
label,
is_symmetric,
to_be_signed,
&mut signature,
&mut new_handle,
)?;
Ok((signature, new_handle))
}
fn seal(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
policy: &[u8],
label: &[u8],
data_to_seal: &[u8],
sealed_data: &mut Message,
new_handle: &mut Option<ContextHandle>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::seal_in(
handle,
retain_context,
policy,
label,
data_to_seal,
&mut buffer,
);
self.send_command(&mut buffer)?;
*new_handle = CommandClient::seal_out(&buffer, sealed_data)?;
Ok(())
}
fn seal2(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
policy: &[u8],
label: &[u8],
data_to_seal: &[u8],
) -> DpeResult<(Message, Option<ContextHandle>)> {
let mut sealed_data = Default::default();
let mut new_handle = Default::default();
self.seal(
handle,
retain_context,
policy,
label,
data_to_seal,
&mut sealed_data,
&mut new_handle,
)?;
Ok((sealed_data, new_handle))
}
fn unseal(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
is_asymmetric: bool,
policy: &[u8],
label: &[u8],
data_to_unseal: &[u8],
unsealed_data: &mut Message,
new_handle: &mut Option<ContextHandle>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::unseal_in(
handle,
retain_context,
is_asymmetric,
policy,
label,
data_to_unseal,
&mut buffer,
);
self.send_command(&mut buffer)?;
*new_handle = CommandClient::unseal_out(&buffer, unsealed_data)?;
Ok(())
}
fn unseal2(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
is_asymmetric: bool,
policy: &[u8],
label: &[u8],
data_to_unseal: &[u8],
) -> DpeResult<(Message, Option<ContextHandle>)> {
let mut unsealed_data = Default::default();
let mut new_handle = Default::default();
self.unseal(
handle,
retain_context,
is_asymmetric,
policy,
label,
data_to_unseal,
&mut unsealed_data,
&mut new_handle,
)?;
Ok((unsealed_data, new_handle))
}
fn derive_sealing_public_key(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
policy: &[u8],
label: &[u8],
public_key: &mut SealingPublicKey,
new_handle: &mut Option<ContextHandle>,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::derive_sealing_public_key_in(
handle,
retain_context,
policy,
label,
&mut buffer,
);
self.send_command(&mut buffer)?;
*new_handle = CommandClient::derive_sealing_public_key_out(
&buffer, public_key,
)?;
Ok(())
}
fn derive_sealing_public_key2(
&mut self,
handle: Option<&ContextHandle>,
retain_context: bool,
policy: &[u8],
label: &[u8],
) -> DpeResult<(SealingPublicKey, Option<ContextHandle>)> {
let mut public_key = Default::default();
let mut new_handle = Default::default();
self.derive_sealing_public_key(
handle,
retain_context,
policy,
label,
&mut public_key,
&mut new_handle,
)?;
Ok((public_key, new_handle))
}
fn rotate_context_handle(
&mut self,
handle: Option<&ContextHandle>,
to_default: bool,
target_locality: Option<LocalityId>,
) -> DpeResult<Option<ContextHandle>> {
let mut buffer = Message::new();
CommandClient::rotate_context_handle_in(
handle,
to_default,
target_locality,
&mut buffer,
);
self.send_command(&mut buffer)?;
CommandClient::rotate_context_handle_out(&buffer)
}
fn destroy_context(
&mut self,
handle: Option<&ContextHandle>,
recursive: bool,
) -> DpeResult<()> {
let mut buffer = Message::new();
CommandClient::destroy_context_in(handle, recursive, &mut buffer);
self.send_command(&mut buffer)?;
CommandClient::destroy_context_out(&buffer)
}
}
fn get_dpe_client() -> DpeClientForTesting {
DpeClientForTesting {
locality_id: LocalityId::new(0).unwrap(),
session_id: SessionId::get_plain_text(),
session_client: Default::default(),
current_context_handle: Default::default(),
dpe: get_dpe_instance(),
}
}
fn get_dpe_client_initialized_with(
simulation: bool,
use_default_context: bool,
) -> DpeClientForTesting {
let mut client = get_dpe_client();
client.open_session().unwrap();
let handle = client
.initialize_context(
simulation,
use_default_context,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE]),
None,
None,
)
.as_slice(),
)
.unwrap();
if let Some(handle) = handle {
client.current_context_handle = handle;
}
client
}
fn get_dpe_client_initialized() -> DpeClientForTesting {
get_dpe_client_initialized_with(false, true)
}
fn get_dpe_instance() -> DpeForTesting {
let _ = env_logger::builder().is_test(true).try_init();
DpeForTesting {
static_dh_key: Default::default(),
internal_uds_seed: None,
internal_cdi_sign: None,
internal_cdi_seal: None,
dice: Default::default(),
rng: <ChaCha12Rng as SeedableRng>::from_seed(Default::default()),
current_session_id: SessionId::get_plain_text(),
current_locality_id: LocalityId::new(0).unwrap(),
sessions: Default::default(),
state_manager: Default::default(),
}
}
#[test]
fn check_initial_state() {
let dpe = get_dpe_instance();
let dpe_state = &dpe.state_manager.get_state();
assert_eq!(dpe_state.internal_secrets_locked, false);
}
#[test]
fn test_get_profile() {
let mut dpe = get_dpe_client();
let mut descriptor = Message::new();
dpe.get_profile(&mut descriptor).unwrap();
let mut decoder = cbor_decoder_from_message(&descriptor);
assert_eq!(decoder.map().unwrap().unwrap(), 1);
assert_eq!(decoder.u32().unwrap(), 1);
assert_eq!(decoder.str().unwrap(), "com.google.opd.default");
// Try again on an encrypted session.
dpe.open_session().unwrap();
let mut descriptor2 = Message::new();
dpe.get_profile(&mut descriptor2).unwrap();
assert_eq!(descriptor, descriptor2);
}
#[test]
fn basic_session_flow() {
let mut client = get_dpe_client();
client.open_session().unwrap();
assert_eq!(
client.session_client.encrypt_cipher_state,
client.dpe.sessions[0].decrypt_cipher_state
);
assert_eq!(
client.session_client.decrypt_cipher_state,
client.dpe.sessions[0].encrypt_cipher_state
);
client.sync_session().unwrap();
client.close_session().unwrap();
assert_eq!(
client.dpe.sessions[0].encrypt_cipher_state,
Default::default()
);
assert_eq!(
client.dpe.sessions[0].decrypt_cipher_state,
Default::default()
);
}
#[test]
fn many_sessions() {
let mut dpe = get_dpe_client();
for _ in 1..=DPE_MAX_SESSIONS {
dpe.open_session().unwrap();
}
// One more should overflow.
let _ = dpe.open_session().unwrap_err();
}
#[test]
fn nested_sessions() {
if DPE_MAX_SESSIONS >= 3 {
let mut dpe = get_dpe_client();
let (session_id1, mut session_client1) =
dpe.open_session_with_session_info(None).unwrap();
let (session_id2, mut session_client2) = dpe
.open_session_with_session_info(Some((
session_id1,
&mut session_client1,
)))
.unwrap();
let (_, _) = dpe
.open_session_with_session_info(Some((
session_id2,
&mut session_client2,
)))
.unwrap();
}
}
#[test]
fn session_invalidates_after_close() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
// Close without changing the client session state.
let mut buffer = Message::new();
CommandClient::close_session_in(&mut buffer);
dpe.send_command(&mut buffer).unwrap();
CommandClient::close_session_out(&buffer).unwrap();
// Send any other command on the closed session, it should fail.
let _ = dpe.any_command().unwrap_err();
}
#[test]
fn close_plaintext_session_fails() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let mut buffer = Message::new();
CommandClient::close_session_in(&mut buffer);
dpe.send_command_plaintext(&mut buffer).unwrap();
let _ = CommandClient::close_session_out(&buffer).unwrap_err();
}
#[test]
fn sync_after_dropped_command() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
dpe.session_client
.encrypt_cipher_state
.set_n(dpe.session_client.encrypt_cipher_state.n() + 1);
let _ = dpe.any_command().unwrap_err();
dpe.sync_session().unwrap();
dpe.any_command().unwrap();
}
#[test]
fn sync_after_dropped_response() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
dpe.any_command().unwrap();
dpe.session_client
.decrypt_cipher_state
.set_n(dpe.session_client.decrypt_cipher_state.n() - 1);
dpe.sync_session().unwrap();
dpe.any_command().unwrap();
}
#[test]
fn sync_not_plaintext_fails() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let mut buffer = Message::new();
CommandClient::sync_session_in(
dpe.session_id,
dpe.session_client.encrypt_cipher_state.n(),
&mut buffer,
);
dpe.send_command(&mut buffer).unwrap();
let _ = CommandClient::sync_session_out(&buffer).unwrap_err();
}
#[test]
fn init_internal_uds() {
if num_handle_contexts() < 1 {
return;
}
let mut dpe = get_dpe_client();
dpe.dpe.internal_uds_seed =
Some(Uds::from_slice(&[0; DICE_UDS_SIZE]).unwrap());
dpe.open_session().unwrap();
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(Some(InitTypeSelector::Uds), None, None, None)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
check_initial_context_policies(&dpe_state.contexts[index]);
}
#[test]
fn init_internal_uds_fail_if_empty() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(Some(InitTypeSelector::Uds), None, None, None)
.as_slice(),
)
.unwrap_err();
}
#[test]
fn init_external_uds() {
if num_handle_contexts() < 1 {
return;
}
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE]),
None,
None,
)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
check_initial_context_policies(&dpe_state.contexts[index]);
}
#[test]
fn init_external_uds_fail_if_short() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE - 1]),
None,
None,
)
.as_slice(),
)
.unwrap_err();
}
#[test]
fn init_combined_uds() {
if num_handle_contexts() < 1 {
return;
}
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
dpe.dpe.internal_uds_seed =
Some(Uds::from_slice(&[0; DICE_UDS_SIZE]).unwrap());
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE]),
None,
None,
)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
check_initial_context_policies(&dpe_state.contexts[index]);
}
#[test]
fn init_combined_uds_fail_if_short() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
// With good internal, short external.
dpe.dpe.internal_uds_seed =
Some(Uds::from_slice(&[0; DICE_UDS_SIZE]).unwrap());
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE - 1]),
None,
None,
)
.as_slice(),
)
.unwrap_err();
}
#[test]
fn init_internal_cdis() {
if num_handle_contexts() < 1 {
return;
}
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
dpe.dpe.internal_cdi_sign =
Some(Cdi::from_slice(&[0; DICE_CDI_SIZE]).unwrap());
dpe.dpe.internal_cdi_seal =
Some(Cdi::from_slice(&[0; DICE_CDI_SIZE]).unwrap());
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(Some(InitTypeSelector::Cdi), None, None, None)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
check_initial_context_policies(&dpe_state.contexts[index]);
}
#[test]
fn init_internal_cdis_fail_if_missing() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
dpe.dpe.internal_cdi_sign = None;
dpe.dpe.internal_cdi_seal =
Some(Cdi::from_slice(&[0; DICE_CDI_SIZE]).unwrap());
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(Some(InitTypeSelector::Cdi), None, None, None)
.as_slice(),
)
.unwrap_err();
dpe.dpe.internal_cdi_sign =
Some(Cdi::from_slice(&[0; DICE_CDI_SIZE]).unwrap());
dpe.dpe.internal_cdi_seal = None;
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(Some(InitTypeSelector::Cdi), None, None, None)
.as_slice(),
)
.unwrap_err();
dpe.dpe.internal_cdi_sign = None;
dpe.dpe.internal_cdi_seal = None;
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(Some(InitTypeSelector::Cdi), None, None, None)
.as_slice(),
)
.unwrap_err();
}
#[test]
fn init_external_cdis() {
if num_handle_contexts() < 1 {
return;
}
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let cdi_value = [0; DICE_CDI_SIZE];
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&cdi_value),
Some(&cdi_value),
)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
check_initial_context_policies(&dpe_state.contexts[index]);
}
#[test]
fn init_external_cdis_single_value() {
if num_handle_contexts() < 1 {
return;
}
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let cdi_value = [0; DICE_CDI_SIZE];
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&cdi_value),
None,
)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
check_initial_context_policies(&dpe_state.contexts[index]);
// Single value has to be the signing CDI.
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
None,
Some(&cdi_value),
)
.as_slice(),
)
.unwrap_err();
}
#[test]
fn init_external_cdis_fails_if_short() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let cdi_value = [0; DICE_CDI_SIZE];
let invalid_cdi_value = [0; DICE_CDI_SIZE - 1];
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&invalid_cdi_value),
None,
)
.as_slice(),
)
.unwrap_err();
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&invalid_cdi_value),
Some(&cdi_value),
)
.as_slice(),
)
.unwrap_err();
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&cdi_value),
Some(&invalid_cdi_value),
)
.as_slice(),
)
.unwrap_err();
let _ = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&invalid_cdi_value),
Some(&invalid_cdi_value),
)
.as_slice(),
)
.unwrap_err();
}
#[test]
fn init_simulation_context() {
if num_handle_contexts() < 2 {
return;
}
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let cdi_value = [0; DICE_CDI_SIZE];
let handle = dpe
.initialize_context(
true,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&cdi_value),
Some(&cdi_value),
)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
assert_eq!(dpe_state.contexts[index].is_simulation, true);
// Check that is_simulation is not set for non-simulation.
let handle = dpe
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Cdi),
None,
Some(&cdi_value),
Some(&cdi_value),
)
.as_slice(),
)
.unwrap()
.unwrap();
let dpe_state = &dpe.dpe.state_manager.get_state();
let index = find_context_by_handle(dpe_state, &handle).unwrap();
assert_eq!(dpe_state.contexts[index].is_simulation, false);
check_initial_context_policies(&dpe_state.contexts[index]);
}
#[test]
fn init_max_contexts() {
let mut client = get_dpe_client();
client.open_session().unwrap();
for i in 0..DPE_MAX_CONTEXTS {
assert!(
!client.dpe.state_manager.get_state().contexts[i].initialized
);
}
for _ in 0..num_handle_contexts() {
let _ = client
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE]),
None,
None,
)
.as_slice(),
)
.unwrap();
}
assert_eq!(
ErrCode::OutOfMemory,
client
.initialize_context(
false,
false,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE]),
None,
None,
)
.as_slice(),
)
.unwrap_err()
);
}
#[test]
fn init_default_context() {
let mut dpe = get_dpe_client();
dpe.open_session().unwrap();
let handle = dpe
.initialize_context(
false,
true,
encode_init_seed(
Some(InitTypeSelector::Uds),
Some(&[0; DICE_UDS_SIZE]),
None,
None,
)
.as_slice(),
)
.unwrap();
assert!(handle.is_none());
check_initial_context_policies(dpe.get_default_context());
}
#[test]
fn derive_context_defaults() {
let mut client = get_dpe_client_initialized();
let mut new_context_handle: Option<ContextHandle> = None;
let mut handshake_out: Option<HandshakeMessage> = None;
let mut parent_handle: Option<ContextHandle> = None;
let mut new_certificate: Option<Certificate> = None;
let mut exported_cdi: Option<SmallMessage> = None;
client
.derive_context(
&Default::default(),
None,
None,
None,
&get_fake_dice_input(),
None,
None,
&mut new_context_handle,
&mut handshake_out,
&mut parent_handle,
&mut new_certificate,
&mut exported_cdi,
)
.unwrap();
assert!(new_context_handle.is_none());
assert!(handshake_out.is_none());
assert!(parent_handle.is_none());
assert!(new_certificate.is_none());
assert!(exported_cdi.is_none());
check_context_policies(
client.get_default_context(),
true,
false,
&Default::default(),
);
let index = client.get_default_context_index();
client.check_context_depth(index, 0);
check_cert_counts(client.get_default_context(), 1, 0);
assert!(client.has_context_changed(index, index));
}
#[test]
fn derive_context_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
client.derive_context3(&Default::default()).unwrap();
check_context_policies(
client.get_default_context(),
true,
false,
&Default::default(),
);
let index = client.get_default_context_index();
client.check_context_depth(index, 0);
check_cert_counts(client.get_default_context(), 1, 0);
assert!(client.has_context_changed(index, index));
assert!(client.get_default_context().is_simulation);
}
#[test]
fn derive_context_with_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut new_context_handle: Option<ContextHandle> = None;
let mut handshake_out: Option<HandshakeMessage> = None;
let mut parent_handle: Option<ContextHandle> = None;
let mut new_certificate: Option<Certificate> = None;
let mut exported_cdi: Option<SmallMessage> = None;
let handle = client.current_context_handle.clone();
client
.derive_context(
&Default::default(),
Some(&handle),
None,
None,
&get_fake_dice_input(),
None,
None,
&mut new_context_handle,
&mut handshake_out,
&mut parent_handle,
&mut new_certificate,
&mut exported_cdi,
)
.unwrap();
assert!(new_context_handle.is_some());
client.current_context_handle = new_context_handle.unwrap();
assert!(handshake_out.is_none());
assert!(parent_handle.is_none());
assert!(new_certificate.is_none());
assert!(exported_cdi.is_none());
let index =
client.get_context_index_by_handle(&client.current_context_handle);
check_context_policies(
client.get_context_by_index(index),
true,
false,
&Default::default(),
);
client.check_context_depth(index, 0);
check_cert_counts(client.get_context_by_index(index), 1, 0);
assert!(client.has_context_changed(index, index));
assert_ne!(handle, client.current_context_handle);
}
#[test]
fn derive_context_not_allowed() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.allow_new_context_to_derive = false;
client.derive_context3(&options).unwrap();
assert!(!client.get_default_context().is_derive_allowed);
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err(),
);
}
#[test]
fn derive_retain_parent() {
if num_handle_contexts() < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let mut context_before_derive = client
.get_context_by_handle(&client.current_context_handle)
.clone();
let handle = client.current_context_handle.clone();
let (new_context_handle, _, parent_handle, _, _) = client
.derive_context2(
&options,
Some(&handle),
None,
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let new_context_handle = new_context_handle.unwrap();
let parent_handle = parent_handle.unwrap();
assert_ne!(handle, parent_handle);
assert_ne!(handle, new_context_handle);
assert_ne!(parent_handle, new_context_handle);
// Parent context should be unchanged except for the handle
context_before_derive.handle = parent_handle.clone();
assert_eq!(
&context_before_derive,
client.get_context_by_handle(&parent_handle)
);
assert_ne!(
&context_before_derive.cdi_sign,
&client.get_context_by_handle(&new_context_handle).cdi_sign
);
assert_ne!(
&context_before_derive.cdi_seal,
&client.get_context_by_handle(&new_context_handle).cdi_seal
);
let index = client.get_context_index_by_handle(&new_context_handle);
check_context_policies(
client.get_context_by_index(index),
true,
false,
&Default::default(),
);
client.check_context_depth(index, 1);
check_cert_counts(client.get_context_by_index(index), 1, 0);
}
#[test]
fn derive_retain_parent_default_fails() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
}
#[test]
fn derive_retain_parent_default_new_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let context_before_derive = client.get_default_context().clone();
let _ = client
.derive_context2(
&options,
None,
None,
None,
&get_fake_dice_input(),
None,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
let expected_index = ContextIndex::get_default(
SessionId::get_plain_text(),
LocalityId::new(1).unwrap(),
)
.unwrap();
let new_context = client.get_context_by_index(expected_index);
assert!(new_context.initialized);
assert_ne!(&context_before_derive, new_context);
let parent_context = client.get_default_context();
assert_eq!(&context_before_derive, parent_context);
assert_eq!(parent_context.locality_id, LocalityId::new(0).unwrap());
assert_eq!(new_context.locality_id, LocalityId::new(1).unwrap());
// Check that the new locality is operational.
client.any_command_with_locality(LocalityId::new(1).unwrap()).unwrap();
}
#[test]
fn derive_retain_parent_default_new_session() {
if DPE_MAX_SESSIONS < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let context_before_derive = client.get_default_context().clone();
// To make sure this is right on both sides, force the session counters
// to be different for encrypt vs decrypt.
client
.session_client
.encrypt_cipher_state
.set_n(client.session_client.encrypt_cipher_state.n() + 3);
client.sync_session().unwrap();
let psk = client.session_client.derive_psk();
let mut new_session = SessionClientForTesting::new();
let handshake_in = new_session.start_handshake_with_psk(&psk).unwrap();
let (_, handshake_out, _, _, _) = client
.derive_context2(
&options,
None,
Some(&handshake_in),
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let handshake_out = handshake_out.unwrap();
let encoded_session_id =
new_session.finish_handshake(&handshake_out).unwrap();
let new_session_id = SessionId::new(
cbor_decoder_from_message(&encoded_session_id)
.u32()
.unwrap()
.try_into()
.unwrap(),
)
.unwrap();
let expected_index = ContextIndex::get_default(
new_session_id,
LocalityId::new(0).unwrap(),
)
.unwrap();
let new_context = client.get_context_by_index(expected_index);
assert!(new_context.initialized);
assert_ne!(&context_before_derive, new_context);
let parent_context = client.get_default_context();
assert_eq!(&context_before_derive, parent_context);
assert_eq!(parent_context.session_id, client.session_id);
assert_eq!(new_context.session_id, new_session_id);
assert_ne!(client.session_id, new_session_id);
// Check that the new session is operational.
client
.any_command_with_session_info(new_session_id, &mut new_session)
.unwrap();
}
#[test]
fn derive_retain_parent_default_new_locality_and_session_fails() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
// Localities other than zero do not support encrypted sessions.
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let psk = client.session_client.derive_psk();
let mut new_session = SessionClientForTesting::new();
let handshake_in = new_session.start_handshake_with_psk(&psk).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.derive_context2(
&options,
None,
Some(&handshake_in),
None,
&get_fake_dice_input(),
None,
Some(LocalityId::new(1).unwrap()),
)
.unwrap_err()
);
}
#[test]
fn derive_final() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.allow_new_context_to_derive = false;
client.derive_context3(&options).unwrap();
check_context_policies(
client.get_default_context(),
false,
false,
&[0; DPE_MAX_VERSION_SLOTS],
);
}
#[test]
fn derive_no_certificate() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.create_certificate = false;
client.derive_context3(&options).unwrap();
check_cert_counts(client.get_default_context(), 0, 1);
}
#[test]
fn derive_consume_staged() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.create_certificate = false;
client.derive_context3(&options).unwrap();
check_cert_counts(client.get_default_context(), 0, 1);
options.create_certificate = true;
client.derive_context3(&options).unwrap();
check_cert_counts(client.get_default_context(), 1, 0);
}
#[test]
fn derive_cert_overflow() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
for _ in 0..DPE_MAX_CERTIFICATES_PER_CHAIN {
client.derive_context3(&options).unwrap();
}
assert_eq!(
ErrCode::OutOfMemory,
client.derive_context3(&options).unwrap_err()
);
check_cert_counts(
client.get_default_context(),
DPE_MAX_CERTIFICATES_PER_CHAIN,
0,
);
}
#[test]
fn derive_cert_info_overflow() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.create_certificate = false;
for _ in 0..DPE_MAX_CERTIFICATE_INFOS_PER_CONTEXT {
client.derive_context3(&options).unwrap();
}
assert_eq!(
ErrCode::OutOfMemory,
client.derive_context3(&options).unwrap_err()
);
check_cert_counts(
client.get_default_context(),
0,
DPE_MAX_CERTIFICATE_INFOS_PER_CONTEXT,
);
}
#[test]
fn derive_retain_parent_new_session_with_handles() {
if DPE_MAX_SESSIONS < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let psk = client.session_client.derive_psk();
let mut new_session = SessionClientForTesting::new();
let handshake_in = new_session.start_handshake_with_psk(&psk).unwrap();
let old_parent_handle = client.current_context_handle.clone();
let (new_handle, handshake_out, new_parent_handle, _, _) = client
.derive_context2(
&options,
Some(&old_parent_handle),
Some(&handshake_in),
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let new_handle = new_handle.unwrap();
let new_parent_handle = new_parent_handle.unwrap();
let handshake_out = handshake_out.unwrap();
let encoded_session_id =
new_session.finish_handshake(&handshake_out).unwrap();
let new_session_id = SessionId::new(
cbor_decoder_from_message(&encoded_session_id)
.u32()
.unwrap()
.try_into()
.unwrap(),
)
.unwrap();
// Check that the new session is operational.
client
.any_command_with_session_info(new_session_id, &mut new_session)
.unwrap();
// Now we have two handles each with their own session. Check that each
// handle works only on its assigned session.
let parent_session_id = client.session_id;
let mut parent_session = client.session_client.clone();
assert_eq!(
ErrCode::InvalidArgument,
client
.any_command_with_handle_and_session_info(
&new_handle,
parent_session_id,
&mut parent_session,
)
.unwrap_err()
);
assert_eq!(
ErrCode::InvalidArgument,
client
.any_command_with_handle_and_session_info(
&new_parent_handle,
new_session_id,
&mut new_session,
)
.unwrap_err()
);
assert_eq!(
ErrCode::InvalidArgument,
client
.any_command_with_handle_and_session_info(
&old_parent_handle,
parent_session_id,
&mut parent_session,
)
.unwrap_err()
);
assert_eq!(
ErrCode::InvalidArgument,
client
.any_command_with_handle_and_session_info(
&old_parent_handle,
new_session_id,
&mut new_session,
)
.unwrap_err()
);
let new_handle = client
.any_command_with_handle_and_session_info(
&new_handle,
new_session_id,
&mut new_session,
)
.unwrap();
assert!(client.is_handle_valid(&new_handle));
let new_parent_handle = client
.any_command_with_handle_and_session_info(
&new_parent_handle,
parent_session_id,
&mut parent_session,
)
.unwrap();
assert!(client.is_handle_valid(&new_parent_handle));
}
#[test]
fn derive_max_contexts() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let mut handle = client.current_context_handle.clone();
for _ in 0..num_handle_contexts() - 1 {
// Keep using the same parent so the cert chain doesn't grow.
let (_, _, new_handle, _, _) = client
.derive_context2(
&options,
Some(&handle),
None,
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
handle = new_handle.unwrap();
}
assert_eq!(
ErrCode::OutOfMemory,
client
.derive_context2(
&options,
Some(&handle),
None,
None,
&get_fake_dice_input(),
None,
None
)
.unwrap_err()
);
}
#[test]
fn derive_to_new_locality_with_handle() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let options: DeriveContextOptions = Default::default();
let handle = client.current_context_handle.clone();
assert_eq!(
client
.get_context_by_handle(&client.current_context_handle)
.locality_id,
LocalityId::new(0).unwrap()
);
let (new_handle, _, _, _, _) = client
.derive_context2(
&options,
Some(&handle),
None,
None,
&get_fake_dice_input(),
None,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
// Use the new handle on the new locality.
let mut new_handle = new_handle.unwrap();
client.session_id = SessionId::get_plain_text();
client.locality_id = LocalityId::new(1).unwrap();
new_handle = client.any_command_with_handle(&new_handle).unwrap();
assert_eq!(
client.get_context_by_handle(&new_handle).locality_id,
LocalityId::new(1).unwrap()
);
}
#[test]
fn derive_default_to_new_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
let _ = client
.derive_context2(
&options,
None,
None,
None,
&get_fake_dice_input(),
None,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
client.session_id = SessionId::get_plain_text();
client.locality_id = LocalityId::new(1).unwrap();
check_context_policies(
client.get_default_context(),
true,
false,
&[0; DPE_MAX_VERSION_SLOTS],
);
assert_eq!(
client.get_default_context().locality_id,
LocalityId::new(1).unwrap()
);
// Check that the new default is operational.
client.derive_context3(&options).unwrap();
// Check that the old default is invalid.
client.session_id = SessionId::new(1).unwrap();
client.locality_id = LocalityId::new(0).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
}
#[test]
fn derive_return_cert() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.return_certificate = true;
let (_, _, _, cert, _) = client
.derive_context2(
&options,
None,
None,
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
assert!(cert.is_some());
options.return_certificate = false;
let (_, _, _, cert, _) = client
.derive_context2(
&options,
None,
None,
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
assert!(cert.is_none());
}
#[test]
fn derive_allow_export() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.allow_new_context_to_export = true;
client.derive_context3(&options).unwrap();
assert_eq!(client.get_default_context().is_export_allowed, true);
options.allow_new_context_to_export = false;
client.derive_context3(&options).unwrap();
assert_eq!(client.get_default_context().is_export_allowed, false);
// Check that we can't go back to true once set to false.
options.allow_new_context_to_export = true;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
}
#[test]
fn derive_export() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.export_cdi = true;
options.allow_new_context_to_export = true;
let (_, _, _, _, cdi) = client
.derive_context2(
&options,
None,
None,
None,
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let cdi = cdi.unwrap();
let mut decoder = cbor_decoder_from_message(&cdi);
assert_eq!(decoder.array().unwrap().unwrap(), 2);
let cdi_sign = Cdi::from_slice(decoder.bytes().unwrap()).unwrap();
let cdi_seal = Cdi::from_slice(decoder.bytes().unwrap()).unwrap();
// Check that the CDIs are different than when not exporting.
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.export_cdi = false;
client.derive_context3(&options).unwrap();
assert_ne!(cdi_sign, client.get_default_context().cdi_sign);
assert_ne!(cdi_seal, client.get_default_context().cdi_seal);
}
#[test]
fn derive_invalid_export() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.export_cdi = true;
// Must allow export
options.allow_new_context_to_export = false;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
options.allow_new_context_to_export = true;
// Must allow derive
options.allow_new_context_to_derive = false;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
options.allow_new_context_to_derive = true;
// Must create certificate
options.create_certificate = false;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
options.create_certificate = true;
// Must not be simulation
let mut client = get_dpe_client_initialized_with(true, true);
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
// Must not create new session
let mut client = get_dpe_client_initialized();
let new_session_handshake =
HandshakeMessage::from_slice(&[0, 0]).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.derive_context2(
&options,
None,
Some(&new_session_handshake),
None,
&get_fake_dice_input(),
None,
None
)
.unwrap_err()
);
if DPE_NUM_LOCALITIES >= 2 {
// Must not target another locality
assert_eq!(
ErrCode::InvalidArgument,
client
.derive_context2(
&options,
None,
None,
None,
&get_fake_dice_input(),
None,
Some(LocalityId::new(1).unwrap()),
)
.unwrap_err()
);
}
}
#[test]
fn derive_recursive_invalid() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.recursive = true;
// Must not retain parent.
options.retain_parent_context = true;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
options.retain_parent_context = false;
// Must not export.
options.export_cdi = true;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
options.export_cdi = false;
// Must not return certificate.
options.return_certificate = true;
assert_eq!(
ErrCode::InvalidArgument,
client.derive_context3(&options).unwrap_err()
);
options.return_certificate = false;
}
#[test]
fn derive_recursive_with_zero_derived_contexts() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.recursive = true;
client.derive_context3(&options).unwrap();
}
#[test]
fn derive_recursive_with_one_derived_context() {
if num_handle_contexts() < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
let handle = client.current_context_handle.clone();
let original_parent_cdi =
client.get_context_by_handle(&handle).cdi_sign.clone();
// Construct a simple tree with two nodes: parent -> derived
options.retain_parent_context = true;
let (derived_handle, parent_handle) =
client.derive_context4(&options, &handle).unwrap();
let original_derived_cdi =
client.get_context_by_handle(&derived_handle).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&derived_handle),
1,
);
options.recursive = true;
options.retain_parent_context = false;
let (parent_handle, _) =
client.derive_context4(&options, &parent_handle).unwrap();
// Expect original derived handle remains valid.
assert!(client.is_handle_valid(&derived_handle));
// Expect both parent and derived CDIs are changed.
assert_ne!(
original_parent_cdi,
client.get_context_by_handle(&parent_handle).cdi_sign
);
assert_ne!(
original_derived_cdi,
client.get_context_by_handle(&derived_handle).cdi_sign
);
}
#[test]
fn derive_recursive_linear() {
if num_handle_contexts() < 4 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
// Construct a linear tree: a -> b -> c -> d
let handle_a = client.current_context_handle.clone();
let original_cdi_a =
client.get_context_by_handle(&handle_a).cdi_sign.clone();
options.retain_parent_context = true;
let (handle_b, handle_a) =
client.derive_context4(&options, &handle_a).unwrap();
let original_cdi_b =
client.get_context_by_handle(&handle_b).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_b),
1,
);
let (handle_c, handle_b) =
client.derive_context4(&options, &handle_b).unwrap();
let original_cdi_c =
client.get_context_by_handle(&handle_c).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_c),
2,
);
let (handle_d, handle_c) =
client.derive_context4(&options, &handle_c).unwrap();
let original_cdi_d =
client.get_context_by_handle(&handle_d).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_d),
3,
);
options.recursive = true;
options.retain_parent_context = false;
let (handle_a, _) =
client.derive_context4(&options, &handle_a).unwrap();
// Expect original derived handles remain valid.
assert!(client.is_handle_valid(&handle_b));
assert!(client.is_handle_valid(&handle_c));
assert!(client.is_handle_valid(&handle_d));
// Expect all CDIs are changed.
assert_ne!(
original_cdi_a,
client.get_context_by_handle(&handle_a).cdi_sign
);
assert_ne!(
original_cdi_b,
client.get_context_by_handle(&handle_b).cdi_sign
);
assert_ne!(
original_cdi_c,
client.get_context_by_handle(&handle_c).cdi_sign
);
assert_ne!(
original_cdi_d,
client.get_context_by_handle(&handle_d).cdi_sign
);
}
#[test]
fn derive_recursive_siblings() {
if num_handle_contexts() < 4 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
// Construct a shallow tree with siblings: a -> b,c,d
let handle_a = client.current_context_handle.clone();
let original_cdi_a =
client.get_context_by_handle(&handle_a).cdi_sign.clone();
options.retain_parent_context = true;
let (handle_b, handle_a) =
client.derive_context4(&options, &handle_a).unwrap();
let original_cdi_b =
client.get_context_by_handle(&handle_b).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_b),
1,
);
let (handle_c, handle_a) =
client.derive_context4(&options, &handle_a).unwrap();
let original_cdi_c =
client.get_context_by_handle(&handle_c).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_c),
1,
);
let (handle_d, handle_a) =
client.derive_context4(&options, &handle_a).unwrap();
let original_cdi_d =
client.get_context_by_handle(&handle_d).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_d),
1,
);
options.recursive = true;
options.retain_parent_context = false;
let (handle_a, _) =
client.derive_context4(&options, &handle_a).unwrap();
// Expect original derived handles remain valid.
assert!(client.is_handle_valid(&handle_b));
assert!(client.is_handle_valid(&handle_c));
assert!(client.is_handle_valid(&handle_d));
// Expect all CDIs are changed.
assert_ne!(
original_cdi_a,
client.get_context_by_handle(&handle_a).cdi_sign
);
assert_ne!(
original_cdi_b,
client.get_context_by_handle(&handle_b).cdi_sign
);
assert_ne!(
original_cdi_c,
client.get_context_by_handle(&handle_c).cdi_sign
);
assert_ne!(
original_cdi_d,
client.get_context_by_handle(&handle_d).cdi_sign
);
}
#[test]
fn derive_recursive_subtree() {
if num_handle_contexts() < 4 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
// Construct a tree with two subtrees: a -> b,c; c -> d
let handle_a = client.current_context_handle.clone();
let original_cdi_a =
client.get_context_by_handle(&handle_a).cdi_sign.clone();
options.retain_parent_context = true;
let (handle_b, handle_a) =
client.derive_context4(&options, &handle_a).unwrap();
let original_cdi_b =
client.get_context_by_handle(&handle_b).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_b),
1,
);
let (handle_c, handle_a) =
client.derive_context4(&options, &handle_a).unwrap();
let original_cdi_c =
client.get_context_by_handle(&handle_c).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_c),
1,
);
let (handle_d, handle_c) =
client.derive_context4(&options, &handle_c).unwrap();
let original_cdi_d =
client.get_context_by_handle(&handle_d).cdi_sign.clone();
client.check_context_depth(
client.get_context_index_by_handle(&handle_d),
2,
);
options.recursive = true;
options.retain_parent_context = false;
let (handle_c, _) =
client.derive_context4(&options, &handle_c).unwrap();
// Expect other handles remain valid.
assert!(client.is_handle_valid(&handle_a));
assert!(client.is_handle_valid(&handle_b));
assert!(client.is_handle_valid(&handle_d));
// Expect only subtree CDIs are changed.
assert_eq!(
original_cdi_a,
client.get_context_by_handle(&handle_a).cdi_sign
);
assert_eq!(
original_cdi_b,
client.get_context_by_handle(&handle_b).cdi_sign
);
assert_ne!(
original_cdi_c,
client.get_context_by_handle(&handle_c).cdi_sign
);
assert_ne!(
original_cdi_d,
client.get_context_by_handle(&handle_d).cdi_sign
);
}
#[test]
fn derive_with_versions() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
let _ = client
.derive_context2(
&options,
None,
None,
Some((0, 4)),
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let _ = client
.derive_context2(
&options,
None,
None,
Some((7, 1234)),
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let mut expected_versions: [u64; DPE_MAX_VERSION_SLOTS] = [0; 16];
expected_versions[0] = 4;
expected_versions[7] = 1234;
assert_eq!(
client.get_default_context().max_versions,
expected_versions
);
}
#[test]
fn derive_with_versions_retain_parent() {
if num_handle_contexts() < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let mut options: DeriveContextOptions = Default::default();
let handle_a = client.current_context_handle.clone();
let (handle_a, _, _, _, _) = client
.derive_context2(
&options,
Some(&handle_a),
None,
Some((0, 4)),
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let handle_a = handle_a.unwrap();
options.retain_parent_context = true;
let (handle_b, _, handle_a, _, _) = client
.derive_context2(
&options,
Some(&handle_a),
None,
Some((7, 1234)),
&get_fake_dice_input(),
None,
None,
)
.unwrap();
let handle_a = handle_a.unwrap();
let handle_b = handle_b.unwrap();
// The first context should have only the first version.
let mut expected_versions_a: [u64; DPE_MAX_VERSION_SLOTS] = [0; 16];
expected_versions_a[0] = 4;
// The second context should have both versions.
let mut expected_versions_b = expected_versions_a.clone();
expected_versions_b[7] = 1234;
assert_eq!(
client.get_context_by_handle(&handle_a).max_versions,
expected_versions_a
);
assert_eq!(
client.get_context_by_handle(&handle_b).max_versions,
expected_versions_b
);
}
#[test]
fn get_certificate_chain_empty() {
let mut client = get_dpe_client_initialized();
check_cert_counts(client.get_default_context(), 0, 0);
let encoded_certificate_chain =
client.get_certificate_chain2(true, false).unwrap();
check_cert_counts(client.get_default_context(), 0, 0);
assert_eq!(
decode_certificate_chain(&encoded_certificate_chain).0.len(),
0
);
}
#[test]
fn get_certificate_chain_single() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
client.derive_context3(&options).unwrap();
check_cert_counts(client.get_default_context(), 1, 0);
let encoded_certificate_chain =
client.get_certificate_chain2(true, false).unwrap();
check_cert_counts(client.get_default_context(), 1, 0);
assert_eq!(
decode_certificate_chain(&encoded_certificate_chain).0.len(),
1
);
}
#[test]
fn get_certificate_chain_multiple() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
for _ in 0..4 {
client.derive_context3(&options).unwrap();
}
check_cert_counts(client.get_default_context(), 4, 0);
let encoded_certificate_chain =
client.get_certificate_chain2(true, false).unwrap();
check_cert_counts(client.get_default_context(), 4, 0);
assert_eq!(
decode_certificate_chain(&encoded_certificate_chain).0.len(),
4
);
}
#[test]
fn get_certificate_chain_retain_context() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
for _ in 0..4 {
client.derive_context3(&options).unwrap();
}
let _ = client.get_certificate_chain2(true, false).unwrap();
assert!(client.get_default_context().initialized);
let _ = client.get_certificate_chain2(false, false).unwrap();
assert!(!client.get_default_context().initialized);
assert_eq!(
ErrCode::InvalidArgument,
client.get_certificate_chain2(false, false).unwrap_err()
);
}
#[test]
fn get_certificate_chain_and_clear() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
for _ in 0..4 {
client.derive_context3(&options).unwrap();
}
let certs = client.get_certificate_chain2(true, true).unwrap();
assert_eq!(decode_certificate_chain(&certs).0.len(), 4);
check_cert_counts(client.get_default_context(), 0, 0);
let certs = client.get_certificate_chain2(true, false).unwrap();
assert_eq!(decode_certificate_chain(&certs).0.len(), 0);
}
#[test]
fn get_certificate_chain_with_handles() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let options: DeriveContextOptions = Default::default();
let mut handle = client.current_context_handle.clone();
for _ in 0..4 {
(handle, _) = client.derive_context4(&options, &handle).unwrap();
}
let mut certs = Default::default();
let mut new_handle = None;
client
.get_certificate_chain(
Some(&handle),
true,
false,
&mut certs,
&mut new_handle,
)
.unwrap();
assert_eq!(decode_certificate_chain(&certs).0.len(), 4);
handle = new_handle.take().unwrap();
let index = client.get_context_index_by_handle(&handle);
// Again but don't retain context.
client
.get_certificate_chain(
Some(&handle),
false,
false,
&mut certs,
&mut new_handle,
)
.unwrap();
assert_eq!(decode_certificate_chain(&certs).0.len(), 4);
assert!(new_handle.is_none());
assert!(!client.is_handle_valid(&handle));
assert!(!client.get_context_by_index(index).initialized);
}
#[test]
fn get_certificate_chain_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
let options: DeriveContextOptions = Default::default();
for _ in 0..4 {
client.derive_context3(&options).unwrap();
}
let encoded_certificate_chain =
client.get_certificate_chain2(false, false).unwrap();
assert_eq!(
decode_certificate_chain(&encoded_certificate_chain).0.len(),
4
);
}
#[test]
fn get_certificate_chain_with_staged() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.create_certificate = false;
for _ in 0..4 {
client.derive_context3(&options).unwrap();
}
check_cert_counts(client.get_default_context(), 0, 4);
// Should fail anytime there is staged cert info.
assert_eq!(
ErrCode::InvalidArgument,
client.get_certificate_chain2(true, false).unwrap_err()
);
options.create_certificate = true;
client.derive_context3(&options).unwrap();
check_cert_counts(client.get_default_context(), 1, 0);
let encoded_certificate_chain =
client.get_certificate_chain2(true, false).unwrap();
assert_eq!(
decode_certificate_chain(&encoded_certificate_chain).0.len(),
1
);
options.create_certificate = false;
client.derive_context3(&options).unwrap();
check_cert_counts(client.get_default_context(), 1, 1);
assert_eq!(
ErrCode::InvalidArgument,
client.get_certificate_chain2(true, false).unwrap_err()
);
}
#[test]
fn get_certificate_chain_check_content() {
let mut client = get_dpe_client_initialized();
let options: DeriveContextOptions = Default::default();
let mut expected_public_keys: Vec<SigningPublicKey, 5> = Vec::new();
expected_public_keys
.push(
client
.dpe
.dice
.derive_eca_key_pair(&client.get_default_context().cdi_sign)
.unwrap()
.0,
)
.unwrap();
for _ in 0..4 {
client.derive_context3(&options).unwrap();
expected_public_keys
.push(
client
.dpe
.dice
.derive_eca_key_pair(
&client.get_default_context().cdi_sign,
)
.unwrap()
.0,
)
.unwrap();
}
let encoded_certificate_chain =
client.get_certificate_chain2(false, false).unwrap();
let certificate_chain =
decode_certificate_chain(&encoded_certificate_chain);
let fake_cert_info = client
.dpe
.dice
.create_certificate_info(&get_fake_dice_input(), &[])
.unwrap();
let mut cert_info_list: CertificateInfoList = Default::default();
cert_info_list.0.push(fake_cert_info.clone()).unwrap();
let mut issuer = 0;
let mut subject = 1;
for cert in &certificate_chain.0 {
debug!("check certificate {}", issuer);
check_cert(
cert,
Some(&expected_public_keys[issuer]),
&expected_public_keys[subject],
&cert_info_list,
&[],
);
issuer += 1;
subject += 1;
}
}
#[test]
fn get_certificate_chain_check_content_combined() {
let mut client = get_dpe_client_initialized();
let mut options: DeriveContextOptions = Default::default();
options.create_certificate = false;
let mut expected_public_keys: Vec<SigningPublicKey, 5> = Vec::new();
expected_public_keys
.push(
client
.dpe
.dice
.derive_eca_key_pair(&client.get_default_context().cdi_sign)
.unwrap()
.0,
)
.unwrap();
for _ in 0..2 {
client.derive_context3(&options).unwrap();
}
options.create_certificate = true;
client.derive_context3(&options).unwrap();
expected_public_keys
.push(
client
.dpe
.dice
.derive_eca_key_pair(&client.get_default_context().cdi_sign)
.unwrap()
.0,
)
.unwrap();
let encoded_certificate_chain =
client.get_certificate_chain2(false, false).unwrap();
let certificate_chain =
decode_certificate_chain(&encoded_certificate_chain);
let fake_cert_info = client
.dpe
.dice
.create_certificate_info(&get_fake_dice_input(), &[])
.unwrap();
let mut cert_info_list: CertificateInfoList = Default::default();
for _ in 0..3 {
cert_info_list.0.push(fake_cert_info.clone()).unwrap();
}
let mut issuer = 0;
let mut subject = 1;
for cert in &certificate_chain.0 {
debug!("check certificate {}", issuer);
check_cert(
cert,
Some(&expected_public_keys[issuer]),
&expected_public_keys[subject],
&cert_info_list,
&[],
);
issuer += 1;
subject += 1;
}
}
#[test]
fn certify_key_default_context() {
let mut client = get_dpe_client_initialized();
let public_key = Default::default();
let (cert, _, handle) = client
.certify_key2(None, true, Some(&public_key), &[], &[])
.unwrap();
assert!(handle.is_none());
assert!(cert.0.len() > 0);
assert!(client.get_default_context().initialized);
// Try again, don't retain
let (cert, _, handle) = client
.certify_key2(None, false, Some(&public_key), &[], &[])
.unwrap();
assert!(handle.is_none());
assert!(cert.0.len() > 0);
assert!(!client.get_default_context().initialized);
}
#[test]
fn certify_key_with_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let public_key = Default::default();
let (cert, _, handle) = client
.certify_key2(Some(&handle), true, Some(&public_key), &[], &[])
.unwrap();
assert!(cert.0.len() > 0);
assert!(client.is_handle_valid(handle.as_ref().unwrap()));
// Try again, don't retain
let (cert, _, handle2) = client
.certify_key2(handle.as_ref(), false, Some(&public_key), &[], &[])
.unwrap();
assert!(cert.0.len() > 0);
assert!(handle2.is_none());
assert!(!client.is_handle_valid(handle.as_ref().unwrap()));
}
#[test]
fn certify_key_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
// Not allowed when providing a public key
let public_key = Default::default();
assert_eq!(
ErrCode::InvalidArgument,
client
.certify_key2(None, true, Some(&public_key), &[], &[])
.unwrap_err()
);
// Try again with a derived public key
let (cert, pubkey, _) =
client.certify_key2(None, true, None, &[], &[]).unwrap();
assert!(cert.0.len() > 0);
assert!(pubkey.is_some() && pubkey.unwrap().len() > 0);
}
#[test]
fn certify_key_external_public_key() {
let mut client = get_dpe_client_initialized();
let expected_issuer = client
.dpe
.dice
.derive_eca_key_pair(&client.get_default_context().cdi_sign)
.unwrap()
.0;
let public_key = Default::default();
let (cert, derived_pubkey, _) = client
.certify_key2(None, true, Some(&public_key), &[], &[])
.unwrap();
assert!(derived_pubkey.is_none());
check_cert(
&cert,
Some(&expected_issuer),
&public_key,
&Default::default(),
&[],
);
}
#[test]
fn certify_key_derived_public_key() {
let mut client = get_dpe_client_initialized();
let expected_issuer = client
.dpe
.dice
.derive_eca_key_pair(&client.get_default_context().cdi_sign)
.unwrap()
.0;
let (cert, derived_public_key, _) =
client.certify_key2(None, true, None, &[], &[]).unwrap();
assert!(derived_public_key.is_some());
check_cert(
&cert,
Some(&expected_issuer),
&derived_public_key.unwrap(),
&Default::default(),
&[],
);
}
#[test]
fn certify_key_different_labels() {
let mut client = get_dpe_client_initialized();
let (cert1, derived_public_key1, _) = client
.certify_key2(None, true, None, &"label1".as_bytes(), &[])
.unwrap();
let (cert2, derived_public_key2, _) = client
.certify_key2(None, true, None, &"label2".as_bytes(), &[])
.unwrap();
assert_ne!(&cert1, &cert2);
assert_ne!(&derived_public_key1, &derived_public_key2);
}
#[test]
fn certify_key_additional_info() {
let mut client = get_dpe_client_initialized();
let fake_info = &"fake_info".as_bytes();
let (cert, pubkey, _) =
client.certify_key2(None, true, None, &[], fake_info).unwrap();
let pubkey = pubkey.unwrap();
check_cert(&cert, None, &pubkey, &Default::default(), fake_info);
}
#[test]
fn sign_default_context() {
let mut client = get_dpe_client_initialized();
let (signature, handle) =
client.sign2(None, true, &[], false, &[]).unwrap();
assert!(handle.is_none());
assert!(signature.len() > 0);
assert!(client.get_default_context().initialized);
// Try again, don't retain
let (signature, handle) =
client.sign2(None, false, &[], false, &[]).unwrap();
assert!(handle.is_none());
assert!(signature.len() > 0);
assert!(!client.get_default_context().initialized);
}
#[test]
fn sign_with_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let (signature, handle) =
client.sign2(Some(&handle), true, &[], false, &[]).unwrap();
assert!(handle.is_some());
let handle = handle.unwrap();
assert!(signature.len() > 0);
assert!(client.is_handle_valid(&handle));
// Try again, don't retain
let (signature, handle2) =
client.sign2(Some(&handle), false, &[], false, &[]).unwrap();
assert!(signature.len() > 0);
assert!(handle2.is_none());
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn sign_with_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
assert_eq!(
ErrCode::InvalidArgument,
client.sign2(None, true, &[], false, &[]).unwrap_err()
);
}
#[test]
fn sign_with_different_labels() {
let mut client = get_dpe_client_initialized();
let (signature1, _) =
client.sign2(None, true, &"label1".as_bytes(), false, &[]).unwrap();
let (signature2, _) =
client.sign2(None, true, &"label2".as_bytes(), false, &[]).unwrap();
assert_ne!(signature1, signature2);
}
#[test]
fn sign_and_verify() {
let mut client = get_dpe_client_initialized();
let (_, public_key_opt, _) =
client.certify_key2(None, true, None, &[], &[]).unwrap();
let public_key = ed25519_dalek::VerifyingKey::try_from(
public_key_opt.unwrap().as_slice(),
)
.unwrap();
let message = "fake_message".as_bytes();
let (signature, _) =
client.sign2(None, false, &[], false, message).unwrap();
public_key
.verify_strict(
message,
&ed25519_dalek::Signature::try_from(signature.as_slice())
.unwrap(),
)
.unwrap();
}
#[test]
fn sign_symmetric() {
let mut client = get_dpe_client_initialized();
let (signature, _) = client.sign2(None, false, &[], true, &[]).unwrap();
assert_eq!(signature.len(), HASH_SIZE);
}
#[test]
fn seal_default_context() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let (sealed, handle) =
client.seal2(None, true, policy.as_slice(), &[], &[]).unwrap();
assert!(handle.is_none());
assert!(sealed.len() > 0);
assert!(client.get_default_context().initialized);
// Try again, don't retain
let (sealed, handle) =
client.seal2(None, false, policy.as_slice(), &[], &[]).unwrap();
assert!(handle.is_none());
assert!(sealed.len() > 0);
assert!(!client.get_default_context().initialized);
}
#[test]
fn seal_with_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let policy = get_empty_unseal_policy();
let (sealed, handle) = client
.seal2(Some(&handle), true, policy.as_slice(), &[], &[])
.unwrap();
assert!(handle.is_some());
let handle = handle.unwrap();
assert!(sealed.len() > 0);
assert!(client.is_handle_valid(&handle));
// Try again, don't retain
let (sealed, handle2) = client
.seal2(Some(&handle), false, policy.as_slice(), &[], &[])
.unwrap();
assert!(sealed.len() > 0);
assert!(handle2.is_none());
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn seal_with_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (sealed1, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
// Should match the value without simulation.
let mut client = get_dpe_client_initialized();
let (sealed2, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
assert_eq!(sealed1, sealed2);
}
#[test]
fn seal_with_different_labels() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let label1 = "label1".as_bytes();
let label2 = "label2".as_bytes();
let (sealed1, _) =
client.seal2(None, true, policy.as_slice(), label1, data).unwrap();
let (sealed2, _) =
client.seal2(None, true, policy.as_slice(), label2, data).unwrap();
assert_ne!(sealed1, sealed2);
}
#[test]
fn seal_with_different_policies() {
let mut client = get_dpe_client_initialized();
let mut versions: [u64; DPE_MAX_VERSION_SLOTS] = Default::default();
versions[5] = 1234;
let policy1 = encode_unseal_policy(&versions);
versions[12] = 7;
let policy2 = encode_unseal_policy(&versions);
let data = "fake_data_to_seal".as_bytes();
let (sealed1, _) =
client.seal2(None, true, policy1.as_slice(), &[], data).unwrap();
let (sealed2, _) =
client.seal2(None, true, policy2.as_slice(), &[], data).unwrap();
assert_ne!(sealed1, sealed2);
}
#[test]
fn seal_with_bad_policy_encoding() {
let mut client = get_dpe_client_initialized();
assert_eq!(
ErrCode::InvalidArgument,
client.seal2(None, true, &[], &[], &[]).unwrap_err()
);
}
#[test]
fn seal_with_unsupported_policy() {
let mut client = get_dpe_client_initialized();
let mut policy = SmallMessage::new();
let _ = cbor_encoder_from_message(&mut policy)
.map(1)
.unwrap()
.u16(1000)
.unwrap()
.u64(1001)
.unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client.seal2(None, true, policy.as_slice(), &[], &[]).unwrap_err()
);
}
#[test]
fn seal_and_unseal() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
let (unsealed, _) = client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert_eq!(data, unsealed.as_slice());
}
#[test]
fn seal_only_future_versions_can_unseal() {
let mut client = get_dpe_client_initialized();
client.get_default_context_mut().max_versions[0] = 1;
let mut versions: [u64; DPE_MAX_VERSION_SLOTS] = Default::default();
versions[0] = 2;
let policy = encode_unseal_policy(&versions);
let data = "fake_data_to_seal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
// The current version cannot unseal.
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice()
)
.unwrap_err()
);
// But if we update to the new version, the same unseal should work.
client.get_default_context_mut().max_versions[0] = 2;
let (unsealed, _) = client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert_eq!(data, unsealed.as_slice());
}
#[test]
fn seal_past_versions_can_unseal() {
let mut client = get_dpe_client_initialized();
client.get_default_context_mut().max_versions[0] = 4;
let mut versions: [u64; DPE_MAX_VERSION_SLOTS] = Default::default();
versions[0] = 2;
let policy = encode_unseal_policy(&versions);
let data = "fake_data_to_seal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
// Even if we move from v4 -> v2 unseal should still work.
client.get_default_context_mut().max_versions[0] = 2;
let (unsealed, _) = client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert_eq!(data, unsealed.as_slice());
}
#[test]
fn seal_and_unseal_label_mismatch() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let label1 = "label1".as_bytes();
let label2 = "label2".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), label1, data).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
false,
policy.as_slice(),
label2,
sealed.as_slice(),
)
.unwrap_err()
);
}
#[test]
fn seal_and_unseal_policy_mismatch() {
let mut client = get_dpe_client_initialized();
// Set up the state so both policies are met.
client.get_default_context_mut().max_versions[14] = 4;
client.get_default_context_mut().max_versions[12] = 7;
let mut versions: [u64; DPE_MAX_VERSION_SLOTS] = Default::default();
versions[14] = 4;
let policy1 = encode_unseal_policy(&versions);
versions[12] = 7;
let policy2 = encode_unseal_policy(&versions);
let data = "fake_data_to_seal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy1.as_slice(), &[], data).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
false,
policy2.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap_err()
);
}
#[test]
fn seal_and_unseal_context_mismatch() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
client.derive_context3(&Default::default()).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap_err()
);
}
#[test]
fn seal_and_unseal_asymmetric() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (public_key, _) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), &[])
.unwrap();
let mut sealed = Message::from_slice(data).unwrap();
CryptoForTesting::seal_asymmetric(&public_key, &mut sealed).unwrap();
let (unsealed, _) = client
.unseal2(
None,
true,
true,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert_eq!(data, unsealed.as_slice());
}
#[test]
fn seal_and_unseal_type_mismatch() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (sealed_symmetric, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
let (public_key, _) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), &[])
.unwrap();
let mut sealed_asymmetric = Message::from_slice(data).unwrap();
CryptoForTesting::seal_asymmetric(&public_key, &mut sealed_asymmetric)
.unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
true,
policy.as_slice(),
&[],
sealed_symmetric.as_slice(),
)
.unwrap_err()
);
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed_asymmetric.as_slice(),
)
.unwrap_err()
);
}
#[test]
fn unseal_default_context() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
let (unsealed, handle) = client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert!(handle.is_none());
assert_eq!(unsealed.as_slice(), data);
assert!(client.get_default_context().initialized);
// Try again, don't retain
let (unsealed, handle) = client
.unseal2(
None,
false,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert!(handle.is_none());
assert_eq!(unsealed.as_slice(), data);
assert!(!client.get_default_context().initialized);
}
#[test]
fn unseal_with_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let policy = get_empty_unseal_policy();
let data = "fake_data_to_seal".as_bytes();
let (sealed, handle) = client
.seal2(Some(&handle), true, policy.as_slice(), &[], data)
.unwrap();
let handle = handle.unwrap();
let (unsealed, handle) = client
.unseal2(
Some(&handle),
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert!(handle.is_some());
let handle = handle.unwrap();
assert_eq!(unsealed.as_slice(), data);
assert!(client.is_handle_valid(&handle));
// Try again, don't retain
let (unsealed, handle2) = client
.unseal2(
Some(&handle),
false,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap();
assert_eq!(unsealed.as_slice(), data);
assert!(handle2.is_none());
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn unseal_with_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
let policy = get_empty_unseal_policy();
let data = "fake_data_to_unseal".as_bytes();
let (sealed, _) =
client.seal2(None, true, policy.as_slice(), &[], data).unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(
None,
true,
false,
policy.as_slice(),
&[],
sealed.as_slice(),
)
.unwrap_err()
);
}
#[test]
fn unseal_with_bad_policy_encoding() {
let mut client = get_dpe_client_initialized();
assert_eq!(
ErrCode::InvalidArgument,
client.unseal2(None, true, false, &[], &[], &[]).unwrap_err()
);
}
#[test]
fn unseal_with_unsupported_policy() {
let mut client = get_dpe_client_initialized();
let mut policy = SmallMessage::new();
let _ = cbor_encoder_from_message(&mut policy)
.map(1)
.unwrap()
.u16(1000)
.unwrap()
.u64(1001)
.unwrap();
assert_eq!(
ErrCode::InvalidArgument,
client
.unseal2(None, true, false, policy.as_slice(), &[], &[])
.unwrap_err()
);
}
#[test]
fn derive_sealing_public_key_default_context() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let (public_key, handle) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), &[])
.unwrap();
assert!(handle.is_none());
assert!(public_key.len() > 0);
assert!(client.get_default_context().initialized);
// Try again, don't retain
let (public_key, handle) = client
.derive_sealing_public_key2(None, false, policy.as_slice(), &[])
.unwrap();
assert!(handle.is_none());
assert!(public_key.len() > 0);
assert!(!client.get_default_context().initialized);
}
#[test]
fn derive_sealing_public_key_with_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let policy = get_empty_unseal_policy();
let (public_key, handle) = client
.derive_sealing_public_key2(
Some(&handle),
true,
policy.as_slice(),
&[],
)
.unwrap();
assert!(handle.is_some());
let handle = handle.unwrap();
assert!(public_key.len() > 0);
assert!(client.is_handle_valid(&handle));
// Try again, don't retain
let (public_key, handle2) = client
.derive_sealing_public_key2(
Some(&handle),
false,
policy.as_slice(),
&[],
)
.unwrap();
assert!(public_key.len() > 0);
assert!(handle2.is_none());
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn derive_sealing_public_key_with_simulation() {
let mut client = get_dpe_client_initialized_with(true, true);
let policy = get_empty_unseal_policy();
let (public_key1, _) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), &[])
.unwrap();
// Should match the value without simulation.
let mut client = get_dpe_client_initialized();
let (public_key2, _) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), &[])
.unwrap();
assert_eq!(public_key1, public_key2);
}
#[test]
fn derive_sealing_public_key_with_different_labels() {
let mut client = get_dpe_client_initialized();
let policy = get_empty_unseal_policy();
let label1 = "label1".as_bytes();
let label2 = "label2".as_bytes();
let (public_key1, _) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), label1)
.unwrap();
let (public_key2, _) = client
.derive_sealing_public_key2(None, true, policy.as_slice(), label2)
.unwrap();
assert_ne!(public_key1, public_key2);
}
#[test]
fn derive_sealing_public_key_with_different_policies() {
let mut client = get_dpe_client_initialized();
let mut versions: [u64; DPE_MAX_VERSION_SLOTS] = Default::default();
versions[5] = 1234;
let policy1 = encode_unseal_policy(&versions);
versions[12] = 7;
let policy2 = encode_unseal_policy(&versions);
let (public_key1, _) = client
.derive_sealing_public_key2(None, true, policy1.as_slice(), &[])
.unwrap();
let (public_key2, _) = client
.derive_sealing_public_key2(None, true, policy2.as_slice(), &[])
.unwrap();
assert_ne!(public_key1, public_key2);
}
#[test]
fn rotate_context_handle_basic() {
if num_handle_contexts() < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let handle2 = client
.rotate_context_handle(Some(&handle), false, None)
.unwrap()
.unwrap();
assert!(client.is_handle_valid(&handle2));
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn rotate_context_handle_invalid_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let _ = client
.rotate_context_handle(Some(&handle), false, None)
.unwrap()
.unwrap();
assert!(!client.is_handle_valid(&handle));
assert_eq!(
ErrCode::InvalidArgument,
client
.rotate_context_handle(Some(&handle), false, None)
.unwrap_err()
);
}
#[test]
fn rotate_context_handle_from_default() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized();
let handle =
client.rotate_context_handle(None, false, None).unwrap().unwrap();
assert!(client.is_handle_valid(&handle));
assert!(!client.get_default_context().initialized);
}
#[test]
fn rotate_context_handle_to_default() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let handle2 =
client.rotate_context_handle(Some(&handle), true, None).unwrap();
assert!(handle2.is_none());
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn rotate_context_handle_default_to_default_self() {
let mut client = get_dpe_client_initialized();
assert_eq!(
ErrCode::InvalidArgument,
client.rotate_context_handle(None, true, None).unwrap_err()
);
}
#[test]
fn rotate_context_handle_default_to_default_new_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let handle = client
.rotate_context_handle(
None,
true,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
assert!(handle.is_none());
assert!(!client.get_default_context().initialized);
client.locality_id = LocalityId::new(1).unwrap();
client.session_id = SessionId::get_plain_text();
let context = client.get_default_context();
assert!(context.initialized);
assert_eq!(context.locality_id, LocalityId::new(1).unwrap());
assert_eq!(context.session_id, SessionId::get_plain_text());
}
#[test]
fn rotate_context_handle_default_to_handle_new_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let handle = client
.rotate_context_handle(
None,
false,
Some(LocalityId::new(1).unwrap()),
)
.unwrap()
.unwrap();
assert!(client.is_handle_valid(&handle));
assert!(!client.get_default_context().initialized);
client.locality_id = LocalityId::new(1).unwrap();
client.session_id = SessionId::get_plain_text();
assert!(!client.get_default_context().initialized);
let handle = client.any_command_with_handle(&handle).unwrap();
let context = client.get_context_by_handle(&handle);
assert!(context.initialized);
assert_eq!(context.locality_id, LocalityId::new(1).unwrap());
assert_eq!(context.session_id, SessionId::get_plain_text());
}
#[test]
fn rotate_context_handle_to_default_new_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let handle2 = client
.rotate_context_handle(
Some(&handle),
true,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
assert!(!client.is_handle_valid(&handle));
assert!(handle2.is_none());
assert!(!client.get_default_context().initialized);
client.locality_id = LocalityId::new(1).unwrap();
client.session_id = SessionId::get_plain_text();
client.any_command().unwrap();
let context = client.get_default_context();
assert!(context.initialized);
assert_eq!(context.locality_id, LocalityId::new(1).unwrap());
assert_eq!(context.session_id, SessionId::get_plain_text());
}
#[test]
fn rotate_context_handle_new_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let handle2 = client
.rotate_context_handle(
Some(&handle),
false,
Some(LocalityId::new(1).unwrap()),
)
.unwrap()
.unwrap();
assert!(client.is_handle_valid(&handle2));
assert!(!client.is_handle_valid(&handle));
assert_eq!(
ErrCode::InvalidArgument,
client.any_command_with_handle(&handle2).unwrap_err()
);
client.locality_id = LocalityId::new(1).unwrap();
client.session_id = SessionId::get_plain_text();
let handle = client.any_command_with_handle(&handle2).unwrap();
let context = client.get_context_by_handle(&handle);
assert!(context.initialized);
assert_eq!(context.locality_id, LocalityId::new(1).unwrap());
assert_eq!(context.session_id, SessionId::get_plain_text());
}
#[test]
fn rotate_context_handle_to_locality_zero() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let _ = client
.rotate_context_handle(
None,
true,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
client.locality_id = LocalityId::new(1).unwrap();
client.session_id = SessionId::get_plain_text();
assert_eq!(
ErrCode::InvalidArgument,
client
.rotate_context_handle(
None,
true,
Some(LocalityId::new(0).unwrap())
)
.unwrap_err()
);
}
#[test]
fn rotate_context_handle_reparent() {
if num_handle_contexts() < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let (derived_handle, parent_handle) =
client.derive_context4(&options, &handle).unwrap();
let parent_index = client.get_context_index_by_handle(&parent_handle);
let derived_index = client.get_context_index_by_handle(&derived_handle);
assert_eq!(
client.get_context_by_index(derived_index).parent,
Some(parent_index)
);
let _ = client.rotate_context_handle(Some(&parent_handle), true, None);
let new_parent_index = client.get_default_context_index();
assert_ne!(parent_index, new_parent_index);
assert_eq!(
client.get_context_by_index(derived_index).parent,
Some(new_parent_index)
);
}
#[test]
fn destroy_context_default() {
let mut client = get_dpe_client_initialized();
assert!(client.get_default_context().initialized);
client.destroy_context(None, false).unwrap();
assert!(!client.get_default_context().initialized);
}
#[test]
fn destroy_context_handle() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
assert!(client.is_handle_valid(&handle));
client.destroy_context(Some(&handle), false).unwrap();
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn destroy_context_simulation() {
let mut client = get_dpe_client_initialized_with(false, true);
let handle = client.current_context_handle.clone();
assert!(client.is_handle_valid(&handle));
client.destroy_context(Some(&handle), false).unwrap();
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn destroy_context_other_locality() {
if DPE_NUM_LOCALITIES < 2 {
return;
}
let mut client = get_dpe_client_initialized();
let _ = client
.rotate_context_handle(
None,
true,
Some(LocalityId::new(1).unwrap()),
)
.unwrap();
client.locality_id = LocalityId::new(1).unwrap();
client.session_id = SessionId::get_plain_text();
assert!(client.get_default_context().initialized);
client.destroy_context(None, false).unwrap();
assert!(!client.get_default_context().initialized);
}
#[test]
fn destroy_context_reparent_to_no_parent() {
if num_handle_contexts() < 2 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let (derived_handle, parent_handle) =
client.derive_context4(&options, &handle).unwrap();
let parent_index = client.get_context_index_by_handle(&parent_handle);
let derived_index = client.get_context_index_by_handle(&derived_handle);
assert_eq!(
client.get_context_by_index(derived_index).parent,
Some(parent_index)
);
client.check_context_depth(derived_index, 1);
client.destroy_context(Some(&parent_handle), false).unwrap();
assert!(!client.is_handle_valid(&parent_handle));
assert!(client.is_handle_valid(&derived_handle));
client.check_context_depth(derived_index, 0);
}
#[test]
fn destroy_context_reparent_to_next_parent() {
if num_handle_contexts() < 3 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let level1_handle = client.current_context_handle.clone();
let level1_index = client.get_context_index_by_handle(&level1_handle);
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let (level2_handle, level1_handle) =
client.derive_context4(&options, &level1_handle).unwrap();
let level2_index = client.get_context_index_by_handle(&level2_handle);
let (level3_handle, level2_handle) =
client.derive_context4(&options, &level2_handle).unwrap();
let level3_index = client.get_context_index_by_handle(&level3_handle);
client.check_context_depth(level1_index, 0);
client.check_context_depth(level2_index, 1);
client.check_context_depth(level3_index, 2);
client.destroy_context(Some(&level2_handle), false).unwrap();
assert!(!client.is_handle_valid(&level2_handle));
assert!(client.is_handle_valid(&level1_handle));
assert!(client.is_handle_valid(&level3_handle));
client.check_context_depth(level3_index, 1);
assert_eq!(
client.get_context_by_index(level3_index).parent,
Some(level1_index)
);
}
#[test]
fn destroy_context_reparent_forked() {
if num_handle_contexts() < 4 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let level1_handle = client.current_context_handle.clone();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let (level2_handle, level1_handle) =
client.derive_context4(&options, &level1_handle).unwrap();
let (level3_handle, level2_handle) =
client.derive_context4(&options, &level2_handle).unwrap();
let (level3b_handle, level2_handle) =
client.derive_context4(&options, &level2_handle).unwrap();
let level1_index = client.get_context_index_by_handle(&level1_handle);
let level2_index = client.get_context_index_by_handle(&level2_handle);
let level3_index = client.get_context_index_by_handle(&level3_handle);
let level3b_index = client.get_context_index_by_handle(&level3b_handle);
client.check_context_depth(level1_index, 0);
client.check_context_depth(level2_index, 1);
client.check_context_depth(level3_index, 2);
client.check_context_depth(level3b_index, 2);
client.destroy_context(Some(&level2_handle), false).unwrap();
assert!(!client.is_handle_valid(&level2_handle));
assert!(client.is_handle_valid(&level1_handle));
assert!(client.is_handle_valid(&level3_handle));
assert!(client.is_handle_valid(&level3b_handle));
client.check_context_depth(level3_index, 1);
client.check_context_depth(level3b_index, 1);
assert_eq!(
client.get_context_by_index(level3_index).parent,
Some(level1_index)
);
assert_eq!(
client.get_context_by_index(level3b_index).parent,
Some(level1_index)
);
}
#[test]
fn destroy_context_recursive_none_derived() {
if num_handle_contexts() < 1 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let handle = client.current_context_handle.clone();
client.destroy_context(Some(&handle), true).unwrap();
assert!(!client.is_handle_valid(&handle));
}
#[test]
fn destroy_context_recursive_single_path() {
if num_handle_contexts() < 3 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let level1_handle = client.current_context_handle.clone();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let (level2_handle, level1_handle) =
client.derive_context4(&options, &level1_handle).unwrap();
let (level3_handle, level2_handle) =
client.derive_context4(&options, &level2_handle).unwrap();
let level1_index = client.get_context_index_by_handle(&level1_handle);
let level2_index = client.get_context_index_by_handle(&level2_handle);
let level3_index = client.get_context_index_by_handle(&level3_handle);
client.check_context_depth(level1_index, 0);
client.check_context_depth(level2_index, 1);
client.check_context_depth(level3_index, 2);
client.destroy_context(Some(&level1_handle), true).unwrap();
assert!(!client.is_handle_valid(&level2_handle));
assert!(!client.is_handle_valid(&level1_handle));
assert!(!client.is_handle_valid(&level3_handle));
}
#[test]
fn destroy_context_recursive_forked() {
if num_handle_contexts() < 4 {
return;
}
let mut client = get_dpe_client_initialized_with(false, false);
let level1_handle = client.current_context_handle.clone();
let mut options: DeriveContextOptions = Default::default();
options.retain_parent_context = true;
let (level2_handle, level1_handle) =
client.derive_context4(&options, &level1_handle).unwrap();
let (level3_handle, level2_handle) =
client.derive_context4(&options, &level2_handle).unwrap();
let (level3b_handle, level2_handle) =
client.derive_context4(&options, &level2_handle).unwrap();
let level1_index = client.get_context_index_by_handle(&level1_handle);
let level2_index = client.get_context_index_by_handle(&level2_handle);
let level3_index = client.get_context_index_by_handle(&level3_handle);
let level3b_index = client.get_context_index_by_handle(&level3b_handle);
client.check_context_depth(level1_index, 0);
client.check_context_depth(level2_index, 1);
client.check_context_depth(level3_index, 2);
client.check_context_depth(level3b_index, 2);
client.destroy_context(Some(&level2_handle), true).unwrap();
assert!(client.is_handle_valid(&level1_handle));
assert!(!client.is_handle_valid(&level2_handle));
assert!(!client.is_handle_valid(&level3_handle));
assert!(!client.is_handle_valid(&level3b_handle));
}
}