DCAP cert validation tests (#6)

This commit is contained in:
Shoaib Ahmed 2024-06-20 22:09:29 +02:00 committed by GitHub
parent b92242c09a
commit fcad39e5d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 259 additions and 10 deletions

1
Cargo.lock generated
View file

@ -2369,6 +2369,7 @@ dependencies = [
"cosmwasm-std", "cosmwasm-std",
"der", "der",
"displaydoc", "displaydoc",
"hex",
"hex-literal", "hex-literal",
"mc-attestation-verifier", "mc-attestation-verifier",
"mc-sgx-core-types", "mc-sgx-core-types",

View file

@ -31,3 +31,6 @@ mc-sgx-dcap-sys-types.workspace = true
# cosmos # cosmos
cosmwasm-schema.workspace = true cosmwasm-schema.workspace = true
cosmwasm-std.workspace = true cosmwasm-std.workspace = true
[dev-dependencies]
hex = "0.4.3"

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEjzCCBDSgAwIBAgIVAPtJxlxRlleZOb/spRh9U8K7AT/3MAoGCCqGSM49BAMC
MHExIzAhBgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQK
DBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV
BAgMAkNBMQswCQYDVQQGEwJVUzAeFw0yMjA2MTMyMTQ2MzRaFw0yOTA2MTMyMTQ2
MzRaMHAxIjAgBgNVBAMMGUludGVsIFNHWCBQQ0sgQ2VydGlmaWNhdGUxGjAYBgNV
BAoMEUludGVsIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkG
A1UECAwCQ0ExCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
j/Ee1lkGJofDX745Ks5qxqu7Mk7Mqcwkx58TCSTsabRCSvobSl/Ts8b0dltKUW3j
qRd+SxnPEWJ+jUw+SpzwWaOCAqgwggKkMB8GA1UdIwQYMBaAFNDoqtp11/kuSReY
PHsUZdDV8llNMGwGA1UdHwRlMGMwYaBfoF2GW2h0dHBzOi8vYXBpLnRydXN0ZWRz
ZXJ2aWNlcy5pbnRlbC5jb20vc2d4L2NlcnRpZmljYXRpb24vdjMvcGNrY3JsP2Nh
PXByb2Nlc3NvciZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFKy9gk624HzNnDyCw7QW
nhmVfE31MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIIB1AYJKoZIhvhN
AQ0BBIIBxTCCAcEwHgYKKoZIhvhNAQ0BAQQQ36FQl3ntUr3KUwbEFvmRGzCCAWQG
CiqGSIb4TQENAQIwggFUMBAGCyqGSIb4TQENAQIBAgERMBAGCyqGSIb4TQENAQIC
AgERMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgEEMBAGCyqGSIb4
TQENAQIFAgEBMBEGCyqGSIb4TQENAQIGAgIAgDAQBgsqhkiG+E0BDQECBwIBBjAQ
BgsqhkiG+E0BDQECCAIBADAQBgsqhkiG+E0BDQECCQIBADAQBgsqhkiG+E0BDQEC
CgIBADAQBgsqhkiG+E0BDQECCwIBADAQBgsqhkiG+E0BDQECDAIBADAQBgsqhkiG
+E0BDQECDQIBADAQBgsqhkiG+E0BDQECDgIBADAQBgsqhkiG+E0BDQECDwIBADAQ
BgsqhkiG+E0BDQECEAIBADAQBgsqhkiG+E0BDQECEQIBCzAfBgsqhkiG+E0BDQEC
EgQQERECBAGABgAAAAAAAAAAADAQBgoqhkiG+E0BDQEDBAIAADAUBgoqhkiG+E0B
DQEEBAYAkG7VAAAwDwYKKoZIhvhNAQ0BBQoBADAKBggqhkjOPQQDAgNJADBGAiEA
1XJi0ht4hw8YtC6E4rYscp9bF+7UOhVGeKePA5TW2FQCIQCIUAaewOuWOIvstZN4
V8Zu8NFCC4vFg+cZqO6QfezEaA==
-----END CERTIFICATE-----

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICmDCCAj6gAwIBAgIVANDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMC
MGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD
b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw
CQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHExIzAh
BgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQKDBFJbnRl
bCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNB
MQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL9q+NMp2IOg
tdl1bk/uWZ5+TGQm8aCi8z78fs+fKCQ3d+uDzXnVTAT2ZhDCifyIuJwvN3wNBp9i
HBSSMJMJrBOjgbswgbgwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqww
UgYDVR0fBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNl
cnZpY2VzLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFNDo
qtp11/kuSReYPHsUZdDV8llNMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG
AQH/AgEAMAoGCCqGSM49BAMCA0gAMEUCIQCJgTbtVqOyZ1m3jqiAXM6QYa6r5sWS
4y/G7y8uIJGxdwIgRqPvBSKzzQagBLQq5s5A70pdoiaRJ8z/0uDz4NgV91k=
-----END CERTIFICATE-----

Binary file not shown.

View file

@ -0,0 +1 @@
{"enclaveIdentity":{"id":"QE","version":2,"issueDate":"2023-07-12T20:48:25Z","nextUpdate":"2023-08-11T20:48:25Z","tcbEvaluationDataNumber":15,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":8},"tcbDate":"2023-02-15T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00615"]},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]}]},"signature":"953add69a564b80c43adb9c9dbc888da81aad8af240cd7dfd751f0209d262a71d9240603a528cb766e9fc3278722e59a43f2a2e43b55c776a7b48acbe8cd61a3"}

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw
aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv
cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ
BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG
A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0
aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT
AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7
1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB
uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ
MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50
ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV
Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI
KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg
AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=
-----END CERTIFICATE-----

Binary file not shown.

View file

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw
aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv
cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ
BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG
A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw
b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD
VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv
P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju
ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f
BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz
LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK
QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG
SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj
ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==
-----END CERTIFICATE-----

View file

@ -5,17 +5,110 @@ pub mod mc_attest_verifier_types;
/// Root anchor PEM file for use with DCAP /// Root anchor PEM file for use with DCAP
pub const DCAP_ROOT_ANCHOR: &str = include_str!("../../data/DcapRootCACert.pem"); pub const DCAP_ROOT_ANCHOR: &str = include_str!("../../data/DcapRootCACert.pem");
pub use mc_attest_verifier::dcap::DcapVerifier; use mc_attestation_verifier::*;
pub use mc_attest_verifier_types::verification::EnclaveReportDataContents; use mc_sgx_dcap_types::{Collateral, Quote3};
pub use mc_attestation_verifier::*;
pub use mc_sgx_dcap_sys_types::sgx_ql_qve_collateral_t; use self::{
pub use mc_sgx_dcap_types::{CertificationData, Collateral}; mc_attest_verifier::dcap::{DcapVerifier, DcapVerifierOutput},
pub use x509_cert::Certificate; mc_attest_verifier_types::verification::EnclaveReportDataContents,
};
pub fn verify(
quote: Quote3<Vec<u8>>,
collateral: Collateral,
identities: &[TrustedIdentity],
) -> VerificationOutput<DcapVerifierOutput> {
let report_data_contents = EnclaveReportDataContents::new([0x42u8; 16].into(), [0xAAu8; 32]);
let evidence = Evidence::new(quote, collateral).expect("Failed to get evidence");
let verifier = DcapVerifier::new(identities, None, report_data_contents);
verifier.verify(&evidence)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use hex::FromHex;
use hex_literal::hex; use hex_literal::hex;
use mc_sgx_dcap_types::Quote3; use mc_attestation_verifier::{Evidence, EvidenceVerifier, TrustedMrEnclaveIdentity, Verifier};
use mc_sgx_core_types::MrEnclave;
use mc_sgx_dcap_sys_types::sgx_ql_qve_collateral_t;
use mc_sgx_dcap_types::{Collateral, Quote3};
use crate::intel_sgx::dcap::certificate_chain::TlsCertificateChainVerifier;
const TCB_INFO_JSON: &str = include_str!("../../data/fmspc_00906ED50000_2023_07_12.json");
const QE_IDENTITY_JSON: &str = include_str!("../../data/qe_identity.json");
fn collateral(tcb_info: &str, qe_identity: &str) -> Collateral {
let mut sgx_collateral = sgx_ql_qve_collateral_t::default();
// SAFETY: Version is a union which is inherently unsafe
#[allow(unsafe_code)]
let version = unsafe { sgx_collateral.__bindgen_anon_1.__bindgen_anon_1.as_mut() };
version.major_version = 3;
version.minor_version = 1;
let pck_issuer_cert = include_str!("../../data/processor_ca.pem");
let root_cert = include_str!("../../data/root_ca.pem");
let mut pck_crl_chain = [pck_issuer_cert, root_cert].join("\n").as_bytes().to_vec();
pck_crl_chain.push(0);
sgx_collateral.pck_crl_issuer_chain = pck_crl_chain.as_ptr() as _;
sgx_collateral.pck_crl_issuer_chain_size = pck_crl_chain.len() as u32;
let mut root_crl = include_bytes!("../../data/root_crl.der").to_vec();
root_crl.push(0);
sgx_collateral.root_ca_crl = root_crl.as_ptr() as _;
sgx_collateral.root_ca_crl_size = root_crl.len() as u32;
let mut pck_crl = include_bytes!("../../data/processor_crl.der").to_vec();
pck_crl.push(0);
sgx_collateral.pck_crl = pck_crl.as_ptr() as _;
sgx_collateral.pck_crl_size = pck_crl.len() as u32;
let tcb_cert = include_str!("../../data/tcb_signer.pem");
let mut tcb_chain = [tcb_cert, root_cert].join("\n").as_bytes().to_vec();
tcb_chain.push(0);
sgx_collateral.tcb_info_issuer_chain = tcb_chain.as_ptr() as _;
sgx_collateral.tcb_info_issuer_chain_size = tcb_chain.len() as u32;
sgx_collateral.tcb_info = tcb_info.as_ptr() as _;
sgx_collateral.tcb_info_size = tcb_info.len() as u32;
// For live data the QE identity uses the same chain as the TCB info
sgx_collateral.qe_identity_issuer_chain = tcb_chain.as_ptr() as _;
sgx_collateral.qe_identity_issuer_chain_size = tcb_chain.len() as u32;
sgx_collateral.qe_identity = qe_identity.as_ptr() as _;
sgx_collateral.qe_identity_size = qe_identity.len() as u32;
Collateral::try_from(&sgx_collateral).expect("Failed to parse collateral")
}
#[test]
#[ignore]
fn evidence_verifier_succeeds_with_tls_x509_verifier() {
let root_ca = include_str!("../../data/root_ca.pem");
let certificate_verifier = TlsCertificateChainVerifier::new(root_ca);
let identities = [TrustedMrEnclaveIdentity::new(
MrEnclave::from_hex("840d61b0585dc8b4dc90f53af293c760fda06bee75978a6a86263ffb296423f4")
.expect("malformed MRENCLAVE hex"),
[""; 0],
["INTEL-SA-00334", "INTEL-SA-00615"],
)
.into()];
let verifier = EvidenceVerifier::new(certificate_verifier, identities.as_ref(), None);
let quote_bytes = include_bytes!("../../data/hw_quote.dat");
let quote = Quote3::try_from(quote_bytes.as_ref()).expect("Failed to parse quote");
let collateral = collateral(TCB_INFO_JSON, QE_IDENTITY_JSON);
let evidence: Evidence<Vec<u8>> = Evidence::new(quote, collateral)
.expect("Failed to create evidence")
.into();
let verification = verifier.verify(&evidence);
assert_eq!(verification.is_success().unwrap_u8(), 1);
// let displayable = VerificationTreeDisplay::new(&verifier, verification);
// println!("\n{displayable}");
}
#[test] #[test]
fn test_quote_parse() { fn test_quote_parse() {

View file

@ -5,6 +5,13 @@ use x509_cert::{crl::CertificateList, Certificate};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)] #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
pub struct TlsCertificateChainVerifier; pub struct TlsCertificateChainVerifier;
impl TlsCertificateChainVerifier {
pub fn new(_root_ca: &str) -> Self {
// FIXME(hu55a1n1)
Self
}
}
impl CertificateChainVerifier for TlsCertificateChainVerifier { impl CertificateChainVerifier for TlsCertificateChainVerifier {
fn verify_certificate_chain<'a, 'b>( fn verify_certificate_chain<'a, 'b>(
&self, &self,
@ -15,3 +22,70 @@ impl CertificateChainVerifier for TlsCertificateChainVerifier {
todo!() todo!()
} }
} }
#[cfg(test)]
mod test {
use der::{Decode, DecodePem};
use super::*;
const LEAF_CERT: &str = include_str!("../../../data/leaf_cert.pem");
const PROCESSOR_CA: &str = include_str!("../../../data/processor_ca.pem");
const ROOT_CA: &str = include_str!("../../../data/root_ca.pem");
const PROCESSOR_CRL: &[u8] = include_bytes!("../../../data/processor_crl.der");
const ROOT_CRL: &[u8] = include_bytes!("../../../data/root_crl.der");
#[test]
#[ignore]
fn verify_valid_cert_chain() {
let chain = [LEAF_CERT, PROCESSOR_CA, ROOT_CA]
.iter()
.map(|cert| Certificate::from_pem(cert).expect("failed to parse cert"))
.collect::<Vec<_>>();
let crls = [ROOT_CRL, PROCESSOR_CRL]
.iter()
.map(|crl| CertificateList::from_der(crl).expect("failed to parse CRL"))
.collect::<Vec<_>>();
let verifier = TlsCertificateChainVerifier::new(ROOT_CA);
assert!(verifier
.verify_certificate_chain(chain.iter(), crls.iter(), None)
.is_ok());
}
#[test]
#[ignore]
fn invalid_cert_chain() {
let chain = [LEAF_CERT, ROOT_CA]
.iter()
.map(|cert| Certificate::from_pem(cert).expect("failed to parse cert"))
.collect::<Vec<_>>();
let crls = [ROOT_CRL, PROCESSOR_CRL]
.iter()
.map(|crl| CertificateList::from_der(crl).expect("failed to parse CRL"))
.collect::<Vec<_>>();
let verifier = TlsCertificateChainVerifier::new(ROOT_CA);
assert_eq!(
verifier.verify_certificate_chain(chain.iter(), crls.iter(), None),
Err(CertificateChainVerifierError::SignatureVerification)
);
}
#[test]
#[ignore]
fn unordered_cert_chain_succeeds() {
let chain = [PROCESSOR_CA, ROOT_CA, LEAF_CERT]
.iter()
.map(|cert| Certificate::from_pem(cert).expect("failed to parse cert"))
.collect::<Vec<_>>();
let crls = [ROOT_CRL, PROCESSOR_CRL]
.iter()
.map(|crl| CertificateList::from_der(crl).expect("failed to parse CRL"))
.collect::<Vec<_>>();
let verifier = TlsCertificateChainVerifier::new(ROOT_CA);
assert!(verifier
.verify_certificate_chain(chain.iter(), crls.iter(), None)
.is_ok());
}
// TODO(hu55a1n1) - add [PKITS tests](https://csrc.nist.gov/projects/pki-testing)
}

View file

@ -18,7 +18,7 @@ pub struct DcapVerifier {
verifier: And<EvidenceVerifier<TlsCertificateChainVerifier>, ReportDataHashVerifier>, verifier: And<EvidenceVerifier<TlsCertificateChainVerifier>, ReportDataHashVerifier>,
} }
type DcapVerifierOutput = AndOutput<EvidenceValue, ReportData>; pub type DcapVerifierOutput = AndOutput<EvidenceValue, ReportData>;
impl DcapVerifier { impl DcapVerifier {
/// Create a new instance of the DcapVerifier. /// Create a new instance of the DcapVerifier.

View file

@ -13,7 +13,8 @@
unused_qualifications, unused_qualifications,
warnings warnings
)] )]
#![forbid(unsafe_code)] // FIXME(hu55a1n1) - uncomment once we have better wrappers for FFI structs and ctors
// #![forbid(unsafe_code)]
pub mod intel_sgx; pub mod intel_sgx;