Skip to content

Commit

Permalink
Add CA certificate generation to DeriveContextCmd
Browse files Browse the repository at this point in the history
  • Loading branch information
clundin25 committed Jan 11, 2025
1 parent 661f64d commit 604d64a
Show file tree
Hide file tree
Showing 22 changed files with 1,207 additions and 225 deletions.
66 changes: 66 additions & 0 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,20 @@ pub trait Crypto {
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

/// Derive a CDI for an exported private key based on the current base CDI and measurements
///
/// # Arguments
///
/// * `algs` - Which length of algorithms to use.
/// * `measurement` - A digest of the measurements which should be used for CDI derivation
/// * `info` - Caller-supplied info string to use in CDI derivation
fn derive_exported_cdi(
&mut self,
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

/// CFI wrapper around derive_cdi
///
/// To implement this function, you need to add the
Expand All @@ -182,6 +196,28 @@ pub trait Crypto {
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

/// CFI wrapper around derive_cdi_exported
///
/// To implement this function, you need to add the
/// cfi_impl_fn proc_macro to derive_exported_cdi.
#[cfg(not(feature = "no-cfi"))]
fn __cfi_derive_exported_cdi(
&mut self,
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

/// Retrieves the CDI for an exported private key.
fn get_exported_cdi(&mut self) -> Result<Self::Cdi, CryptoError>;

/// CFI wrapper around get_exported_cdi
///
/// To implement this function, you need to add the
/// cfi_impl_fn proc_macro to derive_cdi.
#[cfg(not(feature = "no-cfi"))]
fn __cfi_get_exported_cdi(&mut self) -> Result<Self::Cdi, CryptoError>;

/// Derives a key pair using a cryptographically secure KDF
///
/// # Arguments
Expand All @@ -199,6 +235,23 @@ pub trait Crypto {
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError>;

/// Derives an exported key pair using a cryptographically secure KDF
///
/// # Arguments
///
/// * `algs` - Which length of algorithms to use.
/// * `cdi` - Caller-supplied private key to use in public key derivation
/// * `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,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError>;

/// CFI wrapper around derive_key_pair
///
/// To implement this function, you need to add the
Expand All @@ -212,6 +265,19 @@ pub trait Crypto {
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError>;

/// CFI wrapper around derive_key_pair_exported
///
/// To implement this function, you need to add the
/// cfi_impl_fn proc_macro to derive_key_pair.
#[cfg(not(feature = "no-cfi"))]
fn __cfi_derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError>;

/// Sign `digest` with the platform Alias Key
///
/// # Arguments
Expand Down
101 changes: 76 additions & 25 deletions crypto/src/openssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,31 @@ impl Hasher for OpensslHasher {
}

#[cfg(feature = "deterministic_rand")]
pub struct OpensslCrypto(StdRng);
pub struct OpensslCrypto {
rng: StdRng,
// Cached CDI for exported CDI operations.
exported_cdi: Option<Vec<u8>>,
}

#[cfg(not(feature = "deterministic_rand"))]
pub struct OpensslCrypto;
pub struct OpensslCrypto {
exported_cdi: Option<Vec<u8>>,
}

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)
OpensslCrypto {
rng: seeded_rng,
exported_cdi: None,
}
}

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

fn get_digest(algs: AlgLen) -> MessageDigest {
Expand Down Expand Up @@ -90,6 +99,35 @@ impl OpensslCrypto {

EcKey::from_private_components(&group, priv_key_bn, &pub_point)
}

fn derive_key_pair_inner(
&mut self,
algs: AlgLen,
cdi: &<OpensslCrypto as Crypto>::Cdi,
label: &[u8],
info: &[u8],
) -> Result<(<OpensslCrypto as Crypto>::PrivKey, EcdsaPub), CryptoError> {
let priv_key = hkdf_get_priv_key(algs, cdi, label, info)?;

let ec_priv_key = OpensslCrypto::ec_key_from_priv_key(algs, &priv_key)?;
let nid = OpensslCrypto::get_curve(algs);

let group = EcGroup::from_curve_name(nid).unwrap();
let mut bn_ctx = BigNumContext::new().unwrap();

let mut x = BigNum::new().unwrap();
let mut y = BigNum::new().unwrap();

ec_priv_key
.public_key()
.affine_coordinates(&group, &mut x, &mut y, &mut bn_ctx)
.unwrap();

let x = CryptoBuf::new(&x.to_vec_padded(algs.size() as i32).unwrap()).unwrap();
let y = CryptoBuf::new(&y.to_vec_padded(algs.size() as i32).unwrap()).unwrap();

Ok((priv_key, EcdsaPub { x, y }))
}
}

impl Default for OpensslCrypto {
Expand All @@ -112,7 +150,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 All @@ -133,7 +171,28 @@ impl Crypto for OpensslCrypto {
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError> {
hkdf_derive_cdi(algs, measurement, info)
let cdi = hkdf_derive_cdi(algs, measurement, info)?;
self.exported_cdi = Some(cdi.clone());
Ok(cdi)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_exported_cdi(
&mut self,
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError> {
let cdi = hkdf_derive_cdi(algs, measurement, info)?;
self.exported_cdi = Some(cdi.clone());
Ok(cdi)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn get_exported_cdi(&mut self) -> Result<Self::Cdi, CryptoError> {
self.exported_cdi
.clone()
.ok_or(CryptoError::CryptoLibError(0))
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
Expand All @@ -144,26 +203,18 @@ impl Crypto for OpensslCrypto {
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
let priv_key = hkdf_get_priv_key(algs, cdi, label, info)?;

let ec_priv_key = OpensslCrypto::ec_key_from_priv_key(algs, &priv_key)?;
let nid = OpensslCrypto::get_curve(algs);

let group = EcGroup::from_curve_name(nid).unwrap();
let mut bn_ctx = BigNumContext::new().unwrap();

let mut x = BigNum::new().unwrap();
let mut y = BigNum::new().unwrap();

ec_priv_key
.public_key()
.affine_coordinates(&group, &mut x, &mut y, &mut bn_ctx)
.unwrap();

let x = CryptoBuf::new(&x.to_vec_padded(algs.size() as i32).unwrap()).unwrap();
let y = CryptoBuf::new(&y.to_vec_padded(algs.size() as i32).unwrap()).unwrap();
self.derive_key_pair_inner(algs, cdi, label, info)
}

Ok((priv_key, EcdsaPub { x, y }))
#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
self.derive_key_pair_inner(algs, cdi, label, info)
}

fn ecdsa_sign_with_alias(
Expand Down
97 changes: 74 additions & 23 deletions crypto/src/rustcrypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,56 @@ impl Hasher for RustCryptoHasher {
}
}

pub struct RustCryptoImpl(StdRng);
pub struct RustCryptoImpl {
rng: StdRng,
// Cached CDI for exported CDI operations.
exported_cdi: Option<Vec<u8>>,
}
impl RustCryptoImpl {
#[cfg(not(feature = "deterministic_rand"))]
pub fn new() -> Self {
RustCryptoImpl(StdRng::from_entropy())
RustCryptoImpl {
rng: StdRng::from_entropy(),
exported_cdi: None,
}
}

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

fn derive_key_pair_inner(
&mut self,
algs: AlgLen,
cdi: &<RustCryptoImpl as Crypto>::Cdi,
label: &[u8],
info: &[u8],
) -> Result<(<RustCryptoImpl as Crypto>::PrivKey, EcdsaPub), CryptoError> {
let secret = hkdf_get_priv_key(algs, cdi, label, info)?;
match algs {
AlgLen::Bit256 => {
let signing = p256::ecdsa::SigningKey::from_slice(&secret.bytes())?;
let verifying = p256::ecdsa::VerifyingKey::from(&signing);
let point = verifying.to_encoded_point(false);
let x = CryptoBuf::new(point.x().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
let y = CryptoBuf::new(point.y().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
Ok((secret, EcdsaPub { x, y }))
}
AlgLen::Bit384 => {
let signing = p384::ecdsa::SigningKey::from_slice(&secret.bytes())?;
let verifying = p384::ecdsa::VerifyingKey::from(&signing);
let point = verifying.to_encoded_point(false);
let x = CryptoBuf::new(point.x().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
let y = CryptoBuf::new(point.y().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
Ok((secret, EcdsaPub { x, y }))
}
}
}
}

Expand All @@ -86,10 +124,11 @@ 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(())
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_cdi(
&mut self,
algs: AlgLen,
Expand All @@ -99,32 +138,44 @@ impl Crypto for RustCryptoImpl {
hkdf_derive_cdi(algs, measurement, info)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_exported_cdi(
&mut self,
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError> {
let cdi = hkdf_derive_cdi(algs, measurement, info)?;
self.exported_cdi = Some(cdi.clone());
Ok(cdi)
}

fn get_exported_cdi(&mut self) -> Result<Self::Cdi, CryptoError> {
self.exported_cdi
.clone()
.ok_or(CryptoError::CryptoLibError(0))
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_key_pair(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
let secret = hkdf_get_priv_key(algs, cdi, label, info)?;
match algs {
AlgLen::Bit256 => {
let signing = p256::ecdsa::SigningKey::from_slice(&secret.bytes())?;
let verifying = p256::ecdsa::VerifyingKey::from(&signing);
let point = verifying.to_encoded_point(false);
let x = CryptoBuf::new(point.x().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
let y = CryptoBuf::new(point.y().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
Ok((secret, EcdsaPub { x, y }))
}
AlgLen::Bit384 => {
let signing = p384::ecdsa::SigningKey::from_slice(&secret.bytes())?;
let verifying = p384::ecdsa::VerifyingKey::from(&signing);
let point = verifying.to_encoded_point(false);
let x = CryptoBuf::new(point.x().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
let y = CryptoBuf::new(point.y().ok_or(RUSTCRYPTO_ECDSA_ERROR)?.as_slice())?;
Ok((secret, EcdsaPub { x, y }))
}
}
self.derive_key_pair_inner(algs, cdi, label, info)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_key_pair_exported(
&mut self,
algs: AlgLen,
cdi: &Self::Cdi,
label: &[u8],
info: &[u8],
) -> Result<(Self::PrivKey, EcdsaPub), CryptoError> {
self.derive_key_pair_inner(algs, cdi, label, info)
}

fn ecdsa_sign_with_alias(
Expand Down
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
1 change: 1 addition & 0 deletions dpe/fuzz/src/fuzz_target_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ fn harness(data: &[u8]) {
Response::RotateCtx(ref res) => res.resp_hdr.status,
Response::CertifyKey(ref res) => res.resp_hdr.status,
Response::Sign(ref res) => res.resp_hdr.status,
Response::SignWithExported(ref res) => res.resp_hdr.status,
Response::DestroyCtx(ref resp_hdr) => resp_hdr.status,
Response::GetCertificateChain(ref res) => res.resp_hdr.status,
Response::Error(ref resp_hdr) => resp_hdr.status,
Expand Down
Loading

0 comments on commit 604d64a

Please sign in to comment.