Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package snphost for openSUSE:Factory checked in at 2025-05-31 19:16:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/snphost (Old) and /work/SRC/openSUSE:Factory/.snphost.new.16005 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "snphost" Sat May 31 19:16:49 2025 rev:5 rq:1281534 version:0.6.0 Changes: -------- --- /work/SRC/openSUSE:Factory/snphost/snphost.changes 2024-10-07 21:49:39.951846227 +0200 +++ /work/SRC/openSUSE:Factory/.snphost.new.16005/snphost.changes 2025-05-31 19:17:44.704935810 +0200 @@ -1,0 +2,15 @@ +Fri May 30 16:08:31 UTC 2025 - Caleb Crane (caleb.cr...@suse.com) + +- Update to version 0.6.0: + * Update to 0.6.0 + * config: Add settable FMC for Turin generation processors + * Update sev library to 6.0.0 + * snphost: add a new option arg "url" to fetch vcek command + * deps/sev: Point to upstream git commit + * ok: Move SEV firmware version check + * ok: Modify various test messages + * ok: Move SNP platform tests + * ok: Add test for ALIAS_CHECK_COMPLETE + * ok: Update RMP_INIT check to account for other bitflags + +------------------------------------------------------------------- Old: ---- snphost-0.5.0.obscpio snphost-0.5.0.tar.gz New: ---- snphost-0.6.0.obscpio snphost-0.6.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ snphost.spec ++++++ --- /var/tmp/diff_new_pack.wz4arJ/_old 2025-05-31 19:17:46.877025574 +0200 +++ /var/tmp/diff_new_pack.wz4arJ/_new 2025-05-31 19:17:46.881025740 +0200 @@ -1,7 +1,7 @@ # # spec file for package snphost # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # Copyright (C) 2023 VirTEE # # All modifications and additions to the file contributed by third parties @@ -18,7 +18,7 @@ Name: snphost -Version: 0.5.0 +Version: 0.6.0 Release: 0 Summary: A Rust command-line tool for interacting with the AMD Secure Processor License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.wz4arJ/_old 2025-05-31 19:17:46.985030038 +0200 +++ /var/tmp/diff_new_pack.wz4arJ/_new 2025-05-31 19:17:47.009031030 +0200 @@ -1,9 +1,9 @@ <services> <service mode="disabled" name="obs_scm"> - <param name="url">https://github.com/virtee/snphost.git</param> + <param name="url">https://gitlab.suse.de/virtualization/snphost.git</param> <param name="versionformat">@PARENT_TAG@</param> <param name="scm">git</param> - <param name="revision">v0.5.0</param> + <param name="revision">v0.6.0</param> <param name="match-tag">*</param> <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param> <param name="versionrewrite-replacement">\1</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.wz4arJ/_old 2025-05-31 19:17:47.097034667 +0200 +++ /var/tmp/diff_new_pack.wz4arJ/_new 2025-05-31 19:17:47.117035493 +0200 @@ -1,6 +1,8 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/virtee/snphost.git</param> - <param name="changesrevision">a7ba00220202240cd01819ef1fe81d57ebbb9f8b</param></service></servicedata> + <param name="changesrevision">a7ba00220202240cd01819ef1fe81d57ebbb9f8b</param></service><service name="tar_scm"> + <param name="url">https://gitlab.suse.de/virtualization/snphost.git</param> + <param name="changesrevision">545bdf882ec5a5f054e0b75d0b382040bd8efc39</param></service></servicedata> (No newline at EOF) ++++++ snphost-0.5.0.obscpio -> snphost-0.6.0.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/.github/workflows/lint.yml new/snphost-0.6.0/.github/workflows/lint.yml --- old/snphost-0.5.0/.github/workflows/lint.yml 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/.github/workflows/lint.yml 2025-04-10 17:35:21.000000000 +0200 @@ -26,7 +26,7 @@ - uses: actions-rs/toolchain@v1 with: components: clippy - toolchain: 1.80 + toolchain: 1.80.0 profile: minimal override: true - uses: actions-rs/cargo@v1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/0001-Update-to-0.6.0.patch new/snphost-0.6.0/0001-Update-to-0.6.0.patch --- old/snphost-0.5.0/0001-Update-to-0.6.0.patch 1970-01-01 01:00:00.000000000 +0100 +++ new/snphost-0.6.0/0001-Update-to-0.6.0.patch 2025-04-10 17:35:21.000000000 +0200 @@ -0,0 +1,576 @@ +From dc6051450919d0789e0a15069b143dc50c9e0bf8 Mon Sep 17 00:00:00 2001 +From: Caleb Crane <ccr...@suse.de> +Date: Thu, 29 May 2025 10:09:41 -0400 +Subject: [PATCH] Update to 0.6.0 + +Signed-off-by: Tyler Fanelli <tfane...@redhat.com> +(cherry picked from commit 545bdf882ec5a5f054e0b75d0b382040bd8efc39) +Signed-off-by: Caleb Crane <ccr...@suse.de> +--- + .github/workflows/lint.yml | 2 +- + Cargo.lock | 14 ++-- + Cargo.toml | 6 +- + docs/snphost.1.adoc | 7 +- + src/cert/fetch/ca.rs | 7 +- + src/cert/fetch/vcek.rs | 9 ++- + src/config.rs | 21 +++++- + src/ok.rs | 148 ++++++++++++++++++++++--------------- + src/show.rs | 2 +- + 9 files changed, 136 insertions(+), 80 deletions(-) + +diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml +index 5cf4bd4..36ce92c 100644 +--- a/.github/workflows/lint.yml ++++ b/.github/workflows/lint.yml +@@ -26,7 +26,7 @@ jobs: + - uses: actions-rs/toolchain@v1 + with: + components: clippy +- toolchain: 1.80 ++ toolchain: 1.80.0 + profile: minimal + override: true + - uses: actions-rs/cargo@v1 +diff --git a/Cargo.lock b/Cargo.lock +index b5f0a54..0a099a2 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -313,9 +313,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + + [[package]] + name = "libc" +-version = "0.2.154" ++version = "0.2.162" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" ++checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + + [[package]] + name = "libredox" +@@ -544,9 +544,9 @@ dependencies = [ + + [[package]] + name = "sev" +-version = "4.0.0" ++version = "6.0.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "a97bd0b2e2d937951add10c8512a2dacc6ad29b39e5c5f26565a3e443329857d" ++checksum = "20ac277517d8fffdf3c41096323ed705b3a7c75e397129c072fb448339839d0f" + dependencies = [ + "base64", + "bincode", +@@ -570,7 +570,7 @@ dependencies = [ + + [[package]] + name = "snphost" +-version = "0.5.0" ++version = "0.6.0" + dependencies = [ + "anyhow", + "clap", +@@ -658,9 +658,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + + [[package]] + name = "uuid" +-version = "1.8.0" ++version = "1.11.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" ++checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" + dependencies = [ + "serde", + ] +diff --git a/Cargo.toml b/Cargo.toml +index f09f99c..10f0876 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "snphost" +-version = "0.5.0" ++version = "0.6.0" + authors = ["The VirTEE Project Developers"] + edition = "2021" + license = "Apache-2.0" +@@ -25,10 +25,10 @@ is-it-maintained-open-issues = { repository = "virtee/snphost" } + + [dependencies] + anyhow = "1.0.83" +-sev = { version = "4.0.0", features = ['openssl']} ++sev = { version = "6.0.0", features = ['openssl']} + env_logger = "0.10.1" + clap = { version = "4.5", features = [ "derive" ] } + colorful = "0.2.2" +-libc = "0.2.154" ++libc = "0.2.161" + curl = "0.4" + msru = "0.2.0" +diff --git a/docs/snphost.1.adoc b/docs/snphost.1.adoc +index 560dc0b..c933f2e 100644 +--- a/docs/snphost.1.adoc ++++ b/docs/snphost.1.adoc +@@ -102,6 +102,7 @@ COMMANDS + + For example, if the user would like MASK KEY to be enabled and CHIP ID disabled, + then the they would pass in a 2. ++ FMC: Current FMC firmware version + + options: + -h, --help Show a help message. +@@ -154,12 +155,14 @@ COMMANDS + -h, --help Show a help message + + *snphost fetch vcek*:: +- usage: snphost fetch vcek [ der, pem ] DIR-PATH ++ usage: snphost fetch vcek [ der, pem ] DIR-PATH [url] + + This command fetches the host system's versioned chip endorsement + key (VCEK) and writes the encoded certificate to the directory at path + DIR-PATH. Users must specify which format they would like the +- certificate to be encoded in (DER or PEM). ++ certificate to be encoded in (DER or PEM). The URL of the VCEK can be ++ explicitly set. If not explicitly set, the URL will be generated based ++ on firmware data. + + options: + -h, --help Show a help message +diff --git a/src/cert/fetch/ca.rs b/src/cert/fetch/ca.rs +index 694cb54..3308e16 100644 +--- a/src/cert/fetch/ca.rs ++++ b/src/cert/fetch/ca.rs +@@ -3,7 +3,7 @@ + use super::*; + use anyhow::{Context, Result}; + use curl::easy::Easy; +-use sev::certs::snp::{ca::Chain, Certificate}; ++use sev::certs::snp::ca::Chain; + use std::{ + fs::{create_dir_all, OpenOptions}, + io::Write, +@@ -76,10 +76,7 @@ pub fn fetch(url: &str) -> Result<Chain> { + transfer.perform()?; + drop(transfer); + +- Ok(Chain { +- ask: Certificate::from_pem(&buf[..2325])?, +- ark: Certificate::from_pem(&buf[2325..])?, +- }) ++ Ok(Chain::from_pem_bytes(&buf)?) + } + + fn ca_chain_url() -> Result<String> { +diff --git a/src/cert/fetch/vcek.rs b/src/cert/fetch/vcek.rs +index be74c43..5aeec21 100644 +--- a/src/cert/fetch/vcek.rs ++++ b/src/cert/fetch/vcek.rs +@@ -23,10 +23,17 @@ pub struct Vcek { + /// The path of a directory to store the encoded VCEK in + #[arg(value_name = "path", required = true)] + path: PathBuf, ++ ++ /// The URL of the VCEK. If not explicitly set, the URL will be generated based on firmware data ++ #[arg(value_name = "url", required = false)] ++ url: Option<String>, + } + + pub fn cmd(vcek: Vcek) -> Result<()> { +- let url = vcek_url()?; ++ let url = match vcek.url { ++ Some(url) => url, ++ None => vcek_url()?, ++ }; + let cert = fetch(&url).context(format!("unable to fetch VCEK from {}", url))?; + + let (vcek_name, vcek_bytes) = match vcek.encoding_fmt { +diff --git a/src/config.rs b/src/config.rs +index b4b1c1d..4a5f9c3 100644 +--- a/src/config.rs ++++ b/src/config.rs +@@ -1,6 +1,8 @@ + // SPDX-License-Identifier: Apache-2.0 + + use super::*; ++use crate::processor::ProcessorGeneration; ++use anyhow::anyhow; + + // Different config commands + #[derive(Subcommand)] +@@ -45,11 +47,28 @@ mod set { + /// Change mask chip bit field (Unsigned 32-bit Integer) values by providing decimal representation of desired change (0-3). Bit[0]: CHIP_ID, Bit[1]: CHIP_KEY. Both are disabled by default + #[arg(value_name = "mask-chip", required = true)] + mask_chip: u32, ++ ++ /// FMC firmware version. ++ #[arg(value_name = "fmc", required = false)] ++ fmc: Option<u8>, + } + + pub fn set_config(args: Args) -> Result<()> { ++ let fmc = match ProcessorGeneration::current()? { ++ ProcessorGeneration::Turin => { ++ let Some(fmc) = args.fmc else { ++ return Err(anyhow!( ++ "Turin generation processor requires FMC version when setting TCB" ++ )); ++ }; ++ ++ Some(fmc) ++ } ++ _ => None, ++ }; ++ + // Create Tcb with provided values +- let tcb = TcbVersion::new(args.bootloader, args.tee, args.snp_fw, args.microcode); ++ let tcb = TcbVersion::new(fmc, args.bootloader, args.tee, args.snp_fw, args.microcode); + + // Create Mask Chip with provided value + let mask_chip = MaskId(args.mask_chip); +diff --git a/src/ok.rs b/src/ok.rs +index 209404c..0fc1fc9 100644 +--- a/src/ok.rs ++++ b/src/ok.rs +@@ -63,21 +63,23 @@ impl fmt::Display for TestState { + enum SnpStatusTest { + Tcb, + Rmp, ++ AliasCheck, + Snp, + } + + enum SevStatusTests { + Sev, + Firmware, +- Seves, ++ SevEs, + } + + impl fmt::Display for SnpStatusTest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + SnpStatusTest::Tcb => "Comparing TCB values", +- SnpStatusTest::Rmp => "RMP INIT", +- SnpStatusTest::Snp => "SNP INIT", ++ SnpStatusTest::Rmp => "RMP table initialized", ++ SnpStatusTest::AliasCheck => "Alias check", ++ SnpStatusTest::Snp => "SNP initialized", + }; + write!(f, "{}", s) + } +@@ -86,9 +88,9 @@ impl fmt::Display for SnpStatusTest { + impl fmt::Display for SevStatusTests { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { +- SevStatusTests::Sev => "SEV INIT", +- SevStatusTests::Firmware => "SEV Firmware Version", +- SevStatusTests::Seves => "SEV-ES INIT", ++ SevStatusTests::Sev => "SEV initialized", ++ SevStatusTests::Firmware => "SEV firmware version", ++ SevStatusTests::SevEs => "SEV-ES initialized", + }; + write!(f, "{}", s) + } +@@ -196,6 +198,12 @@ fn collect_tests() -> Vec<Test> { + } + }), + sub: vec![ ++ Test { ++ name: "SEV Firmware Version", ++ gen_mask: SNP_MASK, ++ run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), ++ sub: vec![], ++ }, + Test { + name: "Encrypted State (SEV-ES)", + gen_mask: ES_MASK, +@@ -215,14 +223,14 @@ fn collect_tests() -> Vec<Test> { + } + }), + sub: vec![Test { +- name: "SEV-ES INIT", ++ name: "SEV-ES initialized", + gen_mask: ES_MASK, +- run: Box::new(|| sev_ioctl(SevStatusTests::Seves)), ++ run: Box::new(|| sev_ioctl(SevStatusTests::SevEs)), + sub: vec![], + }], + }, + Test { +- name: "SEV INIT", ++ name: "SEV initialized", + gen_mask: SNP_MASK, + run: Box::new(|| sev_ioctl(SevStatusTests::Sev)), + sub: vec![], +@@ -287,16 +295,29 @@ fn collect_tests() -> Vec<Test> { + sub: vec![], + }, + Test { +- name: "SEV Firmware Version", +- gen_mask: SNP_MASK, +- run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), +- sub: vec![], +- }, +- Test { +- name: "SNP INIT", ++ name: "SNP initialized", + gen_mask: SNP_MASK, + run: Box::new(|| snp_ioctl(SnpStatusTest::Snp)), +- sub: vec![], ++ sub: vec![ ++ Test { ++ name: "Read RMP tables", ++ gen_mask: SNP_MASK, ++ run: Box::new(get_rmp_address), ++ sub: vec![], ++ }, ++ Test { ++ name: "RMP table initialized", ++ gen_mask: SNP_MASK, ++ run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), ++ sub: vec![], ++ }, ++ Test { ++ name: "Alias check", ++ gen_mask: SNP_MASK, ++ run: Box::new(|| snp_ioctl(SnpStatusTest::AliasCheck)), ++ sub: vec![], ++ }, ++ ], + }, + ], + }, +@@ -443,18 +464,6 @@ fn collect_tests() -> Vec<Test> { + run: Box::new(memlock_rlimit), + sub: vec![], + }, +- Test { +- name: "Read RMP tables", +- gen_mask: SNP_MASK, +- run: Box::new(get_rmp_address), +- sub: vec![], +- }, +- Test { +- name: "RMP INIT", +- gen_mask: SNP_MASK, +- run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), +- sub: vec![], +- }, + Test { + name: "Compare TCB values", + gen_mask: SNP_MASK, +@@ -475,7 +484,7 @@ pub fn cmd(quiet: bool) -> Result<()> { + Ok(()) + } else { + Err(anyhow::anyhow!( +- "One or more tests in sevctl-ok reported a failure" ++ "One or more tests in snphost ok reported a failure" + )) + } + } +@@ -569,27 +578,27 @@ fn emit_skip(tests: &[Test], level: usize, quiet: bool) { + + fn dev_sev_r() -> TestResult { + let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().read(true)) { +- Ok(_) => (TestState::Pass, "/dev/sev readable".to_string()), +- Err(e) => (TestState::Fail, format!("/dev/sev not readable: {}", e)), ++ Ok(_) => (TestState::Pass, None), ++ Err(e) => (TestState::Fail, Some(format!("Not readable: {}", e))), + }; + + TestResult { +- name: "Reading /dev/sev".to_string(), ++ name: "/dev/sev readable".to_string(), + stat, +- mesg: Some(mesg), ++ mesg, + } + } + + fn dev_sev_w() -> TestResult { + let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().write(true)) { +- Ok(_) => (TestState::Pass, "/dev/sev writable".to_string()), +- Err(e) => (TestState::Fail, format!("/dev/sev not writable: {}", e)), ++ Ok(_) => (TestState::Pass, None), ++ Err(e) => (TestState::Fail, Some(format!("Not writable: {}", e))), + }; + + TestResult { +- name: "Writing /dev/sev".to_string(), ++ name: "/dev/sev writable".to_string(), + stat, +- mesg: Some(mesg), ++ mesg, + } + } + +@@ -639,23 +648,27 @@ fn sev_enabled_in_kvm(gen: SevGeneration) -> TestResult { + match std::fs::read_to_string(path_loc) { + Ok(result) => { + if result.trim() == "1" || result.trim() == "Y" { +- (TestState::Pass, "enabled".to_string()) ++ (TestState::Pass, None) + } else { + ( + TestState::Fail, +- format!("Error - contents read from {}: {}", path_loc, result.trim()), ++ Some(format!( ++ "Error - contents read from {}: {}", ++ path_loc, ++ result.trim() ++ )), + ) + } + } + Err(e) => ( + TestState::Fail, +- format!("Error - (unable to read {}): {}", path_loc, e,), ++ Some(format!("Error - (unable to read {}): {}", path_loc, e,)), + ), + } + } else { + ( + TestState::Fail, +- format!("Error - {} does not exist", path_loc), ++ Some(format!("Error - {} does not exist", path_loc)), + ) + }; + +@@ -667,7 +680,7 @@ fn sev_enabled_in_kvm(gen: SevGeneration) -> TestResult { + } + .to_string(), + stat, +- mesg: Some(mesg), ++ mesg, + } + } + +@@ -779,7 +792,7 @@ fn get_rmp_address() -> TestResult { + TestResult { + name: "RMP table addresses".to_string(), + stat: TestState::Pass, +- mesg: format!("Addresses: {} - {}", rmp_base, rmp_end).into(), ++ mesg: format!("0x{:x} - 0x{:x}", rmp_base, rmp_end).into(), + } + } + } +@@ -815,17 +828,34 @@ fn snp_ioctl(test: SnpStatusTest) -> TestResult { + } + } + SnpStatusTest::Rmp => { +- if status.is_rmp_init == 1 { ++ if status.is_rmp_init.is_rmp_init() { + TestResult { + name: format!("{}", SnpStatusTest::Rmp), + stat: TestState::Pass, +- mesg: Some("RMP is INIT".to_string()), ++ mesg: None, + } + } else { + TestResult { + name: format!("{}", SnpStatusTest::Rmp), + stat: TestState::Fail, +- mesg: Some("RMP is UNINIT".to_string()), ++ mesg: None, ++ } ++ } ++ } ++ SnpStatusTest::AliasCheck => { ++ if status.is_rmp_init.alias_check_complete() { ++ TestResult { ++ name: format!("{}", SnpStatusTest::AliasCheck), ++ stat: TestState::Pass, ++ mesg: Some( ++ "Completed since last system update, no aliasing addresses".to_string(), ++ ), ++ } ++ } else { ++ TestResult { ++ name: format!("{}", SnpStatusTest::AliasCheck), ++ stat: TestState::Fail, ++ mesg: None, + } + } + } +@@ -834,13 +864,13 @@ fn snp_ioctl(test: SnpStatusTest) -> TestResult { + TestResult { + name: format!("{}", SnpStatusTest::Snp), + stat: TestState::Pass, +- mesg: Some("SNP is INIT".to_string()), ++ mesg: None, + } + } else { + TestResult { + name: format!("{}", SnpStatusTest::Snp), + stat: TestState::Fail, +- mesg: Some("SNP is UNINIT".to_string()), ++ mesg: None, + } + } + } +@@ -864,19 +894,19 @@ fn sev_ioctl(test: SevStatusTests) -> TestResult { + TestResult { + name: format!("{}", SevStatusTests::Sev), + stat: TestState::Pass, +- mesg: Some("SEV is INIT and currently running a guest".to_string()), ++ mesg: Some("Initialized, currently running a guest".to_string()), + } + } else if status.state == State::Initialized { + TestResult { + name: format!("{}", SevStatusTests::Sev), + stat: TestState::Pass, +- mesg: Some("SEV is INIT, but not currently running a guest".to_string()), ++ mesg: Some("Initialized, no guests running".to_string()), + } + } else { + TestResult { + name: format!("{}", SevStatusTests::Sev), + stat: TestState::Fail, +- mesg: Some("SEV is UNINIT".to_string()), ++ mesg: Some("Uninitialized".to_string()), + } + } + } +@@ -906,21 +936,21 @@ fn sev_ioctl(test: SevStatusTests) -> TestResult { + TestResult { + name: format!("{}", SevStatusTests::Firmware), + stat: TestState::Pass, +- mesg: format!("Sev firmware version: {}", status.build.version).into(), ++ mesg: format!("{}", status.build.version).into(), + } + } + } + +- SevStatusTests::Seves => { +- let (res, mesg) = match status.flags.bits() >> 8 & 1 { +- 1 => (TestState::Pass, "Enabled"), +- 0 => (TestState::Fail, "Disabled"), ++ SevStatusTests::SevEs => { ++ let res = match status.flags.bits() >> 8 & 1 { ++ 1 => TestState::Pass, ++ 0 => TestState::Fail, + _ => unreachable!(), + }; + TestResult { +- name: format!("{}", SevStatusTests::Seves), ++ name: format!("{}", SevStatusTests::SevEs), + stat: res, +- mesg: Some(mesg.to_string()), ++ mesg: None, + } + } + } +diff --git a/src/show.rs b/src/show.rs +index bb69208..1825fef 100644 +--- a/src/show.rs ++++ b/src/show.rs +@@ -44,7 +44,7 @@ pub fn cmd(show: Show) -> Result<()> { + + println!("{}", url); + } +- Show::Version => println!("{}", status.version), ++ Show::Version => println!("{}.{}", status.version.0, status.version.1), + } + + Ok(()) +-- +2.49.0 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/Cargo.lock new/snphost-0.6.0/Cargo.lock --- old/snphost-0.5.0/Cargo.lock 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/Cargo.lock 2025-04-10 17:35:21.000000000 +0200 @@ -313,9 +313,9 @@ [[package]] name = "libc" -version = "0.2.154" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -544,9 +544,9 @@ [[package]] name = "sev" -version = "4.0.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97bd0b2e2d937951add10c8512a2dacc6ad29b39e5c5f26565a3e443329857d" +checksum = "20ac277517d8fffdf3c41096323ed705b3a7c75e397129c072fb448339839d0f" dependencies = [ "base64", "bincode", @@ -570,7 +570,7 @@ [[package]] name = "snphost" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "clap", @@ -658,9 +658,9 @@ [[package]] name = "uuid" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "serde", ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/Cargo.toml new/snphost-0.6.0/Cargo.toml --- old/snphost-0.5.0/Cargo.toml 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/Cargo.toml 2025-04-10 17:35:21.000000000 +0200 @@ -1,6 +1,6 @@ [package] name = "snphost" -version = "0.5.0" +version = "0.6.0" authors = ["The VirTEE Project Developers"] edition = "2021" license = "Apache-2.0" @@ -25,10 +25,10 @@ [dependencies] anyhow = "1.0.83" -sev = { version = "4.0.0", features = ['openssl']} +sev = { version = "6.0.0", features = ['openssl']} env_logger = "0.10.1" clap = { version = "4.5", features = [ "derive" ] } colorful = "0.2.2" -libc = "0.2.154" +libc = "0.2.161" curl = "0.4" msru = "0.2.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/docs/snphost.1.adoc new/snphost-0.6.0/docs/snphost.1.adoc --- old/snphost-0.5.0/docs/snphost.1.adoc 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/docs/snphost.1.adoc 2025-04-10 17:35:21.000000000 +0200 @@ -102,6 +102,7 @@ For example, if the user would like MASK KEY to be enabled and CHIP ID disabled, then the they would pass in a 2. + FMC: Current FMC firmware version options: -h, --help Show a help message. @@ -154,12 +155,14 @@ -h, --help Show a help message *snphost fetch vcek*:: - usage: snphost fetch vcek [ der, pem ] DIR-PATH + usage: snphost fetch vcek [ der, pem ] DIR-PATH [url] This command fetches the host system's versioned chip endorsement key (VCEK) and writes the encoded certificate to the directory at path DIR-PATH. Users must specify which format they would like the - certificate to be encoded in (DER or PEM). + certificate to be encoded in (DER or PEM). The URL of the VCEK can be + explicitly set. If not explicitly set, the URL will be generated based + on firmware data. options: -h, --help Show a help message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/cert/fetch/ca.rs new/snphost-0.6.0/src/cert/fetch/ca.rs --- old/snphost-0.5.0/src/cert/fetch/ca.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/cert/fetch/ca.rs 2025-04-10 17:35:21.000000000 +0200 @@ -3,7 +3,7 @@ use super::*; use anyhow::{Context, Result}; use curl::easy::Easy; -use sev::certs::snp::{ca::Chain, Certificate}; +use sev::certs::snp::ca::Chain; use std::{ fs::{create_dir_all, OpenOptions}, io::Write, @@ -76,10 +76,7 @@ transfer.perform()?; drop(transfer); - Ok(Chain { - ask: Certificate::from_pem(&buf[..2325])?, - ark: Certificate::from_pem(&buf[2325..])?, - }) + Ok(Chain::from_pem_bytes(&buf)?) } fn ca_chain_url() -> Result<String> { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/cert/fetch/vcek.rs new/snphost-0.6.0/src/cert/fetch/vcek.rs --- old/snphost-0.5.0/src/cert/fetch/vcek.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/cert/fetch/vcek.rs 2025-04-10 17:35:21.000000000 +0200 @@ -23,10 +23,17 @@ /// The path of a directory to store the encoded VCEK in #[arg(value_name = "path", required = true)] path: PathBuf, + + /// The URL of the VCEK. If not explicitly set, the URL will be generated based on firmware data + #[arg(value_name = "url", required = false)] + url: Option<String>, } pub fn cmd(vcek: Vcek) -> Result<()> { - let url = vcek_url()?; + let url = match vcek.url { + Some(url) => url, + None => vcek_url()?, + }; let cert = fetch(&url).context(format!("unable to fetch VCEK from {}", url))?; let (vcek_name, vcek_bytes) = match vcek.encoding_fmt { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/config.rs new/snphost-0.6.0/src/config.rs --- old/snphost-0.5.0/src/config.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/config.rs 2025-04-10 17:35:21.000000000 +0200 @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 use super::*; +use crate::processor::ProcessorGeneration; +use anyhow::anyhow; // Different config commands #[derive(Subcommand)] @@ -45,11 +47,28 @@ /// Change mask chip bit field (Unsigned 32-bit Integer) values by providing decimal representation of desired change (0-3). Bit[0]: CHIP_ID, Bit[1]: CHIP_KEY. Both are disabled by default #[arg(value_name = "mask-chip", required = true)] mask_chip: u32, + + /// FMC firmware version. + #[arg(value_name = "fmc", required = false)] + fmc: Option<u8>, } pub fn set_config(args: Args) -> Result<()> { + let fmc = match ProcessorGeneration::current()? { + ProcessorGeneration::Turin => { + let Some(fmc) = args.fmc else { + return Err(anyhow!( + "Turin generation processor requires FMC version when setting TCB" + )); + }; + + Some(fmc) + } + _ => None, + }; + // Create Tcb with provided values - let tcb = TcbVersion::new(args.bootloader, args.tee, args.snp_fw, args.microcode); + let tcb = TcbVersion::new(fmc, args.bootloader, args.tee, args.snp_fw, args.microcode); // Create Mask Chip with provided value let mask_chip = MaskId(args.mask_chip); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/ok.rs new/snphost-0.6.0/src/ok.rs --- old/snphost-0.5.0/src/ok.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/ok.rs 2025-04-10 17:35:21.000000000 +0200 @@ -63,21 +63,23 @@ enum SnpStatusTest { Tcb, Rmp, + AliasCheck, Snp, } enum SevStatusTests { Sev, Firmware, - Seves, + SevEs, } impl fmt::Display for SnpStatusTest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { SnpStatusTest::Tcb => "Comparing TCB values", - SnpStatusTest::Rmp => "RMP INIT", - SnpStatusTest::Snp => "SNP INIT", + SnpStatusTest::Rmp => "RMP table initialized", + SnpStatusTest::AliasCheck => "Alias check", + SnpStatusTest::Snp => "SNP initialized", }; write!(f, "{}", s) } @@ -86,9 +88,9 @@ impl fmt::Display for SevStatusTests { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { - SevStatusTests::Sev => "SEV INIT", - SevStatusTests::Firmware => "SEV Firmware Version", - SevStatusTests::Seves => "SEV-ES INIT", + SevStatusTests::Sev => "SEV initialized", + SevStatusTests::Firmware => "SEV firmware version", + SevStatusTests::SevEs => "SEV-ES initialized", }; write!(f, "{}", s) } @@ -197,6 +199,12 @@ }), sub: vec![ Test { + name: "SEV Firmware Version", + gen_mask: SNP_MASK, + run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), + sub: vec![], + }, + Test { name: "Encrypted State (SEV-ES)", gen_mask: ES_MASK, run: Box::new(|| { @@ -215,14 +223,14 @@ } }), sub: vec![Test { - name: "SEV-ES INIT", + name: "SEV-ES initialized", gen_mask: ES_MASK, - run: Box::new(|| sev_ioctl(SevStatusTests::Seves)), + run: Box::new(|| sev_ioctl(SevStatusTests::SevEs)), sub: vec![], }], }, Test { - name: "SEV INIT", + name: "SEV initialized", gen_mask: SNP_MASK, run: Box::new(|| sev_ioctl(SevStatusTests::Sev)), sub: vec![], @@ -287,16 +295,29 @@ sub: vec![], }, Test { - name: "SEV Firmware Version", - gen_mask: SNP_MASK, - run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), - sub: vec![], - }, - Test { - name: "SNP INIT", + name: "SNP initialized", gen_mask: SNP_MASK, run: Box::new(|| snp_ioctl(SnpStatusTest::Snp)), - sub: vec![], + sub: vec![ + Test { + name: "Read RMP tables", + gen_mask: SNP_MASK, + run: Box::new(get_rmp_address), + sub: vec![], + }, + Test { + name: "RMP table initialized", + gen_mask: SNP_MASK, + run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), + sub: vec![], + }, + Test { + name: "Alias check", + gen_mask: SNP_MASK, + run: Box::new(|| snp_ioctl(SnpStatusTest::AliasCheck)), + sub: vec![], + }, + ], }, ], }, @@ -444,18 +465,6 @@ sub: vec![], }, Test { - name: "Read RMP tables", - gen_mask: SNP_MASK, - run: Box::new(get_rmp_address), - sub: vec![], - }, - Test { - name: "RMP INIT", - gen_mask: SNP_MASK, - run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), - sub: vec![], - }, - Test { name: "Compare TCB values", gen_mask: SNP_MASK, run: Box::new(|| snp_ioctl(SnpStatusTest::Tcb)), @@ -475,7 +484,7 @@ Ok(()) } else { Err(anyhow::anyhow!( - "One or more tests in sevctl-ok reported a failure" + "One or more tests in snphost ok reported a failure" )) } } @@ -569,27 +578,27 @@ fn dev_sev_r() -> TestResult { let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().read(true)) { - Ok(_) => (TestState::Pass, "/dev/sev readable".to_string()), - Err(e) => (TestState::Fail, format!("/dev/sev not readable: {}", e)), + Ok(_) => (TestState::Pass, None), + Err(e) => (TestState::Fail, Some(format!("Not readable: {}", e))), }; TestResult { - name: "Reading /dev/sev".to_string(), + name: "/dev/sev readable".to_string(), stat, - mesg: Some(mesg), + mesg, } } fn dev_sev_w() -> TestResult { let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().write(true)) { - Ok(_) => (TestState::Pass, "/dev/sev writable".to_string()), - Err(e) => (TestState::Fail, format!("/dev/sev not writable: {}", e)), + Ok(_) => (TestState::Pass, None), + Err(e) => (TestState::Fail, Some(format!("Not writable: {}", e))), }; TestResult { - name: "Writing /dev/sev".to_string(), + name: "/dev/sev writable".to_string(), stat, - mesg: Some(mesg), + mesg, } } @@ -639,23 +648,27 @@ match std::fs::read_to_string(path_loc) { Ok(result) => { if result.trim() == "1" || result.trim() == "Y" { - (TestState::Pass, "enabled".to_string()) + (TestState::Pass, None) } else { ( TestState::Fail, - format!("Error - contents read from {}: {}", path_loc, result.trim()), + Some(format!( + "Error - contents read from {}: {}", + path_loc, + result.trim() + )), ) } } Err(e) => ( TestState::Fail, - format!("Error - (unable to read {}): {}", path_loc, e,), + Some(format!("Error - (unable to read {}): {}", path_loc, e,)), ), } } else { ( TestState::Fail, - format!("Error - {} does not exist", path_loc), + Some(format!("Error - {} does not exist", path_loc)), ) }; @@ -667,7 +680,7 @@ } .to_string(), stat, - mesg: Some(mesg), + mesg, } } @@ -779,7 +792,7 @@ TestResult { name: "RMP table addresses".to_string(), stat: TestState::Pass, - mesg: format!("Addresses: {} - {}", rmp_base, rmp_end).into(), + mesg: format!("0x{:x} - 0x{:x}", rmp_base, rmp_end).into(), } } } @@ -815,17 +828,34 @@ } } SnpStatusTest::Rmp => { - if status.is_rmp_init == 1 { + if status.is_rmp_init.is_rmp_init() { TestResult { name: format!("{}", SnpStatusTest::Rmp), stat: TestState::Pass, - mesg: Some("RMP is INIT".to_string()), + mesg: None, } } else { TestResult { name: format!("{}", SnpStatusTest::Rmp), stat: TestState::Fail, - mesg: Some("RMP is UNINIT".to_string()), + mesg: None, + } + } + } + SnpStatusTest::AliasCheck => { + if status.is_rmp_init.alias_check_complete() { + TestResult { + name: format!("{}", SnpStatusTest::AliasCheck), + stat: TestState::Pass, + mesg: Some( + "Completed since last system update, no aliasing addresses".to_string(), + ), + } + } else { + TestResult { + name: format!("{}", SnpStatusTest::AliasCheck), + stat: TestState::Fail, + mesg: None, } } } @@ -834,13 +864,13 @@ TestResult { name: format!("{}", SnpStatusTest::Snp), stat: TestState::Pass, - mesg: Some("SNP is INIT".to_string()), + mesg: None, } } else { TestResult { name: format!("{}", SnpStatusTest::Snp), stat: TestState::Fail, - mesg: Some("SNP is UNINIT".to_string()), + mesg: None, } } } @@ -864,19 +894,19 @@ TestResult { name: format!("{}", SevStatusTests::Sev), stat: TestState::Pass, - mesg: Some("SEV is INIT and currently running a guest".to_string()), + mesg: Some("Initialized, currently running a guest".to_string()), } } else if status.state == State::Initialized { TestResult { name: format!("{}", SevStatusTests::Sev), stat: TestState::Pass, - mesg: Some("SEV is INIT, but not currently running a guest".to_string()), + mesg: Some("Initialized, no guests running".to_string()), } } else { TestResult { name: format!("{}", SevStatusTests::Sev), stat: TestState::Fail, - mesg: Some("SEV is UNINIT".to_string()), + mesg: Some("Uninitialized".to_string()), } } } @@ -906,21 +936,21 @@ TestResult { name: format!("{}", SevStatusTests::Firmware), stat: TestState::Pass, - mesg: format!("Sev firmware version: {}", status.build.version).into(), + mesg: format!("{}", status.build.version).into(), } } } - SevStatusTests::Seves => { - let (res, mesg) = match status.flags.bits() >> 8 & 1 { - 1 => (TestState::Pass, "Enabled"), - 0 => (TestState::Fail, "Disabled"), + SevStatusTests::SevEs => { + let res = match status.flags.bits() >> 8 & 1 { + 1 => TestState::Pass, + 0 => TestState::Fail, _ => unreachable!(), }; TestResult { - name: format!("{}", SevStatusTests::Seves), + name: format!("{}", SevStatusTests::SevEs), stat: res, - mesg: Some(mesg.to_string()), + mesg: None, } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/show.rs new/snphost-0.6.0/src/show.rs --- old/snphost-0.5.0/src/show.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/show.rs 2025-04-10 17:35:21.000000000 +0200 @@ -44,7 +44,7 @@ println!("{}", url); } - Show::Version => println!("{}", status.version), + Show::Version => println!("{}.{}", status.version.0, status.version.1), } Ok(()) ++++++ snphost-0.5.0.tar.gz -> snphost-0.6.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/.github/workflows/lint.yml new/snphost-0.6.0/.github/workflows/lint.yml --- old/snphost-0.5.0/.github/workflows/lint.yml 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/.github/workflows/lint.yml 2025-04-10 17:35:21.000000000 +0200 @@ -26,7 +26,7 @@ - uses: actions-rs/toolchain@v1 with: components: clippy - toolchain: 1.80 + toolchain: 1.80.0 profile: minimal override: true - uses: actions-rs/cargo@v1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/0001-Update-to-0.6.0.patch new/snphost-0.6.0/0001-Update-to-0.6.0.patch --- old/snphost-0.5.0/0001-Update-to-0.6.0.patch 1970-01-01 01:00:00.000000000 +0100 +++ new/snphost-0.6.0/0001-Update-to-0.6.0.patch 2025-04-10 17:35:21.000000000 +0200 @@ -0,0 +1,576 @@ +From dc6051450919d0789e0a15069b143dc50c9e0bf8 Mon Sep 17 00:00:00 2001 +From: Caleb Crane <ccr...@suse.de> +Date: Thu, 29 May 2025 10:09:41 -0400 +Subject: [PATCH] Update to 0.6.0 + +Signed-off-by: Tyler Fanelli <tfane...@redhat.com> +(cherry picked from commit 545bdf882ec5a5f054e0b75d0b382040bd8efc39) +Signed-off-by: Caleb Crane <ccr...@suse.de> +--- + .github/workflows/lint.yml | 2 +- + Cargo.lock | 14 ++-- + Cargo.toml | 6 +- + docs/snphost.1.adoc | 7 +- + src/cert/fetch/ca.rs | 7 +- + src/cert/fetch/vcek.rs | 9 ++- + src/config.rs | 21 +++++- + src/ok.rs | 148 ++++++++++++++++++++++--------------- + src/show.rs | 2 +- + 9 files changed, 136 insertions(+), 80 deletions(-) + +diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml +index 5cf4bd4..36ce92c 100644 +--- a/.github/workflows/lint.yml ++++ b/.github/workflows/lint.yml +@@ -26,7 +26,7 @@ jobs: + - uses: actions-rs/toolchain@v1 + with: + components: clippy +- toolchain: 1.80 ++ toolchain: 1.80.0 + profile: minimal + override: true + - uses: actions-rs/cargo@v1 +diff --git a/Cargo.lock b/Cargo.lock +index b5f0a54..0a099a2 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -313,9 +313,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + + [[package]] + name = "libc" +-version = "0.2.154" ++version = "0.2.162" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" ++checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + + [[package]] + name = "libredox" +@@ -544,9 +544,9 @@ dependencies = [ + + [[package]] + name = "sev" +-version = "4.0.0" ++version = "6.0.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "a97bd0b2e2d937951add10c8512a2dacc6ad29b39e5c5f26565a3e443329857d" ++checksum = "20ac277517d8fffdf3c41096323ed705b3a7c75e397129c072fb448339839d0f" + dependencies = [ + "base64", + "bincode", +@@ -570,7 +570,7 @@ dependencies = [ + + [[package]] + name = "snphost" +-version = "0.5.0" ++version = "0.6.0" + dependencies = [ + "anyhow", + "clap", +@@ -658,9 +658,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + + [[package]] + name = "uuid" +-version = "1.8.0" ++version = "1.11.0" + source = "registry+https://github.com/rust-lang/crates.io-index" +-checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" ++checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" + dependencies = [ + "serde", + ] +diff --git a/Cargo.toml b/Cargo.toml +index f09f99c..10f0876 100644 +--- a/Cargo.toml ++++ b/Cargo.toml +@@ -1,6 +1,6 @@ + [package] + name = "snphost" +-version = "0.5.0" ++version = "0.6.0" + authors = ["The VirTEE Project Developers"] + edition = "2021" + license = "Apache-2.0" +@@ -25,10 +25,10 @@ is-it-maintained-open-issues = { repository = "virtee/snphost" } + + [dependencies] + anyhow = "1.0.83" +-sev = { version = "4.0.0", features = ['openssl']} ++sev = { version = "6.0.0", features = ['openssl']} + env_logger = "0.10.1" + clap = { version = "4.5", features = [ "derive" ] } + colorful = "0.2.2" +-libc = "0.2.154" ++libc = "0.2.161" + curl = "0.4" + msru = "0.2.0" +diff --git a/docs/snphost.1.adoc b/docs/snphost.1.adoc +index 560dc0b..c933f2e 100644 +--- a/docs/snphost.1.adoc ++++ b/docs/snphost.1.adoc +@@ -102,6 +102,7 @@ COMMANDS + + For example, if the user would like MASK KEY to be enabled and CHIP ID disabled, + then the they would pass in a 2. ++ FMC: Current FMC firmware version + + options: + -h, --help Show a help message. +@@ -154,12 +155,14 @@ COMMANDS + -h, --help Show a help message + + *snphost fetch vcek*:: +- usage: snphost fetch vcek [ der, pem ] DIR-PATH ++ usage: snphost fetch vcek [ der, pem ] DIR-PATH [url] + + This command fetches the host system's versioned chip endorsement + key (VCEK) and writes the encoded certificate to the directory at path + DIR-PATH. Users must specify which format they would like the +- certificate to be encoded in (DER or PEM). ++ certificate to be encoded in (DER or PEM). The URL of the VCEK can be ++ explicitly set. If not explicitly set, the URL will be generated based ++ on firmware data. + + options: + -h, --help Show a help message +diff --git a/src/cert/fetch/ca.rs b/src/cert/fetch/ca.rs +index 694cb54..3308e16 100644 +--- a/src/cert/fetch/ca.rs ++++ b/src/cert/fetch/ca.rs +@@ -3,7 +3,7 @@ + use super::*; + use anyhow::{Context, Result}; + use curl::easy::Easy; +-use sev::certs::snp::{ca::Chain, Certificate}; ++use sev::certs::snp::ca::Chain; + use std::{ + fs::{create_dir_all, OpenOptions}, + io::Write, +@@ -76,10 +76,7 @@ pub fn fetch(url: &str) -> Result<Chain> { + transfer.perform()?; + drop(transfer); + +- Ok(Chain { +- ask: Certificate::from_pem(&buf[..2325])?, +- ark: Certificate::from_pem(&buf[2325..])?, +- }) ++ Ok(Chain::from_pem_bytes(&buf)?) + } + + fn ca_chain_url() -> Result<String> { +diff --git a/src/cert/fetch/vcek.rs b/src/cert/fetch/vcek.rs +index be74c43..5aeec21 100644 +--- a/src/cert/fetch/vcek.rs ++++ b/src/cert/fetch/vcek.rs +@@ -23,10 +23,17 @@ pub struct Vcek { + /// The path of a directory to store the encoded VCEK in + #[arg(value_name = "path", required = true)] + path: PathBuf, ++ ++ /// The URL of the VCEK. If not explicitly set, the URL will be generated based on firmware data ++ #[arg(value_name = "url", required = false)] ++ url: Option<String>, + } + + pub fn cmd(vcek: Vcek) -> Result<()> { +- let url = vcek_url()?; ++ let url = match vcek.url { ++ Some(url) => url, ++ None => vcek_url()?, ++ }; + let cert = fetch(&url).context(format!("unable to fetch VCEK from {}", url))?; + + let (vcek_name, vcek_bytes) = match vcek.encoding_fmt { +diff --git a/src/config.rs b/src/config.rs +index b4b1c1d..4a5f9c3 100644 +--- a/src/config.rs ++++ b/src/config.rs +@@ -1,6 +1,8 @@ + // SPDX-License-Identifier: Apache-2.0 + + use super::*; ++use crate::processor::ProcessorGeneration; ++use anyhow::anyhow; + + // Different config commands + #[derive(Subcommand)] +@@ -45,11 +47,28 @@ mod set { + /// Change mask chip bit field (Unsigned 32-bit Integer) values by providing decimal representation of desired change (0-3). Bit[0]: CHIP_ID, Bit[1]: CHIP_KEY. Both are disabled by default + #[arg(value_name = "mask-chip", required = true)] + mask_chip: u32, ++ ++ /// FMC firmware version. ++ #[arg(value_name = "fmc", required = false)] ++ fmc: Option<u8>, + } + + pub fn set_config(args: Args) -> Result<()> { ++ let fmc = match ProcessorGeneration::current()? { ++ ProcessorGeneration::Turin => { ++ let Some(fmc) = args.fmc else { ++ return Err(anyhow!( ++ "Turin generation processor requires FMC version when setting TCB" ++ )); ++ }; ++ ++ Some(fmc) ++ } ++ _ => None, ++ }; ++ + // Create Tcb with provided values +- let tcb = TcbVersion::new(args.bootloader, args.tee, args.snp_fw, args.microcode); ++ let tcb = TcbVersion::new(fmc, args.bootloader, args.tee, args.snp_fw, args.microcode); + + // Create Mask Chip with provided value + let mask_chip = MaskId(args.mask_chip); +diff --git a/src/ok.rs b/src/ok.rs +index 209404c..0fc1fc9 100644 +--- a/src/ok.rs ++++ b/src/ok.rs +@@ -63,21 +63,23 @@ impl fmt::Display for TestState { + enum SnpStatusTest { + Tcb, + Rmp, ++ AliasCheck, + Snp, + } + + enum SevStatusTests { + Sev, + Firmware, +- Seves, ++ SevEs, + } + + impl fmt::Display for SnpStatusTest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { + SnpStatusTest::Tcb => "Comparing TCB values", +- SnpStatusTest::Rmp => "RMP INIT", +- SnpStatusTest::Snp => "SNP INIT", ++ SnpStatusTest::Rmp => "RMP table initialized", ++ SnpStatusTest::AliasCheck => "Alias check", ++ SnpStatusTest::Snp => "SNP initialized", + }; + write!(f, "{}", s) + } +@@ -86,9 +88,9 @@ impl fmt::Display for SnpStatusTest { + impl fmt::Display for SevStatusTests { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = match self { +- SevStatusTests::Sev => "SEV INIT", +- SevStatusTests::Firmware => "SEV Firmware Version", +- SevStatusTests::Seves => "SEV-ES INIT", ++ SevStatusTests::Sev => "SEV initialized", ++ SevStatusTests::Firmware => "SEV firmware version", ++ SevStatusTests::SevEs => "SEV-ES initialized", + }; + write!(f, "{}", s) + } +@@ -196,6 +198,12 @@ fn collect_tests() -> Vec<Test> { + } + }), + sub: vec![ ++ Test { ++ name: "SEV Firmware Version", ++ gen_mask: SNP_MASK, ++ run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), ++ sub: vec![], ++ }, + Test { + name: "Encrypted State (SEV-ES)", + gen_mask: ES_MASK, +@@ -215,14 +223,14 @@ fn collect_tests() -> Vec<Test> { + } + }), + sub: vec![Test { +- name: "SEV-ES INIT", ++ name: "SEV-ES initialized", + gen_mask: ES_MASK, +- run: Box::new(|| sev_ioctl(SevStatusTests::Seves)), ++ run: Box::new(|| sev_ioctl(SevStatusTests::SevEs)), + sub: vec![], + }], + }, + Test { +- name: "SEV INIT", ++ name: "SEV initialized", + gen_mask: SNP_MASK, + run: Box::new(|| sev_ioctl(SevStatusTests::Sev)), + sub: vec![], +@@ -287,16 +295,29 @@ fn collect_tests() -> Vec<Test> { + sub: vec![], + }, + Test { +- name: "SEV Firmware Version", +- gen_mask: SNP_MASK, +- run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), +- sub: vec![], +- }, +- Test { +- name: "SNP INIT", ++ name: "SNP initialized", + gen_mask: SNP_MASK, + run: Box::new(|| snp_ioctl(SnpStatusTest::Snp)), +- sub: vec![], ++ sub: vec![ ++ Test { ++ name: "Read RMP tables", ++ gen_mask: SNP_MASK, ++ run: Box::new(get_rmp_address), ++ sub: vec![], ++ }, ++ Test { ++ name: "RMP table initialized", ++ gen_mask: SNP_MASK, ++ run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), ++ sub: vec![], ++ }, ++ Test { ++ name: "Alias check", ++ gen_mask: SNP_MASK, ++ run: Box::new(|| snp_ioctl(SnpStatusTest::AliasCheck)), ++ sub: vec![], ++ }, ++ ], + }, + ], + }, +@@ -443,18 +464,6 @@ fn collect_tests() -> Vec<Test> { + run: Box::new(memlock_rlimit), + sub: vec![], + }, +- Test { +- name: "Read RMP tables", +- gen_mask: SNP_MASK, +- run: Box::new(get_rmp_address), +- sub: vec![], +- }, +- Test { +- name: "RMP INIT", +- gen_mask: SNP_MASK, +- run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), +- sub: vec![], +- }, + Test { + name: "Compare TCB values", + gen_mask: SNP_MASK, +@@ -475,7 +484,7 @@ pub fn cmd(quiet: bool) -> Result<()> { + Ok(()) + } else { + Err(anyhow::anyhow!( +- "One or more tests in sevctl-ok reported a failure" ++ "One or more tests in snphost ok reported a failure" + )) + } + } +@@ -569,27 +578,27 @@ fn emit_skip(tests: &[Test], level: usize, quiet: bool) { + + fn dev_sev_r() -> TestResult { + let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().read(true)) { +- Ok(_) => (TestState::Pass, "/dev/sev readable".to_string()), +- Err(e) => (TestState::Fail, format!("/dev/sev not readable: {}", e)), ++ Ok(_) => (TestState::Pass, None), ++ Err(e) => (TestState::Fail, Some(format!("Not readable: {}", e))), + }; + + TestResult { +- name: "Reading /dev/sev".to_string(), ++ name: "/dev/sev readable".to_string(), + stat, +- mesg: Some(mesg), ++ mesg, + } + } + + fn dev_sev_w() -> TestResult { + let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().write(true)) { +- Ok(_) => (TestState::Pass, "/dev/sev writable".to_string()), +- Err(e) => (TestState::Fail, format!("/dev/sev not writable: {}", e)), ++ Ok(_) => (TestState::Pass, None), ++ Err(e) => (TestState::Fail, Some(format!("Not writable: {}", e))), + }; + + TestResult { +- name: "Writing /dev/sev".to_string(), ++ name: "/dev/sev writable".to_string(), + stat, +- mesg: Some(mesg), ++ mesg, + } + } + +@@ -639,23 +648,27 @@ fn sev_enabled_in_kvm(gen: SevGeneration) -> TestResult { + match std::fs::read_to_string(path_loc) { + Ok(result) => { + if result.trim() == "1" || result.trim() == "Y" { +- (TestState::Pass, "enabled".to_string()) ++ (TestState::Pass, None) + } else { + ( + TestState::Fail, +- format!("Error - contents read from {}: {}", path_loc, result.trim()), ++ Some(format!( ++ "Error - contents read from {}: {}", ++ path_loc, ++ result.trim() ++ )), + ) + } + } + Err(e) => ( + TestState::Fail, +- format!("Error - (unable to read {}): {}", path_loc, e,), ++ Some(format!("Error - (unable to read {}): {}", path_loc, e,)), + ), + } + } else { + ( + TestState::Fail, +- format!("Error - {} does not exist", path_loc), ++ Some(format!("Error - {} does not exist", path_loc)), + ) + }; + +@@ -667,7 +680,7 @@ fn sev_enabled_in_kvm(gen: SevGeneration) -> TestResult { + } + .to_string(), + stat, +- mesg: Some(mesg), ++ mesg, + } + } + +@@ -779,7 +792,7 @@ fn get_rmp_address() -> TestResult { + TestResult { + name: "RMP table addresses".to_string(), + stat: TestState::Pass, +- mesg: format!("Addresses: {} - {}", rmp_base, rmp_end).into(), ++ mesg: format!("0x{:x} - 0x{:x}", rmp_base, rmp_end).into(), + } + } + } +@@ -815,17 +828,34 @@ fn snp_ioctl(test: SnpStatusTest) -> TestResult { + } + } + SnpStatusTest::Rmp => { +- if status.is_rmp_init == 1 { ++ if status.is_rmp_init.is_rmp_init() { + TestResult { + name: format!("{}", SnpStatusTest::Rmp), + stat: TestState::Pass, +- mesg: Some("RMP is INIT".to_string()), ++ mesg: None, + } + } else { + TestResult { + name: format!("{}", SnpStatusTest::Rmp), + stat: TestState::Fail, +- mesg: Some("RMP is UNINIT".to_string()), ++ mesg: None, ++ } ++ } ++ } ++ SnpStatusTest::AliasCheck => { ++ if status.is_rmp_init.alias_check_complete() { ++ TestResult { ++ name: format!("{}", SnpStatusTest::AliasCheck), ++ stat: TestState::Pass, ++ mesg: Some( ++ "Completed since last system update, no aliasing addresses".to_string(), ++ ), ++ } ++ } else { ++ TestResult { ++ name: format!("{}", SnpStatusTest::AliasCheck), ++ stat: TestState::Fail, ++ mesg: None, + } + } + } +@@ -834,13 +864,13 @@ fn snp_ioctl(test: SnpStatusTest) -> TestResult { + TestResult { + name: format!("{}", SnpStatusTest::Snp), + stat: TestState::Pass, +- mesg: Some("SNP is INIT".to_string()), ++ mesg: None, + } + } else { + TestResult { + name: format!("{}", SnpStatusTest::Snp), + stat: TestState::Fail, +- mesg: Some("SNP is UNINIT".to_string()), ++ mesg: None, + } + } + } +@@ -864,19 +894,19 @@ fn sev_ioctl(test: SevStatusTests) -> TestResult { + TestResult { + name: format!("{}", SevStatusTests::Sev), + stat: TestState::Pass, +- mesg: Some("SEV is INIT and currently running a guest".to_string()), ++ mesg: Some("Initialized, currently running a guest".to_string()), + } + } else if status.state == State::Initialized { + TestResult { + name: format!("{}", SevStatusTests::Sev), + stat: TestState::Pass, +- mesg: Some("SEV is INIT, but not currently running a guest".to_string()), ++ mesg: Some("Initialized, no guests running".to_string()), + } + } else { + TestResult { + name: format!("{}", SevStatusTests::Sev), + stat: TestState::Fail, +- mesg: Some("SEV is UNINIT".to_string()), ++ mesg: Some("Uninitialized".to_string()), + } + } + } +@@ -906,21 +936,21 @@ fn sev_ioctl(test: SevStatusTests) -> TestResult { + TestResult { + name: format!("{}", SevStatusTests::Firmware), + stat: TestState::Pass, +- mesg: format!("Sev firmware version: {}", status.build.version).into(), ++ mesg: format!("{}", status.build.version).into(), + } + } + } + +- SevStatusTests::Seves => { +- let (res, mesg) = match status.flags.bits() >> 8 & 1 { +- 1 => (TestState::Pass, "Enabled"), +- 0 => (TestState::Fail, "Disabled"), ++ SevStatusTests::SevEs => { ++ let res = match status.flags.bits() >> 8 & 1 { ++ 1 => TestState::Pass, ++ 0 => TestState::Fail, + _ => unreachable!(), + }; + TestResult { +- name: format!("{}", SevStatusTests::Seves), ++ name: format!("{}", SevStatusTests::SevEs), + stat: res, +- mesg: Some(mesg.to_string()), ++ mesg: None, + } + } + } +diff --git a/src/show.rs b/src/show.rs +index bb69208..1825fef 100644 +--- a/src/show.rs ++++ b/src/show.rs +@@ -44,7 +44,7 @@ pub fn cmd(show: Show) -> Result<()> { + + println!("{}", url); + } +- Show::Version => println!("{}", status.version), ++ Show::Version => println!("{}.{}", status.version.0, status.version.1), + } + + Ok(()) +-- +2.49.0 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/Cargo.lock new/snphost-0.6.0/Cargo.lock --- old/snphost-0.5.0/Cargo.lock 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/Cargo.lock 2025-04-10 17:35:21.000000000 +0200 @@ -313,9 +313,9 @@ [[package]] name = "libc" -version = "0.2.154" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libredox" @@ -544,9 +544,9 @@ [[package]] name = "sev" -version = "4.0.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97bd0b2e2d937951add10c8512a2dacc6ad29b39e5c5f26565a3e443329857d" +checksum = "20ac277517d8fffdf3c41096323ed705b3a7c75e397129c072fb448339839d0f" dependencies = [ "base64", "bincode", @@ -570,7 +570,7 @@ [[package]] name = "snphost" -version = "0.5.0" +version = "0.6.0" dependencies = [ "anyhow", "clap", @@ -658,9 +658,9 @@ [[package]] name = "uuid" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "serde", ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/Cargo.toml new/snphost-0.6.0/Cargo.toml --- old/snphost-0.5.0/Cargo.toml 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/Cargo.toml 2025-04-10 17:35:21.000000000 +0200 @@ -1,6 +1,6 @@ [package] name = "snphost" -version = "0.5.0" +version = "0.6.0" authors = ["The VirTEE Project Developers"] edition = "2021" license = "Apache-2.0" @@ -25,10 +25,10 @@ [dependencies] anyhow = "1.0.83" -sev = { version = "4.0.0", features = ['openssl']} +sev = { version = "6.0.0", features = ['openssl']} env_logger = "0.10.1" clap = { version = "4.5", features = [ "derive" ] } colorful = "0.2.2" -libc = "0.2.154" +libc = "0.2.161" curl = "0.4" msru = "0.2.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/docs/snphost.1.adoc new/snphost-0.6.0/docs/snphost.1.adoc --- old/snphost-0.5.0/docs/snphost.1.adoc 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/docs/snphost.1.adoc 2025-04-10 17:35:21.000000000 +0200 @@ -102,6 +102,7 @@ For example, if the user would like MASK KEY to be enabled and CHIP ID disabled, then the they would pass in a 2. + FMC: Current FMC firmware version options: -h, --help Show a help message. @@ -154,12 +155,14 @@ -h, --help Show a help message *snphost fetch vcek*:: - usage: snphost fetch vcek [ der, pem ] DIR-PATH + usage: snphost fetch vcek [ der, pem ] DIR-PATH [url] This command fetches the host system's versioned chip endorsement key (VCEK) and writes the encoded certificate to the directory at path DIR-PATH. Users must specify which format they would like the - certificate to be encoded in (DER or PEM). + certificate to be encoded in (DER or PEM). The URL of the VCEK can be + explicitly set. If not explicitly set, the URL will be generated based + on firmware data. options: -h, --help Show a help message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/cert/fetch/ca.rs new/snphost-0.6.0/src/cert/fetch/ca.rs --- old/snphost-0.5.0/src/cert/fetch/ca.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/cert/fetch/ca.rs 2025-04-10 17:35:21.000000000 +0200 @@ -3,7 +3,7 @@ use super::*; use anyhow::{Context, Result}; use curl::easy::Easy; -use sev::certs::snp::{ca::Chain, Certificate}; +use sev::certs::snp::ca::Chain; use std::{ fs::{create_dir_all, OpenOptions}, io::Write, @@ -76,10 +76,7 @@ transfer.perform()?; drop(transfer); - Ok(Chain { - ask: Certificate::from_pem(&buf[..2325])?, - ark: Certificate::from_pem(&buf[2325..])?, - }) + Ok(Chain::from_pem_bytes(&buf)?) } fn ca_chain_url() -> Result<String> { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/cert/fetch/vcek.rs new/snphost-0.6.0/src/cert/fetch/vcek.rs --- old/snphost-0.5.0/src/cert/fetch/vcek.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/cert/fetch/vcek.rs 2025-04-10 17:35:21.000000000 +0200 @@ -23,10 +23,17 @@ /// The path of a directory to store the encoded VCEK in #[arg(value_name = "path", required = true)] path: PathBuf, + + /// The URL of the VCEK. If not explicitly set, the URL will be generated based on firmware data + #[arg(value_name = "url", required = false)] + url: Option<String>, } pub fn cmd(vcek: Vcek) -> Result<()> { - let url = vcek_url()?; + let url = match vcek.url { + Some(url) => url, + None => vcek_url()?, + }; let cert = fetch(&url).context(format!("unable to fetch VCEK from {}", url))?; let (vcek_name, vcek_bytes) = match vcek.encoding_fmt { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/config.rs new/snphost-0.6.0/src/config.rs --- old/snphost-0.5.0/src/config.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/config.rs 2025-04-10 17:35:21.000000000 +0200 @@ -1,6 +1,8 @@ // SPDX-License-Identifier: Apache-2.0 use super::*; +use crate::processor::ProcessorGeneration; +use anyhow::anyhow; // Different config commands #[derive(Subcommand)] @@ -45,11 +47,28 @@ /// Change mask chip bit field (Unsigned 32-bit Integer) values by providing decimal representation of desired change (0-3). Bit[0]: CHIP_ID, Bit[1]: CHIP_KEY. Both are disabled by default #[arg(value_name = "mask-chip", required = true)] mask_chip: u32, + + /// FMC firmware version. + #[arg(value_name = "fmc", required = false)] + fmc: Option<u8>, } pub fn set_config(args: Args) -> Result<()> { + let fmc = match ProcessorGeneration::current()? { + ProcessorGeneration::Turin => { + let Some(fmc) = args.fmc else { + return Err(anyhow!( + "Turin generation processor requires FMC version when setting TCB" + )); + }; + + Some(fmc) + } + _ => None, + }; + // Create Tcb with provided values - let tcb = TcbVersion::new(args.bootloader, args.tee, args.snp_fw, args.microcode); + let tcb = TcbVersion::new(fmc, args.bootloader, args.tee, args.snp_fw, args.microcode); // Create Mask Chip with provided value let mask_chip = MaskId(args.mask_chip); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/ok.rs new/snphost-0.6.0/src/ok.rs --- old/snphost-0.5.0/src/ok.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/ok.rs 2025-04-10 17:35:21.000000000 +0200 @@ -63,21 +63,23 @@ enum SnpStatusTest { Tcb, Rmp, + AliasCheck, Snp, } enum SevStatusTests { Sev, Firmware, - Seves, + SevEs, } impl fmt::Display for SnpStatusTest { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { SnpStatusTest::Tcb => "Comparing TCB values", - SnpStatusTest::Rmp => "RMP INIT", - SnpStatusTest::Snp => "SNP INIT", + SnpStatusTest::Rmp => "RMP table initialized", + SnpStatusTest::AliasCheck => "Alias check", + SnpStatusTest::Snp => "SNP initialized", }; write!(f, "{}", s) } @@ -86,9 +88,9 @@ impl fmt::Display for SevStatusTests { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let s = match self { - SevStatusTests::Sev => "SEV INIT", - SevStatusTests::Firmware => "SEV Firmware Version", - SevStatusTests::Seves => "SEV-ES INIT", + SevStatusTests::Sev => "SEV initialized", + SevStatusTests::Firmware => "SEV firmware version", + SevStatusTests::SevEs => "SEV-ES initialized", }; write!(f, "{}", s) } @@ -197,6 +199,12 @@ }), sub: vec![ Test { + name: "SEV Firmware Version", + gen_mask: SNP_MASK, + run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), + sub: vec![], + }, + Test { name: "Encrypted State (SEV-ES)", gen_mask: ES_MASK, run: Box::new(|| { @@ -215,14 +223,14 @@ } }), sub: vec![Test { - name: "SEV-ES INIT", + name: "SEV-ES initialized", gen_mask: ES_MASK, - run: Box::new(|| sev_ioctl(SevStatusTests::Seves)), + run: Box::new(|| sev_ioctl(SevStatusTests::SevEs)), sub: vec![], }], }, Test { - name: "SEV INIT", + name: "SEV initialized", gen_mask: SNP_MASK, run: Box::new(|| sev_ioctl(SevStatusTests::Sev)), sub: vec![], @@ -287,16 +295,29 @@ sub: vec![], }, Test { - name: "SEV Firmware Version", - gen_mask: SNP_MASK, - run: Box::new(|| sev_ioctl(SevStatusTests::Firmware)), - sub: vec![], - }, - Test { - name: "SNP INIT", + name: "SNP initialized", gen_mask: SNP_MASK, run: Box::new(|| snp_ioctl(SnpStatusTest::Snp)), - sub: vec![], + sub: vec![ + Test { + name: "Read RMP tables", + gen_mask: SNP_MASK, + run: Box::new(get_rmp_address), + sub: vec![], + }, + Test { + name: "RMP table initialized", + gen_mask: SNP_MASK, + run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), + sub: vec![], + }, + Test { + name: "Alias check", + gen_mask: SNP_MASK, + run: Box::new(|| snp_ioctl(SnpStatusTest::AliasCheck)), + sub: vec![], + }, + ], }, ], }, @@ -444,18 +465,6 @@ sub: vec![], }, Test { - name: "Read RMP tables", - gen_mask: SNP_MASK, - run: Box::new(get_rmp_address), - sub: vec![], - }, - Test { - name: "RMP INIT", - gen_mask: SNP_MASK, - run: Box::new(|| snp_ioctl(SnpStatusTest::Rmp)), - sub: vec![], - }, - Test { name: "Compare TCB values", gen_mask: SNP_MASK, run: Box::new(|| snp_ioctl(SnpStatusTest::Tcb)), @@ -475,7 +484,7 @@ Ok(()) } else { Err(anyhow::anyhow!( - "One or more tests in sevctl-ok reported a failure" + "One or more tests in snphost ok reported a failure" )) } } @@ -569,27 +578,27 @@ fn dev_sev_r() -> TestResult { let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().read(true)) { - Ok(_) => (TestState::Pass, "/dev/sev readable".to_string()), - Err(e) => (TestState::Fail, format!("/dev/sev not readable: {}", e)), + Ok(_) => (TestState::Pass, None), + Err(e) => (TestState::Fail, Some(format!("Not readable: {}", e))), }; TestResult { - name: "Reading /dev/sev".to_string(), + name: "/dev/sev readable".to_string(), stat, - mesg: Some(mesg), + mesg, } } fn dev_sev_w() -> TestResult { let (stat, mesg) = match dev_sev_rw(fs::OpenOptions::new().write(true)) { - Ok(_) => (TestState::Pass, "/dev/sev writable".to_string()), - Err(e) => (TestState::Fail, format!("/dev/sev not writable: {}", e)), + Ok(_) => (TestState::Pass, None), + Err(e) => (TestState::Fail, Some(format!("Not writable: {}", e))), }; TestResult { - name: "Writing /dev/sev".to_string(), + name: "/dev/sev writable".to_string(), stat, - mesg: Some(mesg), + mesg, } } @@ -639,23 +648,27 @@ match std::fs::read_to_string(path_loc) { Ok(result) => { if result.trim() == "1" || result.trim() == "Y" { - (TestState::Pass, "enabled".to_string()) + (TestState::Pass, None) } else { ( TestState::Fail, - format!("Error - contents read from {}: {}", path_loc, result.trim()), + Some(format!( + "Error - contents read from {}: {}", + path_loc, + result.trim() + )), ) } } Err(e) => ( TestState::Fail, - format!("Error - (unable to read {}): {}", path_loc, e,), + Some(format!("Error - (unable to read {}): {}", path_loc, e,)), ), } } else { ( TestState::Fail, - format!("Error - {} does not exist", path_loc), + Some(format!("Error - {} does not exist", path_loc)), ) }; @@ -667,7 +680,7 @@ } .to_string(), stat, - mesg: Some(mesg), + mesg, } } @@ -779,7 +792,7 @@ TestResult { name: "RMP table addresses".to_string(), stat: TestState::Pass, - mesg: format!("Addresses: {} - {}", rmp_base, rmp_end).into(), + mesg: format!("0x{:x} - 0x{:x}", rmp_base, rmp_end).into(), } } } @@ -815,17 +828,34 @@ } } SnpStatusTest::Rmp => { - if status.is_rmp_init == 1 { + if status.is_rmp_init.is_rmp_init() { TestResult { name: format!("{}", SnpStatusTest::Rmp), stat: TestState::Pass, - mesg: Some("RMP is INIT".to_string()), + mesg: None, } } else { TestResult { name: format!("{}", SnpStatusTest::Rmp), stat: TestState::Fail, - mesg: Some("RMP is UNINIT".to_string()), + mesg: None, + } + } + } + SnpStatusTest::AliasCheck => { + if status.is_rmp_init.alias_check_complete() { + TestResult { + name: format!("{}", SnpStatusTest::AliasCheck), + stat: TestState::Pass, + mesg: Some( + "Completed since last system update, no aliasing addresses".to_string(), + ), + } + } else { + TestResult { + name: format!("{}", SnpStatusTest::AliasCheck), + stat: TestState::Fail, + mesg: None, } } } @@ -834,13 +864,13 @@ TestResult { name: format!("{}", SnpStatusTest::Snp), stat: TestState::Pass, - mesg: Some("SNP is INIT".to_string()), + mesg: None, } } else { TestResult { name: format!("{}", SnpStatusTest::Snp), stat: TestState::Fail, - mesg: Some("SNP is UNINIT".to_string()), + mesg: None, } } } @@ -864,19 +894,19 @@ TestResult { name: format!("{}", SevStatusTests::Sev), stat: TestState::Pass, - mesg: Some("SEV is INIT and currently running a guest".to_string()), + mesg: Some("Initialized, currently running a guest".to_string()), } } else if status.state == State::Initialized { TestResult { name: format!("{}", SevStatusTests::Sev), stat: TestState::Pass, - mesg: Some("SEV is INIT, but not currently running a guest".to_string()), + mesg: Some("Initialized, no guests running".to_string()), } } else { TestResult { name: format!("{}", SevStatusTests::Sev), stat: TestState::Fail, - mesg: Some("SEV is UNINIT".to_string()), + mesg: Some("Uninitialized".to_string()), } } } @@ -906,21 +936,21 @@ TestResult { name: format!("{}", SevStatusTests::Firmware), stat: TestState::Pass, - mesg: format!("Sev firmware version: {}", status.build.version).into(), + mesg: format!("{}", status.build.version).into(), } } } - SevStatusTests::Seves => { - let (res, mesg) = match status.flags.bits() >> 8 & 1 { - 1 => (TestState::Pass, "Enabled"), - 0 => (TestState::Fail, "Disabled"), + SevStatusTests::SevEs => { + let res = match status.flags.bits() >> 8 & 1 { + 1 => TestState::Pass, + 0 => TestState::Fail, _ => unreachable!(), }; TestResult { - name: format!("{}", SevStatusTests::Seves), + name: format!("{}", SevStatusTests::SevEs), stat: res, - mesg: Some(mesg.to_string()), + mesg: None, } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snphost-0.5.0/src/show.rs new/snphost-0.6.0/src/show.rs --- old/snphost-0.5.0/src/show.rs 2024-09-06 04:33:15.000000000 +0200 +++ new/snphost-0.6.0/src/show.rs 2025-04-10 17:35:21.000000000 +0200 @@ -44,7 +44,7 @@ println!("{}", url); } - Show::Version => println!("{}", status.version), + Show::Version => println!("{}.{}", status.version.0, status.version.1), } Ok(()) ++++++ snphost.obsinfo ++++++ --- /var/tmp/diff_new_pack.wz4arJ/_old 2025-05-31 19:17:47.445049049 +0200 +++ /var/tmp/diff_new_pack.wz4arJ/_new 2025-05-31 19:17:47.445049049 +0200 @@ -1,5 +1,5 @@ name: snphost -version: 0.5.0 -mtime: 1725589995 -commit: a7ba00220202240cd01819ef1fe81d57ebbb9f8b +version: 0.6.0 +mtime: 1744299321 +commit: 545bdf882ec5a5f054e0b75d0b382040bd8efc39 ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/snphost/vendor.tar.gz /work/SRC/openSUSE:Factory/.snphost.new.16005/vendor.tar.gz differ: char 12, line 1