Skip to content

Commit

Permalink
Explicitly exclude code when disabling support features
Browse files Browse the repository at this point in the history
This will ensure that the DPE codesize is smaller when some
features are disabled. Also, add a compiler profile that
enables LTO and sets "s" optimization to optimize for the
binary size.
  • Loading branch information
sree-revoori1 authored and jhand2 committed May 6, 2024
1 parent 98c844b commit 8835c88
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 117 deletions.
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,10 @@ caliptra-cfi-lib-git = { git = "https://github.com/chipsalliance/caliptra-cfi.gi
caliptra-cfi-derive-git = { git = "https://github.com/chipsalliance/caliptra-cfi.git", package = "caliptra-cfi-derive-git", rev = "a98e499d279e81ae85881991b1e9eee354151189"}
zerocopy = "0.6.6"
openssl = "0.10.64"

[profile.firmware]
inherits = "release"
panic = "abort"
lto = true
opt-level = "s"
codegen-units = 1
171 changes: 93 additions & 78 deletions dpe/src/commands/certify_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ use caliptra_cfi_lib_git::cfi_launder;
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq};
use cfg_if::cfg_if;
use crypto::{Crypto, Hasher};
use platform::{Platform, PlatformError, MAX_ISSUER_NAME_SIZE, MAX_KEY_IDENTIFIER_SIZE};
#[cfg(not(feature = "disable_x509"))]
use platform::MAX_ISSUER_NAME_SIZE;
use platform::{Platform, PlatformError, MAX_KEY_IDENTIFIER_SIZE};

#[repr(C)]
#[derive(Debug, PartialEq, Eq, zerocopy::FromBytes, zerocopy::AsBytes)]
Expand Down Expand Up @@ -104,6 +106,7 @@ impl CommandExecution for CertifyKeyCmd {
#[cfg(not(feature = "no-cfi"))]
cfi_assert!(key_pair.is_err());
}
#[allow(unused_variables)]
let (priv_key, pub_key) = key_pair?;

let mut subj_serial = [0u8; DPE_PROFILE.get_hash_size() * 2];
Expand Down Expand Up @@ -158,91 +161,103 @@ impl CommandExecution for CertifyKeyCmd {
subject_alt_name,
};

let mut issuer_name = [0u8; MAX_ISSUER_NAME_SIZE];
let issuer_len = env.platform.get_issuer_name(&mut issuer_name)?;

