Skip to content

Commit

Permalink
Merge pull request #685 from fortanix/raoul/rte-166-verify_tcb_info_d…
Browse files Browse the repository at this point in the history
…ates

[RTE-166] Verify tcb info dates
  • Loading branch information
raoulstrackx authored Jan 23, 2025
2 parents 913a6a2 + 2c245bf commit b187d76
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 17 deletions.
17 changes: 12 additions & 5 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions intel-sgx/pcs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ categories = ["os", "hardware-support"]


[dependencies]
chrono = { version = "0.4.39", features = ["now"] }
dcap-ql = { version = "0.4.0", path = "../dcap-ql", default-features = false }
sgx-isa = { version = "0.4.1", path = "../sgx-isa", default-features = true }
pkix = "0.2.0"
Expand All @@ -38,6 +39,7 @@ mbedtls = { version = "0.12.3", features = ["std", "time"], default-features = f

[dev-dependencies]
hex = "0.4.2"
tempdir = "0.3.7"

[features]
verify = ["anyhow", "mbedtls", "mbedtls/x509"]
Expand Down
19 changes: 19 additions & 0 deletions intel-sgx/pcs/src/iso8601.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use chrono::{DateTime, NaiveDateTime, Utc};
use serde::{Deserialize, Deserializer};
use serde::de;

const ISO8601_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%SZ";

pub fn serialize<S>(timestamp: &DateTime<Utc>, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
let timestamp = timestamp.format(ISO8601_FORMAT).to_string();
serializer.serialize_str(&timestamp)
}

pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<DateTime<Utc>, D::Error> {
let timestamp = String::deserialize(deserializer)?;
let timestamp = NaiveDateTime::parse_from_str(&timestamp, &ISO8601_FORMAT).map_err(de::Error::custom)?;
Ok(timestamp.and_utc())
}
8 changes: 6 additions & 2 deletions intel-sgx/pcs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub use crate::qe_identity::{QeIdentity, QeIdentitySigned};
pub use crate::tcb_info::{Fmspc, TcbInfo, TcbData};

mod io;
mod iso8601;
mod pckcrl;
mod pckcrt;
mod pckid;
Expand Down Expand Up @@ -89,6 +90,9 @@ quick_error! {
InvalidQe3Id(err: MbedError){
display("Invalid QE3 ID: {}", err)
}
Qe3NotValid(err: String){
display("Invalid QE3: {}", err)
}
InvalidFormatQe3Identity{
display("Invalid QE3 Identity format")
}
Expand Down Expand Up @@ -123,12 +127,12 @@ quick_error! {

pub trait VerificationType {}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Verified;

impl VerificationType for Verified {}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Unverified;

impl VerificationType for Unverified {}
Expand Down
30 changes: 25 additions & 5 deletions intel-sgx/pcs/src/qe_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::convert::TryInto;
use std::marker::PhantomData;
use std::path::PathBuf;

use chrono::{DateTime, Utc};
use serde::{de, Deserialize, Deserializer, Serialize};
use serde_json::value::RawValue;
use sgx_isa::{Attributes, Miscselect};
Expand Down Expand Up @@ -47,8 +48,10 @@ impl TcbLevel {
pub struct QeIdentity<V: VerificationType = Verified> {
version: u16,
id: String,
issue_date: String,
next_update: String,
#[serde(with = "crate::iso8601")]
issue_date: DateTime<Utc>,
#[serde(with = "crate::iso8601")]
next_update: DateTime<Utc>,
tcb_evaluation_data_number: u64,
#[serde(deserialize_with = "miscselect_deserializer", serialize_with = "miscselect_serializer")]
miscselect: Miscselect,
Expand Down Expand Up @@ -79,8 +82,10 @@ impl<'de> Deserialize<'de> for QeIdentity<Unverified> {
struct Dummy {
version: u16,
id: String,
issue_date: String,
next_update: String,
#[serde(with = "crate::iso8601")]
issue_date: DateTime<Utc>,
#[serde(with = "crate::iso8601")]
next_update: DateTime<Utc>,
tcb_evaluation_data_number: u64,
#[serde(deserialize_with = "miscselect_deserializer", serialize_with = "miscselect_serializer")]
miscselect: Miscselect,
Expand Down Expand Up @@ -339,9 +344,20 @@ impl QeIdentitySigned {
tcb_levels,
type_: PhantomData,
} = serde_json::from_str(&self.raw_enclave_identity).map_err(|e| Error::ParseError(e))?;

if version != 2 {
return Err(Error::UnknownQeIdentityVersion(version));
}

let now = Utc::now();
if now < issue_date {
return Err(Error::Qe3NotValid(format!("QE3 only valid from {}", issue_date)))
}

if next_update < now {
return Err(Error::Qe3NotValid(format!("QE3 expired on {}", next_update)))
}

Ok(QeIdentity::<Verified> {
version,
id,
Expand All @@ -363,6 +379,7 @@ impl QeIdentitySigned {
#[cfg(feature = "verify")]
#[cfg(test)]
mod tests {
use crate::Error;
#[cfg(not(target_env = "sgx"))]
use crate::qe_identity::QeIdentitySigned;

Expand All @@ -373,7 +390,10 @@ mod tests {

let root_cert = include_bytes!("../tests/data/root_SGX_CA_der.cert");
let root_certs = [&root_cert[..]];
assert!(qe_id.verify(&root_certs).is_ok());
match qe_id.verify(&root_certs) {
Err(Error::Qe3NotValid(msg)) => assert_eq!(msg, "QE3 expired on 2020-06-17 17:49:21 UTC"),
e => assert!(false, "wrong result: {:?}", e),
}
}

#[test]
Expand Down
33 changes: 28 additions & 5 deletions intel-sgx/pcs/src/tcb_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::convert::TryFrom;
use std::marker::PhantomData;
use std::path::PathBuf;

use chrono::{DateTime, Utc};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::value::RawValue;
#[cfg(feature = "verify")]
Expand Down Expand Up @@ -135,8 +136,8 @@ fn sgx_platform() -> Platform {
pub struct TcbData<V: VerificationType = Verified> {
id: Platform,
version: u16,
issue_date: String,
next_update: String,
issue_date: DateTime<Utc>,
next_update: DateTime<Utc>,
fmspc: Fmspc,
pce_id: String,
tcb_type: u16,
Expand All @@ -156,8 +157,10 @@ impl<'de> Deserialize<'de> for TcbData<Unverified> {
#[serde(default = "sgx_platform")]
id: Platform,
version: u16,
issue_date: String,
next_update: String,
#[serde(with = "crate::iso8601")]
issue_date: DateTime<Utc>,
#[serde(with = "crate::iso8601")]
next_update: DateTime<Utc>,
fmspc: Fmspc,
pce_id: String,
tcb_type: u16,
Expand Down Expand Up @@ -346,6 +349,14 @@ impl TcbInfo {
..
} = TcbData::parse(&self.raw_tcb_info)?;

let now = Utc::now();
if now < issue_date {
return Err(Error::InvalidTcbInfo(format!("TCB Info only valid from {}", issue_date)))
}
if next_update < now {
return Err(Error::InvalidTcbInfo(format!("TCB Info expired on {}", next_update)))
}

Ok(TcbData::<Verified> {
id,
version,
Expand All @@ -370,8 +381,10 @@ impl TcbInfo {
mod tests {
#[cfg(not(target_env = "sgx"))]
use {
crate::Error,
crate::tcb_info::{Fmspc, TcbInfo},
std::convert::TryFrom,
tempdir::TempDir,
};

#[test]
Expand All @@ -381,7 +394,17 @@ mod tests {
TcbInfo::restore("./tests/data/", &Fmspc::try_from("00906ea10000").expect("static fmspc")).expect("validated");
let root_certificate = include_bytes!("../tests/data/root_SGX_CA_der.cert");
let root_certificates = [&root_certificate[..]];
assert!(info.verify(&root_certificates).is_ok());
match info.verify(&root_certificates) {
Err(Error::InvalidTcbInfo(msg)) => assert_eq!(msg, String::from("TCB Info expired on 2020-06-17 17:49:24 UTC")),
e => assert!(false, "wrong result: {:?}", e),
}

// Test serialization/deserialization
let temp_dir = TempDir::new("tempdir").unwrap();
let path = temp_dir.path().as_os_str().to_str().unwrap();
info.store(&path).unwrap();
let info2 = TcbInfo::restore(&path, &Fmspc::try_from("00906ea10000").expect("static fmspc")).unwrap();
assert_eq!(info, info2);
}

#[test]
Expand Down

0 comments on commit b187d76

Please sign in to comment.