Skip to content

Commit

Permalink
Changing commands for new 6.6 kernel IOCTL structure
Browse files Browse the repository at this point in the history
Signed-off-by: DGonzalezVillal <[email protected]>
  • Loading branch information
DGonzalezVillal committed Feb 7, 2024
1 parent e8f2613 commit 6b908f7
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 83 deletions.
45 changes: 11 additions & 34 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ is-it-maintained-open-issues = { repository = "virtee/snphost" }

[dependencies]
anyhow = "1.0.71"
sev = { version = "1.2.0", features = [ "openssl" ] }
sev = { git = "https://github.com/DGonzalezVillal/virtee-sev.git", features = [ "openssl" ], branch = "FixExAttestation" }
env_logger = "0.10.1"
structopt = "0.3.26"
colorful = "0.2.2"
Expand Down
37 changes: 31 additions & 6 deletions src/cert/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

use super::EncodingFormat;
use anyhow::{bail, Context, Result};
use sev::{certs::snp::Certificate, firmware::host::CertType};
use sev::{
certs::snp::Certificate,
firmware::host::{CertTableEntry, CertType},
};
use structopt::StructOpt;

use std::{io::Write, path::PathBuf};

use crate::cert_entries;
use std::{
fs::File,
io::{BufReader, Read, Write},
path::PathBuf,
};

fn identify_cert(buf: &[u8]) -> EncodingFormat {
const PEM_START: &[u8] = b"-----BEGIN CERTIFICATE-----";
Expand All @@ -17,13 +22,23 @@ fn identify_cert(buf: &[u8]) -> EncodingFormat {
}
}

// Convert kernel formatted certs into user readable certificates
fn cert_entries(cert_bytes: Vec<u8>) -> Result<Vec<CertTableEntry>> {
let certs = CertTableEntry::vec_bytes_to_cert_table(cert_bytes.to_vec())
.context("Could not convert bytes to certs")?;
Ok(certs)
}

#[derive(StructOpt)]
pub struct Export {
#[structopt(about = "The format the certs are encoded in (PEM or DER)")]
#[structopt(about = "The format the certs will be encoded in (PEM or DER)")]
pub encoding_fmt: EncodingFormat,

#[structopt(about = "The directory to write the certificates to")]
pub dir_path: PathBuf,

#[structopt(about = "File where the formatted certificates are stored.")]
pub target_file: PathBuf,
}

pub fn cmd(export: Export) -> Result<()> {
Expand All @@ -34,7 +49,17 @@ pub fn cmd(export: Export) -> Result<()> {
export.dir_path.display()
))?;

let entries = cert_entries()?;
// Read the cert file with the kenrel formatted certs
let cert_file = File::open(export.target_file)?;
let mut reader = BufReader::new(cert_file);
let mut cert_bytes = Vec::new();

// Read file into vector.
reader.read_to_end(&mut cert_bytes)?;

// Create a vec of CertTableEntry (x509 versioned)
let entries = cert_entries(cert_bytes)?;

