Skip to content

Commit

Permalink
Exchange CDI for CDI handle via DPE::Crypto trait
Browse files Browse the repository at this point in the history
  • Loading branch information
clundin25 committed Jan 23, 2025
1 parent 27b8300 commit c78f0c2
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 34 deletions.
29 changes: 24 additions & 5 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub use rand::*;
mod hkdf;
mod signer;

pub const MAX_EXPORTED_CDI_SIZE: usize = 32;

#[derive(Debug, Clone, Copy)]
#[cfg_attr(test, derive(strum_macros::EnumIter))]
pub enum AlgLen {
Expand Down Expand Up @@ -54,6 +56,8 @@ pub enum CryptoError {
Size = 0x3,
NotImplemented = 0x4,
HashError(u32) = 0x5,
ExportedCdiHandleLimitExceeded = 0x6,
ExportedCdiHandleDuplicateCdi = 0x7,
}

impl CryptoError {
Expand All @@ -66,11 +70,13 @@ impl CryptoError {

pub fn get_error_detail(&self) -> Option<u32> {
match self {
CryptoError::AbstractionLayer(code) => Some(*code),
CryptoError::CryptoLibError(code) => Some(*code),
CryptoError::Size => None,
CryptoError::NotImplemented => None,
CryptoError::HashError(code) => Some(*code),
CryptoError::AbstractionLayer(code)
| CryptoError::CryptoLibError(code)
| CryptoError::HashError(code) => Some(*code),
CryptoError::Size
| CryptoError::ExportedCdiHandleLimitExceeded
| CryptoError::ExportedCdiHandleDuplicateCdi
| CryptoError::NotImplemented => None,
}
}
}
Expand Down Expand Up @@ -208,6 +214,19 @@ pub trait Crypto {
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

/// Retrieve an exported CDI Handle from a CDI.
/// If the CDI has already been exported, the same handle is returned.
/// If the number of CDIs that can be exported has reached its limit,
/// a `CryptoError` is returned.
///
/// # Arguments
///
/// * `cdi` - The CDI to request a handle for.
fn get_exported_cdi_handle(
&mut self,
cdi: &Self::Cdi,
) -> Result<[u8; MAX_EXPORTED_CDI_SIZE], CryptoError>;

/// Derives a key pair using a cryptographically secure KDF
///
/// # Arguments
Expand Down
51 changes: 45 additions & 6 deletions crypto/src/openssl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Licensed under the Apache-2.0 license

use crate::{hkdf::*, AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, Hasher};
use crate::{
hkdf::*, AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, Hasher,
MAX_EXPORTED_CDI_SIZE,
};
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_derive_git::cfi_impl_fn;
use openssl::{
Expand Down Expand Up @@ -41,23 +44,37 @@ impl Hasher for OpensslHasher {
}
}

// Currently only supports one CDI handle but in the future we may want to support multiple.
const MAX_CDI_HANDLES: usize = 1;
type ExportedCdiHandle = [u8; MAX_EXPORTED_CDI_SIZE];

#[cfg(feature = "deterministic_rand")]
pub struct OpensslCrypto(StdRng);
pub struct OpensslCrypto {
rng: StdRng,
export_cdi_slots: Vec<(<OpensslCrypto as Crypto>::Cdi, ExportedCdiHandle)>,
}

#[cfg(not(feature = "deterministic_rand"))]
pub struct OpensslCrypto;
pub struct OpensslCrypto {
export_cdi_slots: Vec<(<OpensslCrypto as Crypto>::Cdi, ExportedCdiHandle)>,
}

impl OpensslCrypto {
#[cfg(feature = "deterministic_rand")]
pub fn new() -> Self {
const SEED: [u8; 32] = [1; 32];
let seeded_rng = StdRng::from_seed(SEED);
OpensslCrypto(seeded_rng)
Self {
rng: seeded_rng,
export_cdi_slots: Vec::new(),
}
}

#[cfg(not(feature = "deterministic_rand"))]
pub fn new() -> Self {
Self {}
Self {
export_cdi_slots: Vec::new(),
}
}

fn get_digest(algs: AlgLen) -> MessageDigest {
Expand Down Expand Up @@ -141,7 +158,7 @@ impl Crypto for OpensslCrypto {

#[cfg(feature = "deterministic_rand")]
fn rand_bytes(&mut self, dst: &mut [u8]) -> Result<(), CryptoError> {
StdRng::fill_bytes(&mut self.0, dst);
StdRng::fill_bytes(&mut self.rng, dst);
Ok(())
}

Expand Down Expand Up @@ -177,6 +194,28 @@ impl Crypto for OpensslCrypto {
Ok(cdi)
}

fn get_exported_cdi_handle(
&mut self,
cdi: &Self::Cdi,
) -> Result<ExportedCdiHandle, CryptoError> {
for (stored_cdi, _) in self.export_cdi_slots.iter() {
if stored_cdi == cdi {
return Err(CryptoError::ExportedCdiHandleDuplicateCdi);
}
}

if self.export_cdi_slots.len() >= MAX_CDI_HANDLES {
return Err(CryptoError::ExportedCdiHandleDuplicateCdi);
}

let mut exported_cdi_handle = [0; MAX_EXPORTED_CDI_SIZE];
self.rand_bytes(&mut exported_cdi_handle)?;
self.export_cdi_slots
.push((cdi.clone(), exported_cdi_handle));

Ok(exported_cdi_handle)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_key_pair(
&mut self,
Expand Down
49 changes: 44 additions & 5 deletions crypto/src/rustcrypto.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Licensed under the Apache-2.0 license

use crate::{hkdf::*, AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, EcdsaSig, Hasher};
use crate::{
hkdf::*, AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, EcdsaSig, Hasher,
MAX_EXPORTED_CDI_SIZE,
};
use core::ops::Deref;
use ecdsa::{signature::hazmat::PrehashSigner, Signature};
use p256::NistP256;
Expand Down Expand Up @@ -54,18 +57,32 @@ impl Hasher for RustCryptoHasher {
}
}

pub struct RustCryptoImpl(StdRng);
// Currently only supports one CDI handle but in the future we may want to support multiple.
const MAX_CDI_HANDLES: usize = 1;
type ExportedCdiHandle = [u8; MAX_EXPORTED_CDI_SIZE];

pub struct RustCryptoImpl {
rng: StdRng,
export_cdi_slots: Vec<(<RustCryptoImpl as Crypto>::Cdi, ExportedCdiHandle)>,
}

impl RustCryptoImpl {
#[cfg(not(feature = "deterministic_rand"))]
pub fn new() -> Self {
RustCryptoImpl(StdRng::from_entropy())
Self {
rng: StdRng::from_entropy(),
export_cdi_slots: Vec::new(),
}
}

#[cfg(feature = "deterministic_rand")]
pub fn new() -> Self {
const SEED: [u8; 32] = [1; 32];
let seeded_rng = StdRng::from_seed(SEED);
RustCryptoImpl(seeded_rng)
Self {
rng: seeded_rng,
export_cdi_slots: Vec::new(),
}
}

fn derive_key_pair_inner(
Expand Down Expand Up @@ -114,7 +131,7 @@ impl Crypto for RustCryptoImpl {
}

fn rand_bytes(&mut self, dst: &mut [u8]) -> Result<(), CryptoError> {
StdRng::fill_bytes(&mut self.0, dst);
StdRng::fill_bytes(&mut self.rng, dst);
Ok(())
}

Expand All @@ -139,6 +156,28 @@ impl Crypto for RustCryptoImpl {
Ok(cdi)
}

fn get_exported_cdi_handle(
&mut self,
cdi: &Self::Cdi,
) -> Result<ExportedCdiHandle, CryptoError> {
for (stored_cdi, _) in self.export_cdi_slots.iter() {
if stored_cdi == cdi {
return Err(CryptoError::ExportedCdiHandleDuplicateCdi);
}
}

if self.export_cdi_slots.len() >= MAX_CDI_HANDLES {
return Err(CryptoError::ExportedCdiHandleLimitExceeded);
}

let mut exported_cdi_handle = [0; MAX_EXPORTED_CDI_SIZE];
self.rand_bytes(&mut exported_cdi_handle)?;
self.export_cdi_slots
.push((cdi.clone(), exported_cdi_handle));

Ok(exported_cdi_handle)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_key_pair(
&mut self,
Expand Down
4 changes: 3 additions & 1 deletion dpe/src/commands/certify_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ impl CommandExecution for CertifyKeyCmd {
};
let mut cert = [0; MAX_CERT_SIZE];

let CreateDpeCertResult { cert_size, pub_key } = match self.format {
let CreateDpeCertResult {
cert_size, pub_key, ..
} = match self.format {
Self::FORMAT_X509 => {
cfg_if! {
if #[cfg(not(feature = "disable_x509"))] {
Expand Down
13 changes: 4 additions & 9 deletions dpe/src/commands/derive_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ use crate::{
},
tci::TciMeasurement,
x509::{create_exported_dpe_cert, CreateDpeCertArgs, CreateDpeCertResult},
DPE_PROFILE, MAX_CERT_SIZE, MAX_EXPORTED_CDI_SIZE,
DPE_PROFILE, MAX_CERT_SIZE,
};
use bitflags::bitflags;
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_derive_git::cfi_impl_fn;
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq};
use cfg_if::cfg_if;
use crypto::Crypto;

#[repr(C)]
#[derive(
Expand Down Expand Up @@ -300,19 +299,15 @@ impl CommandExecution for DeriveContextCmd {
} else if self.creates_certificate() && self.exports_cdi() {
cfg_if! {
if #[cfg(not(feature = "disable_export_cdi"))] {
let mut exported_cdi_handle = [0; MAX_EXPORTED_CDI_SIZE];
env.crypto
.rand_bytes(&mut exported_cdi_handle)
.map_err(DpeErrorCode::Crypto)?;
let args = CreateDpeCertArgs {
handle: &self.handle,
locality,
cdi_label: b"Exported CDI",
key_label: b"Exported ECC",
context: &exported_cdi_handle,
context: b"Exported ECC",
};
let mut cert = [0; MAX_CERT_SIZE];
let CreateDpeCertResult { cert_size, .. } = create_exported_dpe_cert(
let CreateDpeCertResult { cert_size, exported_cdi_handle, .. } = create_exported_dpe_cert(
&args,
dpe,
env,
Expand Down Expand Up @@ -422,7 +417,7 @@ mod tests {
context::ContextType,
dpe_instance::tests::{TestTypes, RANDOM_HANDLE, SIMULATION_HANDLE, TEST_LOCALITIES},
support::Support,
DpeProfile, MAX_HANDLES,
DpeProfile, MAX_EXPORTED_CDI_SIZE, MAX_HANDLES,
};
use caliptra_cfi_lib_git::CfiCounter;
use crypto::{Crypto, Hasher, OpensslCrypto};
Expand Down
2 changes: 1 addition & 1 deletion dpe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub mod x509;

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

const MAX_EXPORTED_CDI_SIZE: usize = 32;
pub use crypto::MAX_EXPORTED_CDI_SIZE;

// Max cert size returned by CertifyKey
const MAX_CERT_SIZE: usize = 6144;
Expand Down
30 changes: 23 additions & 7 deletions dpe/src/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use bitflags::bitflags;
use caliptra_cfi_lib_git::cfi_launder;
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq};
use crypto::{Crypto, Digest, EcdsaPub, EcdsaSig, Hasher};
use crypto::{Crypto, Digest, EcdsaPub, EcdsaSig, Hasher, MAX_EXPORTED_CDI_SIZE};
#[cfg(not(feature = "disable_x509"))]
use platform::CertValidity;
#[cfg(not(feature = "disable_csr"))]
Expand Down Expand Up @@ -2265,6 +2265,9 @@ pub(crate) struct CreateDpeCertResult {
pub cert_size: u32,
/// Public key embedded in Cert or CSR.
pub pub_key: EcdsaPub,
/// If the cert_type is `CertificateType::Exported` the CDI is exchanged for a handle, and
/// returned via `exported_cdi_handle`.
pub exported_cdi_handle: [u8; MAX_EXPORTED_CDI_SIZE],
}

fn get_dpe_measurement_digest(
Expand Down Expand Up @@ -2390,18 +2393,22 @@ fn create_dpe_cert_or_csr(
let algs = DPE_PROFILE.alg_len();
let digest = get_dpe_measurement_digest(dpe, env, args.handle, args.locality)?;

let key_pair = match cert_type {
let (key_pair, cdi) = match cert_type {
CertificateType::Exported => {
let cdi = env
.crypto
.derive_exported_cdi(algs, &digest, args.cdi_label)?;
env.crypto
.derive_key_pair_exported(algs, &cdi, args.key_label, args.context)
let key_pair =
env.crypto
.derive_key_pair_exported(algs, &cdi, args.key_label, args.context);
(key_pair, cdi)
}
CertificateType::Leaf => {
let cdi = env.crypto.derive_cdi(algs, &digest, args.cdi_label)?;
env.crypto
.derive_key_pair(algs, &cdi, args.key_label, args.context)
let key_pair = env
.crypto
.derive_key_pair(algs, &cdi, args.key_label, args.context);
(key_pair, cdi)
}
};
if cfi_launder(key_pair.is_ok()) {
Expand Down Expand Up @@ -2521,7 +2528,16 @@ fn create_dpe_cert_or_csr(
}
};

Ok(CreateDpeCertResult { cert_size, pub_key })
let exported_cdi_handle = match cert_type {
CertificateType::Exported => env.crypto.get_exported_cdi_handle(&cdi)?,
_ => [0; MAX_EXPORTED_CDI_SIZE],
};

Ok(CreateDpeCertResult {
cert_size,
pub_key,
exported_cdi_handle,
})
}

#[cfg(test)]
Expand Down

0 comments on commit c78f0c2

Please sign in to comment.