-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Richard Zak <[email protected]>
- Loading branch information
Showing
9 changed files
with
280 additions
and
5 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// SPDX-FileCopyrightText: 2022 Profian Inc. <[email protected]> | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
use serde::de::Error; | ||
use serde::{Deserialize, Deserializer, Serialize}; | ||
|
||
#[derive(Clone, Deserialize, Debug, Default, Serialize)] | ||
struct Config { | ||
/// Values for `mrsigner` in the report body. | ||
/// This is the list of public keys which have signed the `enarx` binary. | ||
#[serde(default)] | ||
#[serde(deserialize_with = "from_hex")] | ||
enarx_signer: Option<Vec<Vec<u8>>>, | ||
|
||
/// Values allowed for `cpusvn`. | ||
cpu_svn: Option<Vec<u8>>, | ||
|
||
/// Value for `isv_svn`, do not allow versions below this. | ||
enclave_security_version: Option<u16>, | ||
} | ||
|
||
fn from_hex<'de, D>(deserializer: D) -> Result<Option<Vec<Vec<u8>>>, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let s: Vec<&str> = match Deserialize::deserialize(deserializer) { | ||
Ok(x) => x, | ||
Err(_) => return Ok(None), | ||
}; | ||
|
||
let mut outer_vec = Vec::new(); | ||
for hash_string in s { | ||
outer_vec.push(hex::decode(hash_string).map_err(|_| Error::custom("invalid hex"))?); | ||
} | ||
|
||
Ok(Some(outer_vec)) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::config::Config; | ||
|
||
#[test] | ||
fn test_empty_config() { | ||
let config_raw = r#" | ||
something_else = 1 | ||
"#; | ||
|
||
let config_obj: Config = toml::from_str(config_raw).expect("Couldn't deserialize"); | ||
assert!(config_obj.enarx_signer.is_none()); | ||
assert!(config_obj.enclave_security_version.is_none()); | ||
assert!(config_obj.cpu_svn.is_none()); | ||
} | ||
|
||
#[test] | ||
fn test_list_of_hashes() { | ||
let config_raw = r#" | ||
enarx_signer = ["1234567890", "00112233445566778899"] | ||
"#; | ||
|
||
let config_obj: Config = toml::from_str(config_raw).expect("Couldn't deserialize"); | ||
assert!(config_obj.enarx_signer.is_some()); | ||
assert_eq!(config_obj.enarx_signer.clone().unwrap().len(), 2); | ||
assert_eq!( | ||
config_obj.enarx_signer.clone().unwrap().first().unwrap(), | ||
&hex::decode("1234567890").unwrap() | ||
); | ||
assert_eq!( | ||
config_obj.enarx_signer.unwrap().get(1).unwrap(), | ||
&hex::decode("00112233445566778899").unwrap() | ||
); | ||
assert!(config_obj.cpu_svn.is_none()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
// SPDX-FileCopyrightText: 2022 Profian Inc. <[email protected]> | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
mod quote; | ||
pub mod config; | ||
pub mod quote; | ||
|
||
use cryptography::ext::*; | ||
use quote::traits::ParseBytes; | ||
|
@@ -29,7 +30,7 @@ impl Sgx { | |
pub const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.6.1.4.1.58270.1.2"); | ||
pub const ATT: bool = true; | ||
|
||
fn trusted<'c>(&'c self, chain: &'c [Certificate<'c>]) -> Result<&'c TbsCertificate<'c>> { | ||
pub fn trusted<'c>(&'c self, chain: &'c [Certificate<'c>]) -> Result<&'c TbsCertificate<'c>> { | ||
let mut signer = &self.0[0].tbs_certificate; | ||
for cert in self.0.iter().chain(chain.iter()) { | ||
signer = signer.verify_crt(cert)?; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use cryptography; | ||
use cryptography::x509::attr::Attribute; | ||
use cryptography::x509::request::{CertReq, ExtensionReq}; | ||
use cryptography::x509::Certificate; | ||
use der::Decode; | ||
use sgx_validation::quote::traits::ParseBytes; | ||
use sgx_validation::quote::Quote; | ||
use sgx_validation::Sgx; | ||
use std::env; | ||
use std::fs::File; | ||
use std::io::Read; | ||
use std::path::Path; | ||
|
||
fn main() { | ||
let args: Vec<String> = env::args().collect(); | ||
let fname = Path::new(args.get(1).expect("CSR file not specified")); | ||
let mut file = File::open(fname).expect("no such file"); | ||
let mut contents = Vec::new(); | ||
file.read_to_end(&mut contents) | ||
.expect("failed to read file"); | ||
|
||
let cr = CertReq::from_der(&contents).expect("failed to decode DER"); | ||
let cri = cr.info; | ||
#[allow(unused_variables)] | ||
for Attribute { oid, values } in cri.attributes.iter() { | ||
for any in values.iter() { | ||
let ereq: ExtensionReq<'_> = any.decode_into().unwrap(); | ||
for ext in Vec::from(ereq) { | ||
let (quote, bytes): (Quote<'_>, _) = | ||
ext.extn_value.parse().expect("failed to parse"); | ||
let chain = quote.chain().unwrap(); | ||
let chain = chain | ||
.iter() | ||
.map(|c| Certificate::from_der(c)) | ||
.collect::<Result<Vec<_>, _>>() | ||
.unwrap(); | ||
|
||
// Validate the report. | ||
let sgx = Sgx::default(); | ||
let pck = sgx.trusted(&chain).unwrap(); | ||
let report = quote.verify(pck).unwrap(); | ||
println!("{:?}", report); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// SPDX-FileCopyrightText: 2022 Profian Inc. <[email protected]> | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
use crate::{PlatformInfoFlags, PolicyFlags}; | ||
use flagset::FlagSet; | ||
use serde::de::Error; | ||
use serde::{Deserialize, Deserializer, Serialize}; | ||
|
||
#[derive(Clone, Deserialize, Debug, Default, Serialize)] | ||
struct Config { | ||
#[serde(default)] | ||
#[serde(deserialize_with = "from_policy_string")] | ||
policy_flags: Option<u8>, | ||
platform_info_flags: Option<Vec<PlatformInfoFlags>>, | ||
} | ||
|
||
fn from_policy_string<'de, D>(deserializer: D) -> Result<Option<u8>, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let s: &str = match Deserialize::deserialize(deserializer) { | ||
Ok(x) => x, | ||
Err(_) => return Ok(None), | ||
}; | ||
|
||
let mut flags = FlagSet::<PolicyFlags>::from(PolicyFlags::Reserved); | ||
|
||
eprintln!("String: {}", s); | ||
|
||
for flag in s.to_string().split("|") { | ||
match flag.trim() { | ||
"Debug" => { | ||
flags = flags | PolicyFlags::Debug; | ||
} | ||
"MigrateMA" => { | ||
flags = flags | PolicyFlags::MigrateMA; | ||
} | ||
"SingleSocket" => { | ||
flags = flags | PolicyFlags::SingleSocket; | ||
} | ||
"SMT" => { | ||
flags = flags | PolicyFlags::SMT; | ||
} | ||
_ => return Err(D::Error::custom(format!("unknown flag '{}'", flag))), | ||
} | ||
} | ||
|
||
Ok(Some(flags.bits())) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::config::Config; | ||
use crate::PolicyFlags; | ||
use flagset::FlagSet; | ||
|
||
#[test] | ||
fn test_empty_config() { | ||
let config_raw = r#" | ||
something_else = 1 | ||
"#; | ||
|
||
let config_obj: Config = toml::from_str(config_raw).expect("Couldn't deserialize"); | ||
assert!(config_obj.policy_flags.is_none()); | ||
assert!(config_obj.platform_info_flags.is_none()); | ||
} | ||
|
||
#[test] | ||
fn test_flags() { | ||
let config_raw = r#" | ||
policy_flags = "SingleSocket | Debug" | ||
"#; | ||
|
||
let config_obj: Config = toml::from_str(config_raw).expect("Couldn't deserialize"); | ||
assert!(config_obj.policy_flags.is_some()); | ||
assert!(config_obj.platform_info_flags.is_none()); | ||
|
||
let flags = FlagSet::<PolicyFlags>::new(config_obj.policy_flags.unwrap()).unwrap(); | ||
assert_eq!( | ||
flags, | ||
PolicyFlags::SingleSocket | PolicyFlags::Debug | PolicyFlags::Reserved | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
// SPDX-FileCopyrightText: 2022 Profian Inc. <[email protected]> | ||
// SPDX-License-Identifier: AGPL-3.0-only | ||
|
||
pub mod config; | ||
|
||
use cryptography::ext::*; | ||
|
||
use std::{fmt::Debug, mem::size_of}; | ||
|
@@ -16,6 +18,7 @@ use cryptography::x509::{PkiPath, TbsCertificate}; | |
use der::asn1::UIntRef; | ||
use der::{Decode, Encode, Sequence}; | ||
use flagset::{flags, FlagSet}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Clone, Debug, PartialEq, Eq, Sequence)] | ||
pub struct Evidence<'a> { | ||
|
@@ -26,6 +29,7 @@ pub struct Evidence<'a> { | |
} | ||
|
||
flags! { | ||
#[derive(Deserialize, Serialize)] | ||
pub enum PolicyFlags: u8 { | ||
/// Indicates if only one socket is permitted | ||
SingleSocket = 1 << 4, | ||
|
@@ -39,6 +43,7 @@ flags! { | |
SMT = 1 << 0, | ||
} | ||
|
||
#[derive(Deserialize, Serialize)] | ||
pub enum PlatformInfoFlags: u8 { | ||
TSME = 1 << 1, | ||
SMT = 1 << 0, | ||
|
@@ -69,7 +74,7 @@ pub struct PlatformInfo { | |
|
||
#[repr(C, packed)] | ||
#[derive(Copy, Clone, Debug)] | ||
struct Body { | ||
pub struct Body { | ||
/// The version of the attestation report, currently 2 | ||
pub version: u32, | ||
/// Guest Security Version Number (SVN) | ||
|
@@ -178,15 +183,15 @@ impl Es384 { | |
|
||
#[repr(C, packed)] | ||
#[derive(Copy, Clone)] | ||
union Signature { | ||
pub union Signature { | ||
bytes: [u8; 512], | ||
es384: Es384, | ||
} | ||
|
||
/// The attestation report from the trusted environment on an AMD system | ||
#[repr(C, packed)] | ||
#[derive(Copy, Clone)] | ||
struct Report { | ||
pub struct Report { | ||
pub body: Body, | ||
pub signature: Signature, | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use cryptography; | ||
use cryptography::x509::attr::Attribute; | ||
use cryptography::x509::request::{CertReq, ExtensionReq}; | ||
use der::Decode; | ||
use snp_validation; | ||
use snp_validation::Evidence; | ||
use snp_validation::Report; | ||
use std::env; | ||
use std::fs::File; | ||
use std::io::Read; | ||
use std::path::Path; | ||
|
||
fn main() { | ||
let args: Vec<String> = env::args().collect(); | ||
let fname = Path::new(args.get(1).expect("CSR file not specified")); | ||
let mut file = File::open(fname).expect("no such file"); | ||
let mut contents = Vec::new(); | ||
file.read_to_end(&mut contents) | ||
.expect("failed to read file"); | ||
|
||
let cr = CertReq::from_der(&contents).expect("failed to decode DER"); | ||
let cri = cr.info; | ||
#[allow(unused_variables)] | ||
for Attribute { oid, values } in cri.attributes.iter() { | ||
for any in values.iter() { | ||
let ereq: ExtensionReq<'_> = any.decode_into().unwrap(); | ||
for ext in Vec::from(ereq) { | ||
let evidence = Evidence::from_der(ext.extn_value).unwrap(); | ||
let array = evidence.report.try_into().unwrap(); | ||
let report = Report::cast(array); | ||
println!("{:?}", report); | ||
} | ||
} | ||
} | ||
} |