From 0b856e10a8188a2dbfd629ed0c654ca93afd0e8d Mon Sep 17 00:00:00 2001 From: Carl Lundin Date: Fri, 3 Jan 2025 12:50:41 -0800 Subject: [PATCH] Use an "exported" variant of derive_cdi and export_key_pair to distinguish the exported CDI from the DPE CDI. Use this new API to create the exported CDIs keypair --- crypto/src/openssl.rs | 69 ++++++++++++++++++++++-------- crypto/src/rustcrypto.rs | 67 +++++++++++++++++++++-------- dpe/src/commands/derive_context.rs | 28 ++++++++---- 3 files changed, 117 insertions(+), 47 deletions(-) diff --git a/crypto/src/openssl.rs b/crypto/src/openssl.rs index f1bba622..0c12235d 100644 --- a/crypto/src/openssl.rs +++ b/crypto/src/openssl.rs @@ -90,6 +90,35 @@ impl OpensslCrypto { EcKey::from_private_components(&group, priv_key_bn, &pub_point) } + + fn derive_key_pair_inner( + &mut self, + algs: AlgLen, + cdi: &::Cdi, + label: &[u8], + info: &[u8], + ) -> Result<(::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 { @@ -133,6 +162,16 @@ impl Crypto for OpensslCrypto { hkdf_derive_cdi(algs, measurement, info) } + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] + fn derive_cdi_exported( + &mut self, + algs: AlgLen, + measurement: &Digest, + info: &[u8], + ) -> Result { + hkdf_derive_cdi(algs, measurement, info) + } + #[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)] fn derive_key_pair( &mut self, @@ -141,26 +180,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( diff --git a/crypto/src/rustcrypto.rs b/crypto/src/rustcrypto.rs index 5a691032..879a97e1 100644 --- a/crypto/src/rustcrypto.rs +++ b/crypto/src/rustcrypto.rs @@ -67,6 +67,34 @@ impl RustCryptoImpl { let seeded_rng = StdRng::from_seed(SEED); RustCryptoImpl(seeded_rng) } + + fn derive_key_pair_inner( + &mut self, + algs: AlgLen, + cdi: &::Cdi, + label: &[u8], + info: &[u8], + ) -> Result<(::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 })) + } + } + } } impl Crypto for RustCryptoImpl { @@ -96,6 +124,15 @@ impl Crypto for RustCryptoImpl { hkdf_derive_cdi(algs, measurement, info) } + fn derive_cdi_exported( + &mut self, + algs: AlgLen, + measurement: &Digest, + info: &[u8], + ) -> Result { + hkdf_derive_cdi(algs, measurement, info) + } + fn derive_key_pair( &mut self, algs: AlgLen, @@ -103,25 +140,17 @@ impl Crypto for RustCryptoImpl { 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) + } + + 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( diff --git a/dpe/src/commands/derive_context.rs b/dpe/src/commands/derive_context.rs index 3941423d..1670035c 100644 --- a/dpe/src/commands/derive_context.rs +++ b/dpe/src/commands/derive_context.rs @@ -296,16 +296,24 @@ impl CommandExecution for DeriveContextCmd { } } } else if self.allows_create_certificate() && self.allows_exports_cdi() { + //TODO(clundin): Fill info with RNG and return it." let algs = DPE_PROFILE.alg_len(); let digest = dpe.compute_measurement_hash(env, parent_idx)?; let cdi = env .crypto - .derive_cdi(DPE_PROFILE.alg_len(), &digest, b"DPE")?; + .derive_cdi(DPE_PROFILE.alg_len(), &digest, b"Exported CDI")?; + let mut exported_cdi_handle = [0; MAX_EXPORTED_CDI_SIZE]; + env.crypto + .rand_bytes(&mut exported_cdi_handle) + .map_err(DpeErrorCode::Crypto)?; + + let key_label = b"Exported ECC"; // TODO(clundin): Is this an appropriate + // label? let key_pair = env.crypto - .derive_key_pair(algs, &cdi, &[0xA; DPE_PROFILE.get_hash_size()], b"ECC"); - let (_, pub_key) = key_pair?; + .derive_key_pair_exported(algs, &cdi, key_label, &exported_cdi_handle); + let (priv_key, pub_key) = key_pair?; let mut subj_serial = [0u8; DPE_PROFILE.get_hash_size() * 2]; env.crypto @@ -352,7 +360,7 @@ impl CommandExecution for DeriveContextCmd { }; let measurements = MeasurementData { - label: &[0xA; DPE_PROFILE.get_hash_size()], //TODO(clundin): Determine correct label + label: key_label, //TODO(clundin): Determine correct label tci_nodes: &nodes[..tcb_count], is_ca: true, supports_recursive: false, @@ -387,9 +395,12 @@ impl CommandExecution for DeriveContextCmd { 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 sig = env.crypto.ecdsa_sign_with_derived( + DPE_PROFILE.alg_len(), + &tbs_digest, + &priv_key, + &pub_key, + )?; let mut cert_writer = CertWriter::new(&mut cert, true); bytes_written = @@ -400,8 +411,7 @@ impl CommandExecution for DeriveContextCmd { handle: ContextHandle::new_invalid(), parent_handle: dpe.contexts[parent_idx].handle, resp_hdr: ResponseHdr::new(DpeErrorCode::NoError), - exported_cdi: [0; MAX_EXPORTED_CDI_SIZE], // TODO(clundin): Implement CDI storage - // behind a Platform trait. + exported_cdi: exported_cdi_handle, certificate_size: cert_size, new_certificate: cert, }))