Skip to content

Commit

Permalink
Fixed testing to have comprehensive testing for the library
Browse files Browse the repository at this point in the history
Several bugs caught when trying to run cargo test with different
feature combinations. Fixed these bugs and made some slight tweaks to be
able to run comprehensive testing on the library.

- When running cargo test with dangerous_hw_tests enabled both has_sev
  and has_sev_guest tests were run leading to a failure. Fixed by
removing an unecessary or
- Renamed has_sev to host and renamed has_sev_guest to guest
- ID-BLOCK had to be put behind openssl only
- Changed snp_config test to hit only the IOCTL and not modify the
  config. This was done to avoid messing up system configs during
testing.
- Renamed the launch test to sev_launch test. This allows us to test
  that launch test individually.
- Added code to create a legacy SEV cert-chain locally. This allows us
  to test the SEV launch test without the need of an external tool.
- Cached Turin certificates to the SEV builtin certs and the SNP builtin
  certs.

Signed-off-by: DGonzalezVillal <Diego.GonzalezVillalobos@amd.com>
  • Loading branch information
DGonzalezVillal committed Nov 21, 2024
1 parent f892722 commit 7b0dee1
Show file tree
Hide file tree
Showing 18 changed files with 1,349 additions and 177 deletions.
1,115 changes: 1,047 additions & 68 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ doc = false
default = ["sev", "snp"]
openssl = ["dep:openssl", "dep:rdrand"]
hw_tests = []
dangerous_hw_tests = ["hw_tests"]
dangerous_hw_tests = ["hw_tests", "dep:reqwest", "dep:tokio"]
sev = []
snp = []
crypto_nossl = ["dep:p384", "dep:rsa", "dep:sha2", "dep:x509-cert"]
Expand Down Expand Up @@ -70,6 +70,8 @@ x509-cert = { version = "0.2.5", optional = true }
byteorder = "1.4.3"
base64 = "0.22.1"
rdrand = { version = "^0.8", optional = true }
reqwest = { version="0.11.10", features = ["blocking"], optional = true }
tokio = {version = "1.29.1", features =["rt-multi-thread"], optional = true }

