Skip to content

Commit

Permalink
feat: configuration for attestation
Browse files Browse the repository at this point in the history
Co-authored-by: Roman Volosatovs <roman@profian.com>
Signed-off-by: Richard Zak <richard@profian.com>
  • Loading branch information
rjzak and rvolosatovs committed Dec 6, 2022
1 parent 48ffff6 commit 9a9d9ac
Show file tree
Hide file tree
Showing 16 changed files with 1,142 additions and 141 deletions.
43 changes: 43 additions & 0 deletions Cargo.lock

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

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,20 @@ anyhow = { version = "^1.0.66", default-features = false }
base64 = { version = "^0.13.1", default-features = false }
mime = { version = "^0.3.16", default-features = false }
confargs = { version = "^0.1.3", default-features = false }
serde = { version = "1.0", features = ["derive"], default-features = false }
toml = { version = "0.5", default-features = false }

[target.'cfg(not(target_os = "wasi"))'.dependencies]
tokio = { version = "^1.23.0", features = ["rt-multi-thread", "macros"], default-features = false }

[dev-dependencies]
validation_common = { path = "crates/validation_common" }
tower = { version = "^0.4.11", features = ["util"], default-features = false }
axum = { version = "^0.5.17", default-features = false }
http = { version = "^0.2.6", default-features = false }
memoffset = { version = "0.7.1", default-features = false }
rstest = { version = "0.16", default-features = false }
sgx = { version = "0.6.0", default-features = false }
testaso = { version = "0.1", default-features = false }

[profile.release]
Expand All @@ -51,7 +55,8 @@ strip = true
[workspace]
resolver = '2'
members = [
'crates/cryptography',
'crates/sgx_validation',
'crates/snp_validation',
'crates/cryptography',
'crates/validation_common',
]
1 change: 1 addition & 0 deletions crates/cryptography/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rand = { version = "0.8", features = ["std"], default-features = false }
rsa = {version = "0.7.2", features = ["std"], default-features = false }
rustls-pemfile = {version = "1.0.1", default-features = false }
sec1 = { version = "0.3", features = ["std", "pkcs8"], default-features = false }
serde = { version = "1.0", features = ["derive", "std"], default-features = false }
sha2 = { version = "^0.10.2", default-features = false }
signature = {version = "1.6", default-features = false }
spki = { version = "0.6", default-features = false }
Expand Down
3 changes: 3 additions & 0 deletions crates/sgx_validation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ description = "Intel SGX Attestation validation library for Steward"

[dependencies]
cryptography = { path = "../cryptography" }
validation_common = { path = "../validation_common" }
anyhow = { version = "^1.0.55", default-features = false }
der = { version = "0.6", features = ["std"], default-features = false }
serde = { version = "1.0", features = ["derive", "std"], default-features = false }
sgx = { version = "0.6.0", default-features = false }

[dev-dependencies]
testaso = { version = "0.1", default-features = false }
toml = { version = "0.5", default-features = false }
164 changes: 164 additions & 0 deletions crates/sgx_validation/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// SPDX-FileCopyrightText: 2022 Profian Inc. <opensource@profian.com>
// SPDX-License-Identifier: AGPL-3.0-only

use serde::{Deserialize, Deserializer};
use sgx::parameters::{Features, MiscSelect};
use validation_common::Measurements;

#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
pub enum SgxFeatures {
CET,
Debug,
EInitKey,
KSS,
ProvisioningKey,
}

#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
pub enum SgxMiscSelect {
EXINFO,
}

