Skip to content

Commit

Permalink
Add is_certificate and export_cdi flags to DeriveContext
Browse files Browse the repository at this point in the history
As well as other boiler plate work to make sure the invariants laid out
in the spec are enforced.
  • Loading branch information
clundin25 committed Dec 26, 2024
1 parent af0251e commit 637686d
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 4 deletions.
1 change: 1 addition & 0 deletions dpe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ disable_csr = []
disable_internal_info = []
disable_internal_dice = []
disable_retain_parent_context = []
disable_export_cdi = []
no-cfi = ["crypto/no-cfi"]

[dependencies]
Expand Down
154 changes: 151 additions & 3 deletions dpe/src/commands/derive_context.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Licensed under the Apache-2.0 license.
use super::CommandExecution;
use crate::{
context::{ActiveContextArgs, Context, ContextHandle, ContextState},
context::{ActiveContextArgs, Context, ContextHandle, ContextState, ContextType},
dpe_instance::{DpeEnv, DpeInstance, DpeTypes},
response::{DeriveContextResp, DpeErrorCode, Response, ResponseHdr},
tci::TciMeasurement,
DPE_PROFILE,
DPE_PROFILE, MAX_CERT_SIZE, MAX_EXPORTED_CDI_SIZE,
};
use bitflags::bitflags;
#[cfg(not(feature = "no-cfi"))]
Expand Down Expand Up @@ -36,6 +36,9 @@ bitflags! {
const INPUT_ALLOW_CA = 1u32 << 26;
const INPUT_ALLOW_X509 = 1u32 << 25;
const RECURSIVE = 1u32 << 24;
const EXPORT_CDI = 1u32 << 23;
const CREATE_CERTIFICATE = 1u32 << 22;
const RETURN_CERTIFICATE = 1u32 << 21;
}
}

Expand Down Expand Up @@ -91,6 +94,18 @@ impl DeriveContextCmd {
self.flags.contains(DeriveContextFlags::RECURSIVE)
}

pub const fn allows_exports_cdi(&self) -> bool {
self.flags.contains(DeriveContextFlags::EXPORT_CDI)
}

pub const fn allows_create_certificate(&self) -> bool {
self.flags.contains(DeriveContextFlags::CREATE_CERTIFICATE)
}

pub const fn allows_return_certificate(&self) -> bool {
self.flags.contains(DeriveContextFlags::RETURN_CERTIFICATE)
}