[target.'cfg(target_os = "linux")'.dev-dependencies]
kvm-ioctls = ">=0.16"
Expand Down
12 changes: 6 additions & 6 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ fn main() {
use std::path::Path;

// Add in configurations to be checked within the code.
println!("cargo::rustc-check-cfg=cfg(has_sev)");
println!("cargo::rustc-check-cfg=cfg(has_sev_guest)");
println!("cargo::rustc-check-cfg=cfg(host)");
println!("cargo::rustc-check-cfg=cfg(guest)");

if cfg!(feature = "hw_tests") || Path::new("/dev/sev").exists() {
println!("cargo:rustc-cfg=has_sev");
if Path::new("/dev/sev").exists() {
println!("cargo:rustc-cfg=host");
}

if cfg!(feature = "hw_tests") || Path::new("/dev/sev-guest").exists() {
println!("cargo:rustc-cfg=has_sev_guest");
if Path::new("/dev/sev-guest").exists() {
println!("cargo:rustc-cfg=guest");
}
}
1 change: 1 addition & 0 deletions src/certs/sev/builtin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pub mod genoa;
pub mod milan;
pub mod naples;
pub mod rome;
pub mod turin;
Binary file added src/certs/sev/builtin/turin/ark.cert
Binary file not shown.
Binary file added src/certs/sev/builtin/turin/ask.cert
Binary file not shown.
14 changes: 14 additions & 0 deletions src/certs/sev/builtin/turin/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0

//! AMD's TURIN certificates.
//!
//! Certificate provenance: <https://developer.amd.com/wp-content/resources/ask_ark_turin.cert>
//!
//! For convenience, the certificate chain has been split into individual
//! certificates and are embedded here as byte slices.
/// The public Turin ARK certificate.
pub const ARK: &[u8] = include_bytes!("ark.cert");

/// The public Turin ASK certificate.
pub const ASK: &[u8] = include_bytes!("ask.cert");
3 changes: 3 additions & 0 deletions src/certs/snp/builtin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ pub mod genoa;
/// Milan generation.
pub mod milan;

/// Turin generation
pub mod turin;

use super::*;
37 changes: 37 additions & 0 deletions src/certs/snp/builtin/turin/ark.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
-----BEGIN CERTIFICATE-----
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
zpacMwFusA==
-----END CERTIFICATE-----
37 changes: 37 additions & 0 deletions src/certs/snp/builtin/turin/ask.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
-----BEGIN CERTIFICATE-----
MIIGiTCCBDigAwIBAgIDAwABMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC
BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS
BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg
Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp
Y2VzMRIwEAYDVQQDDAlBUkstVHVyaW4wHhcNMjMwNTE1MjAyNTIxWhcNNDgwNTE1
MjAyNTIxWjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS
BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j
ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJU0VWLVR1cmluMIICIjANBgkqhkiG
9w0BAQEFAAOCAg8AMIICCgKCAgEAnvg5Grv2Emd9lAhKdO64RXU3UESb6JTm0Hhz
evx1PyxinxYqJL329qTJM0XmdozLYb7rsHxgM5I2pU18M8gect2pN/YB2LQ1/bIq
37TPDbg7ym0MN6KkZ6aERxAX0voYtdDyNxjDAUjpRpCe1FccAev/Es2n/Fz1G1Tm
C2XepTQqaKpmt6mnDWSCHCVsQoY0gSibeaG6doM6OiNUCbKXaC7KHH5b/96BD1DJ
84M+JHqPClFhHqUJwzKF5Qxj4wgWAZzK8UPhiNGjrF6+TBdlFGdSzEqw1jOrCTHd
uYyLK+5OQ3OIw4S+vZeOVoxJajTIWdsqYP2DLc0HkL0qWOumEOrrc2/4DeETShB0
MyIpH05kSalyQN2eN5P6ptOB84hddCdbJPEepnD+FqQap1ukw3K8uBcgeBSAF23r
6UtT8Uc5h7MsWX3MoZiEHcSkDQQ8IedTk7CLjsK6S7b/lfKqfYiRhKgGkRvsEd/M
DNcumHZKIgzasJwgagzSggiUo9jXp3EWm84fqyxNXzSutPB7qD5P/ULAB+q9Qgvr
zC8XneaLP0MNrHhM80UejmsBTIktMvFoWVIelYDLdcoi0eMD5DRccfsgrYaY6h/+
/qf9tgg+mX09UJpuSPRF38oyqnNNFMl5v/tWLgUsChPU6NCQC17Qaqr8mu2ynyyu
HEs5JVUCAwEAAaOBozCBoDAdBgNVHQ4EFgQUbYJXt6v2sMgUALjxD0WvG9aq628w
HwYDVR0jBBgwFoAUZKBfceMMCmTYO3XlAVmeK+4GA0QwEgYDVR0TAQH/BAgwBgEB
/wIBADAOBgNVHQ8BAf8EBAMCAQQwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cHM6Ly9r
ZHNpbnRmLmFtZC5jb20vdmNlay92MS9UdXJpbi9jcmwwRgYJKoZIhvcNAQEKMDmg
DzANBglghkgBZQMEAgIFAKEcMBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgIFAKID
AgEwowMCAQEDggIBAAXWJ3DPahralt5kXLPMm9oKlFRqeU3HcS7kA+VBlBA1lQRU
hXkbXnTvW1GZcgdZvNCB/VlET61KbCzoFIhPIESVjjb/xWX2kg3X0HHmh1EtCDbH
aUFM5rq6l+S1h7qOauRZebvrwApDzAANvW0LTHRumfGm/kqh9NDtVCIWPUZ1VQIg
Gx1T3dwmgOK8ncT1J3W5xIyS0Xu3KC6w7oBlq8G2pPgTcCBJ4JBCTXCEXiAAGaTR
/TJIaSzoZFLhxYhCMjP8WQGToPGDK2i/lZhkcGHnJOQ+lgrXfpLGqBtLlS3QODyV
P0MomczG4dqw3THP3Y8Aq9c2KE7SylAKsS/bBKCqkj4OrABkDSkMQEz3BBoFD63a
D5ZG/Qiz+tmhnptyPVcweC9uJlSWYm25KiV4lT52uBjxatDZKQcrpdgcU8+ozzKU
8ICnZPOwfWeyuNMq/juyd/rzg5IePyyvt+13aJ5MlZBXZxJKoxCYIMKUwZigf0Xs
BteT8gw10/xk5smIFIB2ERtTQPMuTENgrPTUjOeiqmBg663c2dLVol+MDiT4ltqf
Em4Kl/cc4f+H6bEwhj1QKAN2ipRf+mP0NfzJb+6ZHNsOvyq/WByYpLXV9JJoiDW/
8RZwPU/Mn7IuQBauCy78G7FS0ta3q1et74faYBBgeJ6awEasa25CvmsmlU0R
-----END CERTIFICATE-----
40 changes: 40 additions & 0 deletions src/certs/snp/builtin/turin/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: Apache-2.0

use super::*;

/// The public Turin ARK certificate (PEM-encoded).
pub const ARK: &[u8] = include_bytes!("ark.pem");

/// The public Turin ASK certificate (PEM-encoded).
pub const ASK: &[u8] = include_bytes!("ask.pem");

/// Get the Turin ARK Certificate.
pub fn ark() -> Result<Certificate> {
Certificate::from_pem(ARK)
}

/// Get the Turin ASK Certificate.
pub fn ask() -> Result<Certificate> {
Certificate::from_pem(ASK)
}

mod tests {
#[test]
fn ark_self_signed() {
use super::*;

let ark = ark().unwrap();

(&ark, &ark).verify().unwrap();
}

#[test]
fn ark_signs_ask() {
use super::*;

let ark = ark().unwrap();
let ask = ask().unwrap();

(&ark, &ask).verify().unwrap();
}
}
20 changes: 20 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub mod vmsa;
/// Error module.
pub mod error;

#[cfg(all(feature = "sev", feature = "dangerous_hw_tests"))]
pub use util::cached_chain;
use util::{TypeLoad, TypeSave};

Expand Down Expand Up @@ -269,6 +270,10 @@ pub enum Generation {
/// Fourth generation EPYC (SEV, SEV-ES, SEV-SNP).
#[cfg(any(feature = "sev", feature = "snp"))]
Genoa,

/// Fifth generation EPYC (SEV, SEV-ES, SEV-SNP).
#[cfg(any(feature = "sev", feature = "snp"))]
Turin,
}

#[cfg(all(feature = "sev", feature = "openssl"))]
Expand All @@ -285,6 +290,8 @@ impl From<Generation> for CertSevCaChain {
Generation::Milan => (SevBuiltin::milan::ARK, SevBuiltin::milan::ASK),
#[cfg(any(feature = "sev", feature = "snp"))]
Generation::Genoa => (SevBuiltin::genoa::ARK, SevBuiltin::genoa::ASK),
#[cfg(any(feature = "sev", feature = "snp"))]
Generation::Turin => (SevBuiltin::turin::ARK, SevBuiltin::turin::ASK),
};

CertSevCaChain {
Expand All @@ -306,6 +313,10 @@ impl From<Generation> for CertSnpCaChain {
SnpBuiltin::genoa::ark().unwrap(),
SnpBuiltin::genoa::ask().unwrap(),
),
Generation::Turin => (
SnpBuiltin::turin::ark().unwrap(),
SnpBuiltin::turin::ask().unwrap(),
),
};

CertSnpCaChain { ark, ask }
Expand All @@ -323,6 +334,7 @@ impl TryFrom<&sev::Chain> for Generation {
let rome: CertSevCaChain = Generation::Rome.into();
let milan: CertSevCaChain = Generation::Milan.into();
let genoa: CertSevCaChain = Generation::Genoa.into();
let turin: CertSevCaChain = Generation::Turin.into();

Ok(if (&naples.ask, &schain.cek).verify().is_ok() {
Generation::Naples
Expand All @@ -332,6 +344,8 @@ impl TryFrom<&sev::Chain> for Generation {
Generation::Milan
} else if (&genoa.ask, &schain.cek).verify().is_ok() {
Generation::Genoa
} else if (&turin.ask, &schain.cek).verify().is_ok() {
Generation::Turin
} else {
return Err(());
})
Expand Down Expand Up @@ -362,6 +376,9 @@ impl TryFrom<String> for Generation {
#[cfg(any(feature = "sev", feature = "snp"))]
"siena" => Ok(Self::Genoa),

#[cfg(any(feature = "sev", feature = "snp"))]
"turin" => Ok(Self::Turin),

_ => Err(()),
}
}
Expand All @@ -383,6 +400,9 @@ impl Generation {

#[cfg(any(feature = "sev", feature = "snp"))]
Self::Genoa => "Genoa".to_string(),

#[cfg(any(feature = "sev", feature = "snp"))]
Self::Turin => "Turin".to_string(),
}
}
}
Expand Down
83 changes: 67 additions & 16 deletions src/util/cached_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,31 @@
//! An entire certificate chain can be created using the `sevctl`
//! utility.
#[cfg(feature = "sev")]
use crate::certs::sev::Chain;
#![cfg(all(feature = "sev", feature = "dangerous_hw_tests"))]

#[cfg(feature = "openssl")]
use crate::{
certs::sev::{ca::Chain as CaChain, Chain as FullChain},
firmware::host::Firmware,
sev::Certificate,
Generation,
};

#[cfg(feature = "openssl")]
use reqwest::{
blocking::{get, Response},
StatusCode,
};

use std::{
env,
path::{Path, PathBuf},
};

#[cfg(feature = "sev")]
use std::{
fs::File,
io::{ErrorKind, Result},
};
#[cfg(feature = "openssl")]
use std::io::Cursor;

#[cfg(feature = "sev")]
#[cfg(feature = "openssl")]
use codicon::Decoder;

fn append_rest<P: AsRef<Path>>(path: P) -> PathBuf {
Expand Down Expand Up @@ -67,13 +77,54 @@ pub fn path() -> Vec<PathBuf> {
.collect()
}

/// Searches for and decodes an SEV certificate chain.
#[cfg(feature = "sev")]
pub fn get() -> Result<Chain> {
let not_found: std::io::Error = ErrorKind::NotFound.into();
/// Remove any certificates that may have been chached to reset
/// testing for SEV APIS.
pub fn rm_cached_chain() {
let paths = path();
if let Some(path) = paths.first() {
if path.exists() {
std::fs::remove_file(path).unwrap();
}
}
}

/// Request CEK certificate from AMD KDS and generate a full chain.
#[cfg(all(feature = "sev", feature = "openssl"))]
pub fn get_chain() -> FullChain {
use std::convert::TryFrom;

let mut firmware = Firmware::open().unwrap();

let paths: Vec<_> = path().into_iter().filter(|p| p.exists()).collect();
let file_name = paths.first().ok_or(not_found)?;
let mut file = File::open(file_name)?;
Chain::decode(&mut file, ())
const CEK_SVC: &str = "https://kdsintf.amd.com/cek/id";

let mut sev_chain = firmware.pdh_cert_export().unwrap();

let id = firmware.get_identifier().unwrap();

let url = format!("{}/{}", CEK_SVC, id);

// VCEK in DER format
let vcek_rsp: Response = get(url).expect("Failed to get CEK certificate");

let cek_resp_bytes = match vcek_rsp.status() {
StatusCode::OK => {
let vcek_rsp_bytes: Vec<u8> = vcek_rsp.bytes().unwrap().to_vec();
vcek_rsp_bytes
}
_ => panic!("Cek request returned an error"),
};

// Create a Cursor around the byte vector
let cursor = Cursor::new(cek_resp_bytes);

sev_chain.cek = Certificate::decode(cursor, ()).expect("Failed to decode CEK cert");

let ca_chain: CaChain = Generation::try_from(&sev_chain)
.expect("Failed to generate SEV CA chain")
.into();

FullChain {
ca: ca_chain,
sev: sev_chain,
}
}
Loading

0 comments on commit 7b0dee1

Please sign in to comment.