Skip to content

Commit 69a4f29

Browse files
rjzakrvolosatovs
andcommitted
feat: configuration for attestation
Co-authored-by: Roman Volosatovs <[email protected]> Signed-off-by: Richard Zak <[email protected]>
1 parent 48ffff6 commit 69a4f29

File tree

16 files changed

+1142
-141
lines changed

16 files changed

+1142
-141
lines changed

Cargo.lock

+43
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,20 @@ anyhow = { version = "^1.0.66", default-features = false }
3030
base64 = { version = "^0.13.1", default-features = false }
3131
mime = { version = "^0.3.16", default-features = false }
3232
confargs = { version = "^0.1.3", default-features = false }
33+
serde = { version = "1.0", features = ["derive"], default-features = false }
34+
toml = { version = "0.5", default-features = false }
3335

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

3739
[dev-dependencies]
40+
validation_common = { path = "crates/validation_common" }
3841
tower = { version = "^0.4.11", features = ["util"], default-features = false }
3942
axum = { version = "^0.5.17", default-features = false }
4043
http = { version = "^0.2.6", default-features = false }
4144
memoffset = { version = "0.7.1", default-features = false }
4245
rstest = { version = "0.16", default-features = false }
46+
sgx = { version = "0.6.0", default-features = false }
4347
testaso = { version = "0.1", default-features = false }
4448

4549
[profile.release]
@@ -51,7 +55,8 @@ strip = true
5155
[workspace]
5256
resolver = '2'
5357
members = [
58+
'crates/cryptography',
5459
'crates/sgx_validation',
5560
'crates/snp_validation',
56-
'crates/cryptography',
61+
'crates/validation_common',
5762
]

crates/cryptography/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rand = { version = "0.8", features = ["std"], default-features = false }
1313
rsa = {version = "0.7.2", features = ["std"], default-features = false }
1414
rustls-pemfile = {version = "1.0.1", default-features = false }
1515
sec1 = { version = "0.3", features = ["std", "pkcs8"], default-features = false }
16+
serde = { version = "1.0", features = ["derive", "std"], default-features = false }
1617
sha2 = { version = "^0.10.2", default-features = false }
1718
signature = {version = "1.6", default-features = false }
1819
spki = { version = "0.6", default-features = false }

crates/sgx_validation/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ description = "Intel SGX Attestation validation library for Steward"
77

88
[dependencies]
99
cryptography = { path = "../cryptography" }
10+
validation_common = { path = "../validation_common" }
1011
anyhow = { version = "^1.0.55", default-features = false }
1112
der = { version = "0.6", features = ["std"], default-features = false }
13+
serde = { version = "1.0", features = ["derive", "std"], default-features = false }
1214
sgx = { version = "0.6.0", default-features = false }
1315

1416
[dev-dependencies]
1517
testaso = { version = "0.1", default-features = false }
18+
toml = { version = "0.5", default-features = false }

