Skip to content

Commit

Permalink
Merge pull request #371 from clundin25/feature/gh-issue-caliptra-sw-1807
Browse files Browse the repository at this point in the history
Add is_certificate and export_cdi flags to DeriveContext
  • Loading branch information
clundin25 authored Jan 14, 2025
2 parents af0251e + d852604 commit ce993a6
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 2 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
162 changes: 161 additions & 1 deletion dpe/src/commands/derive_context.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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,
Expand Down Expand Up @@ -36,6 +36,8 @@ 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;
}
}

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

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

pub const fn creates_certificate(&self) -> bool {
self.flags.contains(DeriveContextFlags::CREATE_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 +206,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.creates_certificate() || self.exports_cdi()))
|| (!dpe.support.recursive() && self.is_recursive())
{
return Err(DpeErrorCode::ArgumentNotSupported);
Expand All @@ -204,6 +216,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.exports_cdi() && !self.creates_certificate())
|| (self.exports_cdi() && self.is_recursive())
|| (self.exports_cdi() && self.changes_locality())
|| (self.exports_cdi()
&& dpe.contexts[parent_idx].context_type == ContextType::Simulation)
|| (self.is_recursive() && self.retains_parent())
{
return Err(DpeErrorCode::InvalidArgument);
Expand Down Expand Up @@ -267,6 +284,8 @@ impl CommandExecution for DeriveContextCmd {
Err(DpeErrorCode::ArgumentNotSupported)?
}
}
} else if self.creates_certificate() && self.exports_cdi() {
todo!("(clundin): Generate ECA certificiate / export random CDI")
} else {
let child_idx = dpe
.get_next_inactive_context_pos()
Expand Down Expand Up @@ -784,6 +803,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 @@ -996,4 +1016,144 @@ 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();

// When `DeriveContextFlags::EXPORT_CDI` is set, `DeriveContextFlags::CREATE_CERTIFICATE` MUST
// also be set, or `DpeErrorCode::InvalidArgument` is raised.
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."),
};
// DPE must return an `DpeErrorCode::InvalidArgument` error if the context-handle refers to a simulation context.
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])
);

// DPE must return an `DpeErrorCode::InvalidArgument` if `DeriveContextFlags::EXPORT_CDI` and `DeriveContextFlags::RECURSIVE` are set.
assert_eq!(
Err(DpeErrorCode::InvalidArgument),
DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::CREATE_CERTIFICATE
| DeriveContextFlags::EXPORT_CDI
| DeriveContextFlags::RECURSIVE,
tci_type: 0,
target_locality: TEST_LOCALITIES[0]
}
.execute(&mut dpe, &mut env, TEST_LOCALITIES[0])
);

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

// Happy case!
assert!(DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::EXPORT_CDI | DeriveContextFlags::CREATE_CERTIFICATE,
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();

// `DpeInstance` needs `Support::EXPORT_CDI` to use `DeriveContextFlags::EXPORT_CDI`.
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])
);

// `DpeInstance` needs `Support::EXPORT_CDI` to use `DeriveContextFlags::EXPORT_CDI`.
assert_eq!(
Err(DpeErrorCode::ArgumentNotSupported),
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])
);

// `DpeInstance` needs `Support::EXPORT_CDI` to use `DeriveContextFlags::EXPORT_CDI`.
assert_eq!(
Err(DpeErrorCode::ArgumentNotSupported),
DeriveContextCmd {
handle: ContextHandle::default(),
data: [0; DPE_PROFILE.get_tci_size()],
flags: DeriveContextFlags::CREATE_CERTIFICATE,
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
23 changes: 22 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 All @@ -18,6 +18,7 @@ pub enum Response {
GetProfile(GetProfileResp),
InitCtx(NewHandleResp),
DeriveContext(DeriveContextResp),
DeriveContextExportedCdi(DeriveContextExportedCdiResp),
RotateCtx(NewHandleResp),
CertifyKey(CertifyKeyResp),
Sign(SignResp),
Expand All @@ -32,6 +33,7 @@ impl Response {
Response::GetProfile(res) => res.as_bytes(),
Response::InitCtx(res) => res.as_bytes(),
Response::DeriveContext(res) => res.as_bytes(),
Response::DeriveContextExportedCdi(res) => res.as_bytes(),
Response::RotateCtx(res) => res.as_bytes(),
Response::CertifyKey(res) => res.as_bytes(),
Response::Sign(res) => res.as_bytes(),
Expand Down Expand Up @@ -141,6 +143,25 @@ pub struct DeriveContextResp {
pub parent_handle: ContextHandle,
}

#[repr(C)]
#[derive(
Debug,
PartialEq,
Eq,
zerocopy::IntoBytes,
zerocopy::FromBytes,
zerocopy::Immutable,
zerocopy::KnownLayout,
)]
pub struct DeriveContextExportedCdiResp {
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)]
#[derive(
Debug,
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)
);
}
}
1 change: 1 addition & 0 deletions simulator/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ fn handle_request(dpe: &mut DpeInstance, env: &mut DpeEnv<impl DpeTypes>, stream
Response::GetProfile(ref res) => res.resp_hdr.status,
Response::InitCtx(ref res) => res.resp_hdr.status,
Response::DeriveContext(ref res) => res.resp_hdr.status,
Response::DeriveContextExportedCdi(ref res) => res.resp_hdr.status,
Response::RotateCtx(ref res) => res.resp_hdr.status,
Response::CertifyKey(ref res) => res.resp_hdr.status,
Response::Sign(ref res) => res.resp_hdr.status,
Expand Down

0 comments on commit ce993a6

Please sign in to comment.