/// Whether it is okay to make a default context.
///
/// When a default context is in a locality, it MUST be the only context in the locality. This
Expand Down Expand Up @@ -196,6 +211,8 @@ impl CommandExecution for DeriveContextCmd {
|| (!dpe.support.internal_dice() && self.uses_internal_dice_input())
|| (!dpe.support.retain_parent_context() && self.retains_parent())
|| (!dpe.support.x509() && self.allows_x509())
|| (!dpe.support.cdi_export()
&& (self.allows_create_certificate() && self.allows_exports_cdi()))
|| (!dpe.support.recursive() && self.is_recursive())
{
return Err(DpeErrorCode::ArgumentNotSupported);
Expand All @@ -204,6 +221,11 @@ impl CommandExecution for DeriveContextCmd {
let parent_idx = dpe.get_active_context_pos(&self.handle, locality)?;
if (!dpe.contexts[parent_idx].allow_ca() && self.allows_ca())
|| (!dpe.contexts[parent_idx].allow_x509() && self.allows_x509())
|| (self.allows_exports_cdi() && !self.allows_create_certificate())
|| (self.allows_exports_cdi() && self.is_recursive())
|| (self.allows_exports_cdi() && self.changes_locality())
|| (self.allows_exports_cdi()
&& dpe.contexts[parent_idx].context_type == ContextType::Simulation)
|| (self.is_recursive() && self.retains_parent())
{
return Err(DpeErrorCode::InvalidArgument);
Expand Down Expand Up @@ -262,11 +284,17 @@ impl CommandExecution for DeriveContextCmd {
// Should be ignored since retain_parent cannot be true
parent_handle: ContextHandle::default(),
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE]
}))
} else {
Err(DpeErrorCode::ArgumentNotSupported)?
}
}
// TODO(clundin): Take another look at specifications to make sure my usage of create_certificate & exports_cdi flags makes sense.
} else if self.allows_create_certificate() && self.allows_exports_cdi() {
todo!("(clundin): Generate ECA certificiate / export random CDI")
} else {
let child_idx = dpe
.get_next_inactive_context_pos()
Expand Down Expand Up @@ -346,6 +374,9 @@ impl CommandExecution for DeriveContextCmd {
handle: child_handle,
parent_handle: dpe.contexts[parent_idx].handle,
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE],
}))
}
}
Expand All @@ -363,7 +394,7 @@ mod tests {
context::ContextType,
dpe_instance::tests::{TestTypes, RANDOM_HANDLE, SIMULATION_HANDLE, TEST_LOCALITIES},
support::Support,
MAX_HANDLES,
MAX_CERT_SIZE, MAX_HANDLES,
};
use caliptra_cfi_lib_git::CfiCounter;
use crypto::{Crypto, Hasher, OpensslCrypto};
Expand Down Expand Up @@ -596,6 +627,9 @@ mod tests {
handle: ContextHandle::default(),
parent_handle: ContextHandle([0xff; ContextHandle::SIZE]),
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE]
})),
DeriveContextCmd {
handle: ContextHandle::default(),
Expand All @@ -613,6 +647,9 @@ mod tests {
handle: RANDOM_HANDLE,
parent_handle: ContextHandle([0xff; ContextHandle::SIZE]),
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE]
})),
DeriveContextCmd {
handle: ContextHandle::default(),
Expand Down Expand Up @@ -741,6 +778,9 @@ mod tests {
handle: ContextHandle::default(),
parent_handle: ContextHandle([0xff; ContextHandle::SIZE]),
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE]
})),
DeriveContextCmd {
handle: ContextHandle::default(),
Expand All @@ -758,6 +798,9 @@ mod tests {
handle: ContextHandle::default(),
parent_handle: ContextHandle::default(),
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE]
})),
DeriveContextCmd {
handle: ContextHandle::default(),
Expand All @@ -784,6 +827,7 @@ mod tests {
handle,
parent_handle,
resp_hdr,
..
}) = DeriveContextCmd {
handle: dpe.contexts[old_default_idx].handle,
data: [0; DPE_PROFILE.get_tci_size()],
Expand Down Expand Up @@ -947,6 +991,9 @@ mod tests {
handle: ContextHandle::default(),
parent_handle: ContextHandle::default(),
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
exported_cdi: [0; MAX_EXPORTED_CDI_SIZE],
certificate_size: 0,
new_certificate: [0; MAX_CERT_SIZE]
})),
DeriveContextCmd {
handle: ContextHandle::default(),
Expand Down Expand Up @@ -996,4 +1043,105 @@ mod tests {
let digest = hasher_2.finish().unwrap();
assert_eq!(digest.bytes(), dpe.contexts[child_idx].tci.tci_cumulative.0);
}

#[test]
fn test_cdi_export_flags() {
CfiCounter::reset_for_test();
let mut env = DpeEnv::<TestTypes> {
crypto: OpensslCrypto::new(),
platform: DefaultPlatform,
};
let mut dpe = DpeInstance::new(
&mut env,
Support::AUTO_INIT
| Support::CDI_EXPORT
| Support::X509
| Support::RECURSIVE
| Support::SIMULATION,
)
.unwrap();
assert_eq!(
Err(DpeErrorCode::InvalidArgument),
DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::EXPORT_CDI | DeriveContextFlags::CHANGE_LOCALITY,
tci_type: 0,
target_locality: TEST_LOCALITIES[1]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
);
assert_eq!(
Err(DpeErrorCode::InvalidArgument),
DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::EXPORT_CDI | DeriveContextFlags::RECURSIVE,
tci_type: 0,
target_locality: TEST_LOCALITIES[0]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
);
let simulation_handle = match InitCtxCmd::new_simulation()
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
.unwrap()
{
Response::InitCtx(resp) => resp.handle,
_ => panic!("Wrong response type."),
};
assert_eq!(
Err(DpeErrorCode::InvalidArgument),
DeriveContextCmd {
handle: simulation_handle,
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::CREATE_CERTIFICATE | DeriveContextFlags::EXPORT_CDI,
tci_type: 0,
target_locality: TEST_LOCALITIES[0]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
);
assert!(DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::CREATE_CERTIFICATE | DeriveContextFlags::EXPORT_CDI,
tci_type: 0,
target_locality: TEST_LOCALITIES[0]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
.is_ok());

dpe = DpeInstance::new(
&mut env,
Support::AUTO_INIT | Support::CDI_EXPORT | Support::X509,
)
.unwrap();

assert!(DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::EXPORT_CDI,
tci_type: 0,
target_locality: TEST_LOCALITIES[0]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
.is_ok());

let mut dpe = DpeInstance::new(
&mut env,
Support::AUTO_INIT | Support::INTERNAL_INFO | Support::INTERNAL_DICE | Support::X509,
)
.unwrap();

assert_eq!(
Err(DpeErrorCode::ArgumentNotSupported),
DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::CREATE_CERTIFICATE | DeriveContextFlags::EXPORT_CDI,
tci_type: 0,
target_locality: TEST_LOCALITIES[0]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
);
}
}
2 changes: 2 additions & 0 deletions dpe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub mod x509;

use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};

