Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CFI to DPE #310

Merged
merged 1 commit into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ members = [
"simulator",
"tools",
]

[workspace.dependencies]
caliptra-cfi-lib-git = { git = "https://github.com/chipsalliance/caliptra-cfi.git", package = "caliptra-cfi-lib-git", rev = "9f315fcf11fe006e95e62149f54f98620e5244e7", default-features = false, features = ["cfi", "cfi-counter" ] }
caliptra-cfi-derive-git = { git = "https://github.com/chipsalliance/caliptra-cfi.git", package = "caliptra-cfi-derive-git", rev = "9f315fcf11fe006e95e62149f54f98620e5244e7"}
12 changes: 7 additions & 5 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ set -ex
function build_rust_targets() {
profile=$1

cargo build --release --manifest-path dpe/Cargo.toml --features=$profile,no-cfi --no-default-features

cargo build --release --manifest-path crypto/Cargo.toml --no-default-features
cargo build --release --manifest-path platform/Cargo.toml --features=$profile --no-default-features
cargo build --release --manifest-path dpe/Cargo.toml --features=$profile --no-default-features
Expand Down Expand Up @@ -47,7 +49,7 @@ function test_rust_targets() {

sree-revoori1 marked this conversation as resolved.
Show resolved Hide resolved
cargo test --manifest-path platform/Cargo.toml --features=$profile --no-default-features
cargo test --manifest-path crypto/Cargo.toml --no-default-features
cargo test --manifest-path dpe/Cargo.toml --features=$profile --no-default-features
cargo test --manifest-path dpe/Cargo.toml --features=$profile --no-default-features -- --test-threads=1
cargo test --manifest-path simulator/Cargo.toml --features=$profile,openssl --no-default-features
}

Expand Down Expand Up @@ -80,13 +82,13 @@ run_verification_tests dpe_profile_p384_sha384 rustcrypto

# Build fuzz target
( cd dpe/fuzz
rustup toolchain install nightly-2023-04-15
cargo +nightly-2023-04-15 install cargo-fuzz cargo-afl
rustup toolchain install nightly-2023-11-16
cargo +nightly-2023-11-16 install cargo-fuzz cargo-afl
cargo fmt --check
cargo clippy --features libfuzzer-sys
cargo clippy --features afl
cargo +nightly-2023-04-15 fuzz build --features libfuzzer-sys
cargo +nightly-2023-04-15 afl build --features afl
cargo +nightly-2023-11-16 fuzz build --features libfuzzer-sys
cargo +nightly-2023-11-16 afl build --features afl
)

# Fix license headers
Expand Down
3 changes: 3 additions & 0 deletions crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ edition = "2021"
openssl = ["dep:openssl", "dep:hkdf", "dep:sha2"]
rustcrypto = ["dep:hkdf", "dep:hmac", "dep:p256", "dep:p384", "dep:rand", "dep:sha2", "dep:base64ct", "dep:ecdsa", "dep:sec1"]
deterministic_rand = ["dep:rand"]
no-cfi = []

[dependencies]
arrayvec = { version = "0.7.4", default-features = false, features = ["zeroize"] }
caliptra-cfi-lib-git = { workspace = true, default-features = false, features = ["cfi", "cfi-counter" ] }
caliptra-cfi-derive-git.workspace = true
ecdsa = { version = "0.16.9", optional = true, features = ["pem"]}
hkdf = { version = "0.12.3", optional = true }
hmac = {version="0.12.1", optional = true}
Expand Down
25 changes: 25 additions & 0 deletions crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,18 @@ pub trait Crypto {
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

/// CFI wrapper around derive_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_derive_cdi(
&mut self,
algs: AlgLen,
measurement: &Digest,
info: &[u8],
) -> Result<Self::Cdi, CryptoError>;

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

/// CFI wrapper around derive_key_pair
///
/// 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(
&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
4 changes: 4 additions & 0 deletions crypto/src/openssl.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Licensed under the Apache-2.0 license

use crate::{hkdf::*, AlgLen, Crypto, CryptoBuf, CryptoError, Digest, EcdsaPub, Hasher, HmacSig};
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_derive_git::cfi_impl_fn;
use openssl::{
bn::{BigNum, BigNumContext},
ec::{EcGroup, EcKey, EcPoint},
Expand Down Expand Up @@ -122,6 +124,7 @@ impl Crypto for OpensslCrypto {
Ok(OpensslHasher(openssl::hash::Hasher::new(md)?))
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_cdi(
&mut self,
algs: AlgLen,
Expand All @@ -131,6 +134,7 @@ impl Crypto for OpensslCrypto {
hkdf_derive_cdi(algs, measurement, info)
}

#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn derive_key_pair(
&mut self,
algs: AlgLen,
Expand Down
7 changes: 6 additions & 1 deletion dpe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version = "0.1.0"
edition = "2021"

[features]
default = ["dpe_profile_p256_sha256"]
default = ["dpe_profile_p256_sha256", "no-cfi"]
dpe_profile_p256_sha256 = ["platform/dpe_profile_p256_sha256"]
dpe_profile_p384_sha384 = ["platform/dpe_profile_p384_sha384"]
# Run ARBITRARY_MAX_HANDLES=n cargo build --features arbitrary_max_handles to use this feature
Expand All @@ -22,18 +22,23 @@ disable_internal_info = []
disable_internal_dice = []
disable_is_ca = []
disable_retain_parent_context = []
no-cfi = ["crypto/no-cfi"]

[dependencies]
bitflags = "2.4.0"
caliptra-cfi-lib-git = { workspace = true, default-features = false, features = ["cfi", "cfi-counter" ] }
caliptra-cfi-derive-git.workspace = true
constant_time_eq = "0.3.0"
crypto = {path = "../crypto", default-features = false}
platform = {path = "../platform", default-features = false}
ufmt = { git = "https://github.com/korran/ufmt.git", rev = "1d0743c1ffffc68bc05ca8eeb81c166192863f33", features = ["inline"] }
zerocopy = "0.6.1"
zeroize = { version = "1.6.0", default-features = false, features = ["zeroize_derive"] }
cfg-if = "1.0.0"

[dev-dependencies]
asn1 = "0.13.0"
caliptra-cfi-lib-git = { workspace = true, features = ["cfi-test"] }
openssl = "0.10.57"
x509-parser = "0.15.1"
crypto = {path = "../crypto", features = ["deterministic_rand", "openssl"]}
Expand Down
27 changes: 27 additions & 0 deletions dpe/fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 38 additions & 10 deletions dpe/src/commands/certify_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ use crate::{
DPE_PROFILE, MAX_CERT_SIZE, MAX_HANDLES,
};
use bitflags::bitflags;
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_derive_git::cfi_impl_fn;
use caliptra_cfi_lib_git::cfi_launder;
#[cfg(not(feature = "no-cfi"))]
use caliptra_cfi_lib_git::{cfi_assert, cfi_assert_eq};
use cfg_if::cfg_if;
use crypto::Crypto;
use platform::{Platform, MAX_ISSUER_NAME_SIZE};

Expand Down Expand Up @@ -41,6 +47,7 @@ impl CertifyKeyCmd {
}

impl CommandExecution for CertifyKeyCmd {
#[cfg_attr(not(feature = "no-cfi"), cfi_impl_fn)]
fn execute(
&self,
dpe: &mut DpeInstance,
Expand All @@ -64,21 +71,40 @@ impl CommandExecution for CertifyKeyCmd {
if !context.allow_x509() {
return Err(DpeErrorCode::InvalidArgument);
}
} else if self.format == Self::FORMAT_CSR && !dpe.support.csr() {
return Err(DpeErrorCode::ArgumentNotSupported);
}

// Make sure the command is coming from the right locality.
if context.locality != locality {
return Err(DpeErrorCode::InvalidLocality);
}

cfg_if! {
if #[cfg(not(feature = "no-cfi"))] {
cfi_assert!(!self.uses_is_ca() || dpe.support.is_ca());
cfi_assert!(!self.uses_is_ca() || context.allow_ca());
cfi_assert!(self.format != Self::FORMAT_X509 || dpe.support.x509());
cfi_assert!(self.format != Self::FORMAT_X509 || context.allow_x509());
cfi_assert!(self.format != Self::FORMAT_CSR || dpe.support.csr());
cfi_assert_eq(context.locality, locality);
}
}

let algs = DPE_PROFILE.alg_len();
let digest = dpe.compute_measurement_hash(env, idx)?;
let cdi = env
.crypto
.derive_cdi(DPE_PROFILE.alg_len(), &digest, b"DPE")?;
let (priv_key, pub_key) = env
.crypto
.derive_key_pair(algs, &cdi, &self.label, b"ECC")?;
let key_pair = env.crypto.derive_key_pair(algs, &cdi, &self.label, b"ECC");
if cfi_launder(key_pair.is_ok()) {
sree-revoori1 marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(not(feature = "no-cfi"))]
cfi_assert!(key_pair.is_ok());
} else {
#[cfg(not(feature = "no-cfi"))]
cfi_assert!(key_pair.is_err());
}
let (priv_key, pub_key) = key_pair?;

let mut subj_serial = [0u8; DPE_PROFILE.get_hash_size() * 2];
env.crypto
Expand Down Expand Up @@ -109,6 +135,8 @@ impl CommandExecution for CertifyKeyCmd {
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 {
Expand Down Expand Up @@ -141,15 +169,10 @@ impl CommandExecution for CertifyKeyCmd {
u32::try_from(bytes_written).map_err(|_| DpeErrorCode::InternalError)?
}
Self::FORMAT_CSR => {
if !dpe.support.csr() {
return Err(DpeErrorCode::ArgumentNotSupported);
}

#[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);
if issuer_len > MAX_ISSUER_NAME_SIZE {
return Err(DpeErrorCode::InternalError);
}
let mut bytes_written = cert_req_info_writer.encode_certification_request_info(
&pub_key,
&subject_name,
Expand Down Expand Up @@ -230,6 +253,7 @@ mod tests {
dpe_instance::tests::{TestTypes, SIMULATION_HANDLE, TEST_LOCALITIES},
support::Support,
};
use caliptra_cfi_lib_git::CfiCounter;
use cms::{
content_info::{CmsVersion, ContentInfo},
signed_data::{SignedData, SignerIdentifier},
Expand Down Expand Up @@ -262,6 +286,7 @@ mod tests {

#[test]
fn test_deserialize_certify_key() {
CfiCounter::reset_for_test();
let mut command = CommandHdr::new_for_test(Command::CERTIFY_KEY)
.as_bytes()
.to_vec();
Expand All @@ -274,6 +299,7 @@ mod tests {

#[test]
fn test_certify_key_x509() {
CfiCounter::reset_for_test();
let mut env = DpeEnv::<TestTypes> {
crypto: OpensslCrypto::new(),
platform: DefaultPlatform,
Expand Down Expand Up @@ -314,6 +340,7 @@ mod tests {

#[test]
fn test_is_ca() {
CfiCounter::reset_for_test();
let mut env = DpeEnv::<TestTypes> {
crypto: OpensslCrypto::new(),
platform: DefaultPlatform,
Expand Down Expand Up @@ -385,6 +412,7 @@ mod tests {

#[test]
fn test_certify_key_csr() {
CfiCounter::reset_for_test();
let mut env = DpeEnv::<TestTypes> {
crypto: OpensslCrypto::new(),
platform: DefaultPlatform,
Expand Down
Loading
Loading