#[derive(Clone, Deserialize, Debug, Default, Eq, PartialEq)]
pub struct Config {
/// Values for `mrsigner` in the report body, as `Measurements::signer()`
/// This is the list of public keys which have signed the Enarx binary.
/// Values for `mrenclave` in the report body, as `Measurements::hash()`
/// This is the hash of the Enclave environment after the Enarx binary is loaded but
/// before any workload is loaded, so this is a hash of the Enarx binary in memory.
#[serde(default, flatten)]
pub measurements: Measurements<32>,

/// Values for `features`.
/// Checked against `sgx::parameters::attributes::Attributes::features()`
/// These are CPU features reported by the CPU firmware, and most features are not
/// relevant to security concerns, but are used for code execution. Only the features
/// relevant for security are parsed here.
#[serde(default)]
#[serde(deserialize_with = "from_features")]
pub features: Features,

/// Minimum value for `isv_svn`.
/// Checked against `sgx::report::ReportBody::enclave_security_version()`
/// This is the security version of the enclave.
pub enclave_security_version: Option<u16>,

/// Value for `isv_prodid`, do not allow other ids.
/// Checked against `sgx::report::ReportBody::enclave_product_id()`
pub enclave_product_id: Option<u16>,

/// Extra enclave creation parameters
/// Checked against `sgx::report::ReportBody::misc_select()`
#[serde(default)]
#[serde(deserialize_with = "from_misc_select")]
pub misc_select: MiscSelect,
}

fn from_features<'de, D>(deserializer: D) -> Result<Features, D::Error>
where
D: Deserializer<'de>,
{
let s: Vec<SgxFeatures> = Deserialize::deserialize(deserializer)?;

let mut flags = Features::empty();

// Must be set according to Intel SGX documentation, this indicates permission
// to create SGX enclaves.
flags |= Features::INIT;

// Required by Enarx, as Wasmtime requires 64-bit, and modern systems are all 64-bit anyway
flags |= Features::MODE64BIT;

for flag in s {
match flag {
SgxFeatures::CET => {
flags |= Features::CET;
}
SgxFeatures::Debug => {
flags |= Features::DEBUG;
}
SgxFeatures::EInitKey => {
flags |= Features::EINIT_KEY;
}
SgxFeatures::KSS => {
flags |= Features::KSS;
}
SgxFeatures::ProvisioningKey => {
flags |= Features::PROVISIONING_KEY;
}
}
}

Ok(flags)
}

fn from_misc_select<'de, D>(deserializer: D) -> Result<MiscSelect, D::Error>
where
D: Deserializer<'de>,
{
let s: Vec<SgxMiscSelect> = Deserialize::deserialize(deserializer)?;

let mut flags = MiscSelect::default();

for flag in s {
match flag {
SgxMiscSelect::EXINFO => {
flags |= MiscSelect::EXINFO;
}
}
}

Ok(flags)
}

#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
use validation_common::Digest;

#[test]
fn empty_config() {
assert!(toml::from_str::<Config>("").is_err());
}

#[test]
fn serde() {
const SIGNER: &str =
r#"signer = ["2eba0f494f428e799c22d6f12778aebea4dc8d991f9e63fd3cddd57ac6eb5dd9"]"#;

let signer: HashSet<_> = vec![Digest([
0x2e, 0xba, 0x0f, 0x49, 0x4f, 0x42, 0x8e, 0x79, 0x9c, 0x22, 0xd6, 0xf1, 0x27, 0x78,
0xae, 0xbe, 0xa4, 0xdc, 0x8d, 0x99, 0x1f, 0x9e, 0x63, 0xfd, 0x3c, 0xdd, 0xd5, 0x7a,
0xc6, 0xeb, 0x5d, 0xd9,
])]
.into_iter()
.collect();

let config: Config = toml::from_str(&format!(
r#"
{SIGNER}
features = ["Debug"]
misc_select = ["EXINFO"]
"#,
))
.expect("Couldn't deserialize");

assert_eq!(config.measurements.signer, signer);
assert_eq!(
config.features.bits(),
(Features::DEBUG | Features::INIT | Features::MODE64BIT).bits()
);
assert!(config.misc_select.contains(MiscSelect::EXINFO));
}

#[test]
fn too_short() {
let config: Result<Config, toml::de::Error> = toml::from_str(
r#"
signer = ["41c179d5c0d5bc4915752ccf9bbd2baa574716832235ef5bb998fadcda1e46"]
"#,
);
assert!(config.is_err());
}
}
Binary file added crates/sgx_validation/src/icelake.signed.csr
Binary file not shown.
Loading

0 comments on commit 9a9d9ac

Please sign in to comment.