const MAX_EXPORTED_CDI_SIZE: usize = 256;

// Max cert size returned by CertifyKey
const MAX_CERT_SIZE: usize = 6144;
#[cfg(not(feature = "arbitrary_max_handles"))]
Expand Down
5 changes: 4 additions & 1 deletion dpe/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Abstract:
--*/
use crate::{
context::ContextHandle, validation::ValidationError, CURRENT_PROFILE_MAJOR_VERSION,
CURRENT_PROFILE_MINOR_VERSION, DPE_PROFILE, MAX_CERT_SIZE, MAX_HANDLES,
CURRENT_PROFILE_MINOR_VERSION, DPE_PROFILE, MAX_CERT_SIZE, MAX_EXPORTED_CDI_SIZE, MAX_HANDLES,
};
use crypto::CryptoError;
use platform::{PlatformError, MAX_CHUNK_SIZE};
Expand Down Expand Up @@ -139,6 +139,9 @@ pub struct DeriveContextResp {
pub resp_hdr: ResponseHdr,
pub handle: ContextHandle,
pub parent_handle: ContextHandle,
pub exported_cdi: [u8; MAX_EXPORTED_CDI_SIZE],
pub certificate_size: u32,
pub new_certificate: [u8; MAX_CERT_SIZE],
}

#[repr(C)]
Expand Down
11 changes: 11 additions & 0 deletions dpe/src/support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ bitflags! {
const INTERNAL_INFO = 1u32 << 22;
const INTERNAL_DICE = 1u32 << 21;
const RETAIN_PARENT_CONTEXT = 1u32 << 19;
const CDI_EXPORT = 1u32 << 18;
}
}

Expand Down Expand Up @@ -49,6 +50,9 @@ impl Support {
pub fn retain_parent_context(&self) -> bool {
self.contains(Support::RETAIN_PARENT_CONTEXT)
}
pub fn cdi_export(&self) -> bool {
self.contains(Support::CDI_EXPORT)
}

/// Disables supported features based on compilation features
pub fn preprocess_support(&self) -> Support {
Expand Down Expand Up @@ -90,6 +94,10 @@ impl Support {
{
support.insert(Support::RETAIN_PARENT_CONTEXT);
}
#[cfg(feature = "disable_export_cdi")]
{
support.insert(Support::CDI_EXPORT);
}
self.difference(support)
}
}
Expand Down Expand Up @@ -135,6 +143,8 @@ pub mod test {
assert_eq!(flags, 1 << 21);
let flags = Support::RETAIN_PARENT_CONTEXT.bits();
assert_eq!(flags, 1 << 19);
let flags = Support::CDI_EXPORT.bits();
assert_eq!(flags, 1 << 18);
// Supports a couple combos.
let flags = (Support::SIMULATION
| Support::AUTO_INIT
Expand All @@ -161,6 +171,7 @@ pub mod test {
| (1 << 22)
| (1 << 21)
| (1 << 19)
| (1 << 18)
);
}
}

0 comments on commit 637686d

Please sign in to comment.