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 27, 2025
1 parent 27b8300 commit 3297d02
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 45 deletions.
30 changes: 20 additions & 10 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub use rand::*;
mod hkdf;
mod signer;

pub const MAX_EXPORTED_CDI_SIZE: usize = 32;
pub type ExportedCdiHandle = [u8; MAX_EXPORTED_CDI_SIZE];

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

impl CryptoError {
Expand All @@ -66,11 +72,14 @@ 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::InvalidExportedCdiHandle
| CryptoError::ExportedCdiHandleLimitExceeded
| CryptoError::ExportedCdiHandleDuplicateCdi
| CryptoError::NotImplemented => None,
}
}
}
Expand Down Expand Up @@ -182,7 +191,7 @@ pub trait Crypto {
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;
) -> Result<ExportedCdiHandle, CryptoError>;

/// CFI wrapper around derive_cdi
///
Expand All @@ -206,7 +215,7 @@ pub trait Crypto {
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;
) -> Result<ExportedCdiHandle, CryptoError>;

/// Derives a key pair using a cryptographically secure KDF
///
Expand All @@ -230,14 +239,15 @@ pub trait Crypto {
/// # Arguments
///
/// * `algs` - Which length of algorithms to use.
/// * `cdi` - Caller-supplied private key to use in public key derivation
/// * `exported_handle` - The handle associated with an existing CDI. Created by
/// `derive_cdi_exported`
/// * `label` - Caller-supplied label to use in asymmetric key derivation
/// * `info` - Caller-supplied info string to use in asymmetric key derivation
///
fn derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
exported_handle: &ExportedCdiHandle,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError>;
Expand All @@ -263,7 +273,7 @@ pub trait Crypto {
fn __cfi_derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
exported_handle: &ExportedCdiHandle,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError>;
Expand Down
59 changes: 49 additions & 10 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, ExportedCdiHandle, 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,36 @@ 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;

#[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 +157,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 @@ -172,9 +188,23 @@ impl Crypto for OpensslCrypto {
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError> {
) -> Result<ExportedCdiHandle, CryptoError> {
let cdi = hkdf_derive_cdi(algs, measurement, info)?;
Ok(cdi)

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, exported_cdi_handle));
Ok(exported_cdi_handle)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
Expand All @@ -192,11 +222,20 @@ impl Crypto for OpensslCrypto {
fn derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
exported_handle: &ExportedCdiHandle,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
self.derive_key_pair_inner(algs, cdi, label, info)
let cdi = {
let mut cdi = None;
for (stored_cdi, stored_handle) in self.export_cdi_slots.iter() {
if stored_handle == exported_handle {
cdi = Some(stored_cdi.clone());
}
}
cdi.ok_or(CryptoError::InvalidExportedCdiHandle)
}?;
self.derive_key_pair_inner(algs, &cdi, label, info)
}

fn ecdsa_sign_with_alias(
Expand Down
57 changes: 48 additions & 9 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, ExportedCdiHandle,
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,31 @@ 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;

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 +130,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 @@ -134,9 +150,23 @@ impl Crypto for RustCryptoImpl {
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError> {
) -> Result<ExportedCdiHandle, CryptoError> {
let cdi = hkdf_derive_cdi(algs, measurement, info)?;
Ok(cdi)

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, exported_cdi_handle));
Ok(exported_cdi_handle)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
Expand All @@ -154,11 +184,20 @@ impl Crypto for RustCryptoImpl {
fn derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
exported_handle: &ExportedCdiHandle,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
self.derive_key_pair_inner(algs, cdi, label, info)
let cdi = {
let mut cdi = None;
for (stored_cdi, stored_handle) in self.export_cdi_slots.iter() {
if stored_handle == exported_handle {
cdi = Some(stored_cdi.clone());
}
}
cdi.ok_or(CryptoError::InvalidExportedCdiHandle)
}?;
self.derive_key_pair_inner(algs, &cdi, label, info)
}

fn ecdsa_sign_with_alias(
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::{ExportedCdiHandle, MAX_EXPORTED_CDI_SIZE};

// Max cert size returned by CertifyKey
const MAX_CERT_SIZE: usize = 6144;
Expand Down
Loading

0 comments on commit 3297d02

Please sign in to comment.