crates/sgx_validation/src/config.rs

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// SPDX-FileCopyrightText: 2022 Profian Inc. <[email protected]>
2+
// SPDX-License-Identifier: AGPL-3.0-only
3+
4+
use serde::{Deserialize, Deserializer};
5+
use sgx::parameters::{Features, MiscSelect};
6+
use validation_common::Measurements;
7+
8+
#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
9+
pub enum SgxFeatures {
10+
CET,
11+
Debug,
12+
EInitKey,
13+
KSS,
14+
ProvisioningKey,
15+
}
16+
17+
#[derive(Clone, Deserialize, Debug, Eq, PartialEq)]
18+
pub enum SgxMiscSelect {
19+
EXINFO,
20+
}
21+
22+
#[derive(Clone, Deserialize, Debug, Default, Eq, PartialEq)]
23+
pub struct Config {
24+
/// Values for `mrsigner` in the report body, as `Measurements::signer()`
25+
/// This is the list of public keys which have signed the Enarx binary.
26+
/// Values for `mrenclave` in the report body, as `Measurements::hash()`
27+
/// This is the hash of the Enclave environment after the Enarx binary is loaded but
28+
/// before any workload is loaded, so this is a hash of the Enarx binary in memory.
29+
#[serde(default, flatten)]
30+
pub measurements: Measurements<32>,
31+
32+
/// Values for `features`.
33+
/// Checked against `sgx::parameters::attributes::Attributes::features()`
34+
/// These are CPU features reported by the CPU firmware, and most features are not
35+
/// relevant to security concerns, but are used for code execution. Only the features
36+
/// relevant for security are parsed here.
37+
#[serde(default)]
38+
#[serde(deserialize_with = "from_features")]
39+
pub features: Features,
40+
41+
/// Minimum value for `isv_svn`.
42+
/// Checked against `sgx::report::ReportBody::enclave_security_version()`
43+
/// This is the security version of the enclave.
44+
pub enclave_security_version: Option<u16>,
45+
46+
/// Value for `isv_prodid`, do not allow other ids.
47+
/// Checked against `sgx::report::ReportBody::enclave_product_id()`
48+
pub enclave_product_id: Option<u16>,
49+
50+
/// Extra enclave creation parameters
51+
/// Checked against `sgx::report::ReportBody::misc_select()`
52+
#[serde(default)]
53+
#[serde(deserialize_with = "from_misc_select")]
54+
pub misc_select: MiscSelect,
55+
}
56+
57+
fn from_features<'de, D>(deserializer: D) -> Result<Features, D::Error>
58+
where
59+
D: Deserializer<'de>,
60+
{
61+
let s: Vec<SgxFeatures> = Deserialize::deserialize(deserializer)?;
62+
63+
let mut flags = Features::empty();
64+
65+
// Must be set according to Intel SGX documentation, this indicates permission
66+
// to create SGX enclaves.
67+
flags |= Features::INIT;
68+
69+
// Required by Enarx, as Wasmtime requires 64-bit, and modern systems are all 64-bit anyway
70+
flags |= Features::MODE64BIT;
71+
72+
for flag in s {
73+
match flag {
74+
SgxFeatures::CET => {
75+
flags |= Features::CET;
76+
}
77+
SgxFeatures::Debug => {
78+
flags |= Features::DEBUG;
79+
}
80+
SgxFeatures::EInitKey => {
81+
flags |= Features::EINIT_KEY;
82+
}
83+
SgxFeatures::KSS => {
84+
flags |= Features::KSS;
85+
}
86+
SgxFeatures::ProvisioningKey => {
87+
flags |= Features::PROVISIONING_KEY;
88+
}
89+
}
90+
}
91+
92+
Ok(flags)
93+
}
94+
95+
fn from_misc_select<'de, D>(deserializer: D) -> Result<MiscSelect, D::Error>
96+
where
97+
D: Deserializer<'de>,
98+
{
99+
let s: Vec<SgxMiscSelect> = Deserialize::deserialize(deserializer)?;
100+
101+
let mut flags = MiscSelect::default();
102+
103+
for flag in s {
104+
match flag {
105+
SgxMiscSelect::EXINFO => {
106+
flags |= MiscSelect::EXINFO;
107+
}
108+
}
109+
}
110+
111+
Ok(flags)
112+
}
113+
114+
#[cfg(test)]
115+
mod tests {
116+
use super::*;
117+
use std::collections::HashSet;
118+
use validation_common::Digest;
119+
120+
#[test]
121+
fn empty_config() {
122+
assert!(toml::from_str::<Config>("").is_err());
123+
}
124+
125+
#[test]
126+
fn serde() {
127+
const SIGNER: &str =
128+
r#"signer = ["2eba0f494f428e799c22d6f12778aebea4dc8d991f9e63fd3cddd57ac6eb5dd9"]"#;
129+
130+
let signer: HashSet<_> = vec![Digest([
131+
0x2e, 0xba, 0x0f, 0x49, 0x4f, 0x42, 0x8e, 0x79, 0x9c, 0x22, 0xd6, 0xf1, 0x27, 0x78,
132+
0xae, 0xbe, 0xa4, 0xdc, 0x8d, 0x99, 0x1f, 0x9e, 0x63, 0xfd, 0x3c, 0xdd, 0xd5, 0x7a,
133+
0xc6, 0xeb, 0x5d, 0xd9,
134+
])]
135+
.into_iter()
136+
.collect();
137+
138+
let config: Config = toml::from_str(&format!(
139+
r#"
140+
{SIGNER}
141+
features = ["Debug"]
142+
misc_select = ["EXINFO"]
143+
"#,
144+
))
145+
.expect("Couldn't deserialize");
146+
147+
assert_eq!(config.measurements.signer, signer);
148+
assert_eq!(
149+
config.features.bits(),
150+
(Features::DEBUG | Features::INIT | Features::MODE64BIT).bits()
151+
);
152+
assert!(config.misc_select.contains(MiscSelect::EXINFO));
153+
}
154+
155+
#[test]
156+
fn too_short() {
157+
let config: Result<Config, toml::de::Error> = toml::from_str(
158+
r#"
159+
signer = ["41c179d5c0d5bc4915752ccf9bbd2baa574716832235ef5bb998fadcda1e46"]
160+
"#,
161+
);
162+
assert!(config.is_err());
163+
}
164+
}
4.85 KB
Binary file not shown.

0 commit comments

Comments
 (0)