let mut cert = [0u8; MAX_CERT_SIZE];
let cert_size = match self.format {
Self::FORMAT_X509 => {
#[cfg(not(feature = "no-cfi"))]
cfi_assert_eq(self.format, Self::FORMAT_X509);
let mut tbs_buffer = [0u8; MAX_CERT_SIZE];
let mut tbs_writer = CertWriter::new(&mut tbs_buffer, true);
if issuer_len > MAX_ISSUER_NAME_SIZE {
return Err(DpeErrorCode::InternalError);
}
let cert_validity = env.platform.get_cert_validity()?;
let mut bytes_written = tbs_writer.encode_ecdsa_tbs(
/*serial=*/
&subject_name.serial.bytes()[..20], // Serial number must be truncated to 20 bytes
&issuer_name[..issuer_len],
&subject_name,
&pub_key,
&measurements,
&cert_validity,
)?;
if bytes_written > MAX_CERT_SIZE {
return Err(DpeErrorCode::InternalError);
}
cfg_if! {
if #[cfg(not(feature = "disable_x509"))] {
let mut issuer_name = [0u8; MAX_ISSUER_NAME_SIZE];
let issuer_len = env.platform.get_issuer_name(&mut issuer_name)?;
#[cfg(not(feature = "no-cfi"))]
cfi_assert_eq(self.format, Self::FORMAT_X509);
let mut tbs_buffer = [0u8; MAX_CERT_SIZE];
let mut tbs_writer = CertWriter::new(&mut tbs_buffer, true);
if issuer_len > MAX_ISSUER_NAME_SIZE {
return Err(DpeErrorCode::InternalError);
}
let cert_validity = env.platform.get_cert_validity()?;
let mut bytes_written = tbs_writer.encode_ecdsa_tbs(
/*serial=*/
&subject_name.serial.bytes()[..20], // Serial number must be truncated to 20 bytes
&issuer_name[..issuer_len],
&subject_name,
&pub_key,
&measurements,
&cert_validity,
)?;
if bytes_written > MAX_CERT_SIZE {
return Err(DpeErrorCode::InternalError);
}

let tbs_digest = env
.crypto
.hash(DPE_PROFILE.alg_len(), &tbs_buffer[..bytes_written])?;
let sig = env
.crypto
.ecdsa_sign_with_alias(DPE_PROFILE.alg_len(), &tbs_digest)?;

let mut cert_writer = CertWriter::new(&mut cert, true);
bytes_written =
cert_writer.encode_ecdsa_certificate(&tbs_buffer[..bytes_written], &sig)?;
u32::try_from(bytes_written).map_err(|_| DpeErrorCode::InternalError)?
let tbs_digest = env
.crypto
.hash(DPE_PROFILE.alg_len(), &tbs_buffer[..bytes_written])?;
let sig = env
.crypto
.ecdsa_sign_with_alias(DPE_PROFILE.alg_len(), &tbs_digest)?;

let mut cert_writer = CertWriter::new(&mut cert, true);
bytes_written =
cert_writer.encode_ecdsa_certificate(&tbs_buffer[..bytes_written], &sig)?;
u32::try_from(bytes_written).map_err(|_| DpeErrorCode::InternalError)?
} else {
Err(DpeErrorCode::ArgumentNotSupported)?
}
}
}
Self::FORMAT_CSR => {
#[cfg(not(feature = "no-cfi"))]
cfi_assert_eq(self.format, Self::FORMAT_CSR);
let mut cert_req_info_buffer = [0u8; MAX_CERT_SIZE];
let mut cert_req_info_writer = CertWriter::new(&mut cert_req_info_buffer, true);
let mut bytes_written = cert_req_info_writer.encode_certification_request_info(
&pub_key,
&subject_name,
&measurements,
)?;
if bytes_written > MAX_CERT_SIZE {
return Err(DpeErrorCode::InternalError);
}
cfg_if! {
if #[cfg(not(feature = "disable_csr"))] {
#[cfg(not(feature = "no-cfi"))]
cfi_assert_eq(self.format, Self::FORMAT_CSR);
let mut cert_req_info_buffer = [0u8; MAX_CERT_SIZE];
let mut cert_req_info_writer = CertWriter::new(&mut cert_req_info_buffer, true);
let mut bytes_written = cert_req_info_writer
.encode_certification_request_info(
&pub_key,
&subject_name,
&measurements,
)?;
if bytes_written > MAX_CERT_SIZE {
return Err(DpeErrorCode::InternalError);
}

let cert_req_info_digest = env.crypto.hash(
DPE_PROFILE.alg_len(),
&cert_req_info_buffer[..bytes_written],
)?;
// The PKCS#10 CSR is self-signed so the private key signs it instead of the alias key.
let cert_req_info_sig = env.crypto.ecdsa_sign_with_derived(
DPE_PROFILE.alg_len(),
&cert_req_info_digest,
&priv_key,
&pub_key,
)?;

let mut csr_buffer = [0u8; MAX_CERT_SIZE];
let mut csr_writer = CertWriter::new(&mut csr_buffer, true);
bytes_written = csr_writer
.encode_csr(&cert_req_info_buffer[..bytes_written], &cert_req_info_sig)?;
if bytes_written > MAX_CERT_SIZE {
return Err(DpeErrorCode::InternalError);
}
let cert_req_info_digest = env.crypto.hash(
DPE_PROFILE.alg_len(),
&cert_req_info_buffer[..bytes_written],
)?;
// The PKCS#10 CSR is self-signed so the private key signs it instead of the alias key.
let cert_req_info_sig = env.crypto.ecdsa_sign_with_derived(
DPE_PROFILE.alg_len(),
&cert_req_info_digest,
&priv_key,
&pub_key,
)?;

let mut csr_buffer = [0u8; MAX_CERT_SIZE];
let mut csr_writer = CertWriter::new(&mut csr_buffer, true);
bytes_written = csr_writer
.encode_csr(&cert_req_info_buffer[..bytes_written], &cert_req_info_sig)?;
if bytes_written > MAX_CERT_SIZE {
return Err(DpeErrorCode::InternalError);
}

let csr_digest = env
.crypto
.hash(DPE_PROFILE.alg_len(), &csr_buffer[..bytes_written])?;
let csr_sig = env
.crypto
.ecdsa_sign_with_alias(DPE_PROFILE.alg_len(), &csr_digest)?;
let sid = env.platform.get_signer_identifier()?;

let mut cms_writer = CertWriter::new(&mut cert, true);
bytes_written =
cms_writer.encode_cms(&csr_buffer[..bytes_written], &csr_sig, &sid)?;
u32::try_from(bytes_written).map_err(|_| DpeErrorCode::InternalError)?
let csr_digest = env
.crypto
.hash(DPE_PROFILE.alg_len(), &csr_buffer[..bytes_written])?;
let csr_sig = env
.crypto
.ecdsa_sign_with_alias(DPE_PROFILE.alg_len(), &csr_digest)?;
let sid = env.platform.get_signer_identifier()?;

let mut cms_writer = CertWriter::new(&mut cert, true);
bytes_written =
cms_writer.encode_cms(&csr_buffer[..bytes_written], &csr_sig, &sid)?;
u32::try_from(bytes_written).map_err(|_| DpeErrorCode::InternalError)?
} else {
Err(DpeErrorCode::ArgumentNotSupported)?
}
}
}
_ => return Err(DpeErrorCode::InvalidArgument),
};
Expand Down
61 changes: 34 additions & 27 deletions dpe/src/commands/derive_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ impl CommandExecution for DeriveContextCmd {
|| (!dpe.support.retain_parent_context() && self.retains_parent())
|| (!dpe.support.is_ca() && self.allows_ca())
|| (!dpe.support.x509() && self.allows_x509())
|| (!dpe.support.recursive() && self.is_recursive())
{
return Err(DpeErrorCode::ArgumentNotSupported);
}
Expand Down Expand Up @@ -217,34 +218,40 @@ impl CommandExecution for DeriveContextCmd {
}

if self.is_recursive() {
let mut tmp_context = dpe.contexts[parent_idx];
if tmp_context.tci.tci_type != self.tci_type {
return Err(DpeErrorCode::InvalidArgument);
} else {
#[cfg(not(feature = "no-cfi"))]
cfi_assert_eq(tmp_context.tci.tci_type, self.tci_type);
cfg_if! {
if #[cfg(not(feature = "disable_recursive"))] {
let mut tmp_context = dpe.contexts[parent_idx];
if tmp_context.tci.tci_type != self.tci_type {
return Err(DpeErrorCode::InvalidArgument);
} else {
#[cfg(not(feature = "no-cfi"))]
cfi_assert_eq(tmp_context.tci.tci_type, self.tci_type);
}
dpe.add_tci_measurement(
env,
&mut tmp_context,
&TciMeasurement(self.data),
target_locality,
)?;

// Rotate the handle if it isn't the default context.
dpe.roll_onetime_use_handle(env, parent_idx)?;

dpe.contexts[parent_idx] = Context {
handle: dpe.contexts[parent_idx].handle,
..tmp_context
};

// No child context created so handle is unmeaningful
Ok(Response::DeriveContext(DeriveContextResp {
handle: ContextHandle::default(),
parent_handle: dpe.contexts[parent_idx].handle,
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
}))
} else {
Err(DpeErrorCode::ArgumentNotSupported)?
}
}
dpe.add_tci_measurement(
env,
&mut tmp_context,
&TciMeasurement(self.data),
target_locality,
)?;

// Rotate the handle if it isn't the default context.
dpe.roll_onetime_use_handle(env, parent_idx)?;

dpe.contexts[parent_idx] = Context {
handle: dpe.contexts[parent_idx].handle,
..tmp_context
};

// No child context created so handle is unmeaningful
Ok(Response::DeriveContext(DeriveContextResp {
handle: ContextHandle::default(),
parent_handle: dpe.contexts[parent_idx].handle,
resp_hdr: ResponseHdr::new(DpeErrorCode::NoError),
}))
} else {
let child_idx = dpe
.get_next_inactive_context_pos()
Expand Down
7 changes: 6 additions & 1 deletion dpe/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use self::get_certificate_chain::GetCertificateChainCmd;
pub use self::initialize_context::InitCtxCmd;

pub use self::certify_key::{CertifyKeyCmd, CertifyKeyFlags};

#[cfg(not(feature = "disable_rotate_context"))]
pub use self::rotate_context::{RotateCtxCmd, RotateCtxFlags};
pub use self::sign::{SignCmd, SignFlags};

Expand All @@ -27,6 +27,7 @@ mod derive_context;
mod destroy_context;
mod get_certificate_chain;
mod initialize_context;
#[cfg(not(feature = "disable_rotate_context"))]
mod rotate_context;
mod sign;

Expand All @@ -37,6 +38,7 @@ pub enum Command {
DeriveContext(DeriveContextCmd),
CertifyKey(CertifyKeyCmd),
Sign(SignCmd),
#[cfg(not(feature = "disable_rotate_context"))]
RotateCtx(RotateCtxCmd),
DestroyCtx(DestroyCtxCmd),
GetCertificateChain(GetCertificateChainCmd),
Expand All @@ -48,6 +50,7 @@ impl Command {
pub const DERIVE_CONTEXT: u32 = 0x08;
pub const CERTIFY_KEY: u32 = 0x09;
pub const SIGN: u32 = 0x0A;
#[cfg(not(feature = "disable_rotate_context"))]
pub const ROTATE_CONTEXT_HANDLE: u32 = 0x0e;
pub const DESTROY_CONTEXT: u32 = 0x0f;
pub const GET_CERTIFICATE_CHAIN: u32 = 0x10;
Expand All @@ -67,6 +70,7 @@ impl Command {
Command::DERIVE_CONTEXT => Self::parse_command(Command::DeriveContext, bytes),
Command::CERTIFY_KEY => Self::parse_command(Command::CertifyKey, bytes),
Command::SIGN => Self::parse_command(Command::Sign, bytes),
#[cfg(not(feature = "disable_rotate_context"))]
Command::ROTATE_CONTEXT_HANDLE => Self::parse_command(Command::RotateCtx, bytes),
Command::DESTROY_CONTEXT => Self::parse_command(Command::DestroyCtx, bytes),
Command::GET_CERTIFICATE_CHAIN => {
Expand Down Expand Up @@ -94,6 +98,7 @@ impl From<Command> for u32 {
Command::DeriveContext(_) => Command::DERIVE_CONTEXT,
Command::CertifyKey(_) => Command::CERTIFY_KEY,
Command::Sign(_) => Command::SIGN,
#[cfg(not(feature = "disable_rotate_context"))]
Command::RotateCtx(_) => Command::ROTATE_CONTEXT_HANDLE,
Command::DestroyCtx(_) => Command::DESTROY_CONTEXT,
Command::GetCertificateChain(_) => Command::GET_CERTIFICATE_CHAIN,
Expand Down
21 changes: 15 additions & 6 deletions dpe/src/commands/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use caliptra_cfi_lib_git::cfi_launder;
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq, cfi_assert_ne};
use cfg_if::cfg_if;
use crypto::{Crypto, CryptoBuf, Digest, EcdsaSig, HmacSig};
use crypto::{Crypto, Digest, EcdsaSig};
#[cfg(not(feature = "disable_is_symmetric"))]
use crypto::{CryptoBuf, HmacSig};

#[repr(C)]
#[derive(Debug, PartialEq, Eq, zerocopy::AsBytes, zerocopy::FromBytes)]
Expand Down Expand Up @@ -86,6 +88,7 @@ impl SignCmd {
/// * `idx` - The index of the context where the measurement hash is computed from
/// * `digest` - The data to be signed
#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
#[cfg(not(feature = "disable_is_symmetric"))]
fn hmac_sign(
&self,
dpe: &mut DpeInstance,
Expand Down Expand Up @@ -138,15 +141,21 @@ impl CommandExecution for SignCmd {
}
}

let algs = DPE_PROFILE.alg_len();
let digest = Digest::new(&self.digest)?;

let EcdsaSig { r, s } = if !self.uses_symmetric() {
self.ecdsa_sign(dpe, env, idx, &digest)?
} else {
let r = self.hmac_sign(dpe, env, idx, &digest)?;
let s = CryptoBuf::default(algs);
EcdsaSig { r, s }
cfg_if! {
if #[cfg(not(feature = "disable_is_symmetric"))] {
let algs = DPE_PROFILE.alg_len();
let r = self.hmac_sign(dpe, env, idx, &digest)?;
let s = CryptoBuf::default(algs);
EcdsaSig { r, s }
}
else {
Err(DpeErrorCode::ArgumentNotSupported)?
}
}
};

let sig_r_or_hmac: [u8; DPE_PROFILE.get_ecc_int_size()] = r
Expand Down
Loading

0 comments on commit 8835c88

Please sign in to comment.