for e in entries {
let type_id = match e.cert_type {
CertType::ARK => {
Expand Down
40 changes: 29 additions & 11 deletions src/cert/import.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,61 @@
// SPDX-License-Identifier: Apache-2.0

use sev::firmware::host::{CertTableEntry, CertType, ExtConfig};
use sev::firmware::host::{CertTableEntry, CertType};
use std::{
fs::{read, read_dir, DirEntry},
fs::{read, read_dir, DirEntry, File},
io::Write,
path::PathBuf,
};

use crate::firmware;

use structopt::StructOpt;

use anyhow::{anyhow, bail, Context, Result};

#[derive(StructOpt)]
pub struct Import {
#[structopt(about = "The directory to find the encoded certificates")]
pub path: PathBuf,
#[structopt(about = "The directory where the certificates are stored")]
pub cert_dir: PathBuf,

#[structopt(about = "File where the formatted certificates will be stored.")]
pub target_file: PathBuf,
}

pub fn cmd(import: Import) -> Result<()> {
if !import.path.exists() {
bail!(format!("path {} does not exist", import.path.display()));
if !import.cert_dir.exists() {
bail!(format!("path {} does not exist", import.cert_dir.display()));
}

let mut table: Vec<CertTableEntry> = vec![];

for dir_entry in read_dir(import.path.clone())? {
// For each cert in the directory convert into a kernel formatted cert and write into file
for dir_entry in read_dir(import.cert_dir.clone())? {
match dir_entry {
Ok(de) => table_add_entry(de, &mut table)?,
Err(_) => {
bail!(format!(
"unable to read directory at path {}",
import.path.display()
import.cert_dir.display()
))
}
}
}

firmware()?.snp_set_ext_config(ExtConfig::new_certs_only(table))?;
let cert_bytes = CertTableEntry::cert_table_to_vec_bytes(&table)
.context("Failed to convert certificates to GHCB formatted bytes.")?;

// Write cert into directory
let mut file = if import.target_file.exists() {
std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(import.target_file)
.context("Unable to overwrite kernel cert file contents")?
} else {
File::create(import.target_file).context("Unable to create kernel cert file")?
};

file.write(&cert_bytes)
.context(format!("unable to write data to file {:?}", file))?;

Ok(())
}
Expand Down
73 changes: 73 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: Apache-2.0

use super::*;

// Different config commands
#[derive(StructOpt)]
pub enum ConfigCmd {
#[structopt(about = "Change the Platform Config (TCB and Mask chip) to the provided values")]
Set(set::Args),

#[structopt(about = "Reset the SEV-SNP Config to the last comitted version")]
Reset,
}

pub fn cmd(cmd: ConfigCmd) -> Result<()> {
match cmd {
ConfigCmd::Set(args) => set::set_config(args),
ConfigCmd::Reset => reset::reset_config(),
}
}

mod set {
use super::*;

#[derive(StructOpt)]
pub struct Args {
#[structopt(help = "Bootloader: Bootloader version")]
pub bootloader: u8,

#[structopt(help = "TEE: PSP OS version")]
pub tee: u8,

#[structopt(help = "SNP FIRMWARE: Version of the SNP firmware")]
pub snp_fw: u8,

#[structopt(help = "MICROCODE: Patch level of all the cores")]
pub microcode: u8,

#[structopt(
help = "MASK CHIP: Change mask chip bit field values by providing decimal representation of desired change (0-3). Bit[0]: CHIP_ID, Bit[1]: CHIP_KEY. Both are disabled by default"
)]
mask_chip: u32,
}

pub fn set_config(args: Args) -> Result<()> {
// Create Tcb with provided values
let tcb = TcbVersion::new(args.bootloader, args.tee, args.snp_fw, args.microcode);

// Create Mask Chip with provided value
let mask_chip = MaskId(args.mask_chip);

// Create new Config
let config = Config::new(tcb, mask_chip);

// Change Config
let mut fw = firmware()?;
fw.snp_set_config(config)
.map_err(|e| anyhow::anyhow!(format!("{:?}", e)))
.context("Error setting a new snp config")
}
}

mod reset {
use super::*;
pub fn reset_config() -> Result<()> {
let mut fw = firmware()?;

// Provide confing to set_config with all 0s
fw.snp_set_config(Config::default())
.map_err(|e| anyhow::anyhow!(format!("{:?}", e)))
.context("Error resetting SEV-SNP configuration")
}
}
43 changes: 23 additions & 20 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
#![deny(clippy::all)]

mod cert;
mod config;
mod processor;
mod reset;
mod show;

mod ok;

use cert::{export, fetch, import, verify};

use anyhow::{anyhow, Context, Result};
use anyhow::{Context, Result};
use sev::firmware::host::*;
use structopt::StructOpt;

Expand All @@ -34,23 +34,37 @@ enum SnpHostCmd {
#[structopt(about = "Display information about the SEV-SNP platform")]
Show(show::Show),

#[structopt(about = "Export a certificate chain to a given directory")]
#[structopt(
about = "Export a certificate chain from a kernel format file to a given directory"
)]
Export(export::Export),

#[structopt(about = "Import a certificate chain to the AMD PSP")]
#[structopt(about = "Import a certificate chain to a file")]
Import(import::Import),

#[structopt(about = "Probe system for SEV-SNP support")]
Ok,

#[structopt(about = "Reset the SEV-SNP platform state")]
Reset,
#[structopt(about = "Modify the SNP configuration")]
Config(config::ConfigCmd),

#[structopt(about = "Verify a certificate chain")]
Verify(verify::Verify),

#[structopt(about = "Retrieve some content from the AMD Key Distribution Server (KDS)")]
#[structopt(about = "Retrieve content from the AMD Key Distribution Server (KDS)")]
Fetch(fetch::Fetch),

#[structopt(about = "Commit current firmware and TCB versions to PSP")]
Commit,
}

// Commit command
mod commit {
use super::*;
pub fn cmd() -> Result<()> {
firmware()?.snp_commit()?;
Ok(())
}
}

fn firmware() -> Result<Firmware> {
Expand All @@ -64,18 +78,6 @@ fn platform_status() -> Result<SnpPlatformStatus> {
.context("unable to retrieve SNP platform status")
}

fn cert_entries() -> Result<Vec<CertTableEntry>> {
let config = firmware()?
.snp_get_ext_config()
.map_err(|e| anyhow::anyhow!(format!("{:?}", e)))
.context("unable to retrieve SNP certificates")?;

match config.certs {
Some(c) => Ok(c),
None => Err(anyhow!("no SNP certificates found")),
}
}

fn main() -> Result<()> {
env_logger::init();

Expand All @@ -85,9 +87,10 @@ fn main() -> Result<()> {
SnpHostCmd::Export(export) => export::cmd(export),
SnpHostCmd::Import(import) => import::cmd(import),
SnpHostCmd::Ok => ok::cmd(snphost.quiet),
SnpHostCmd::Reset => reset::cmd(),
SnpHostCmd::Config(subcmd) => config::cmd(subcmd),
SnpHostCmd::Verify(verify) => verify::cmd(verify, snphost.quiet),
SnpHostCmd::Fetch(fetch) => fetch::cmd(fetch),
SnpHostCmd::Commit => commit::cmd(),
};

if !snphost.quiet {
Expand Down
Loading

0 comments on commit 6b908f7

Please sign in to comment.