use super::*;
use sev::firmware::guest::{DerivedKey, Firmware, GuestFieldSelect};
use std::io::Read;
use std::{fs, path::PathBuf};
#[derive(Parser)]
pub struct KeyArgs {
#[arg(value_name = "key-path", required = true)]
pub key_path: PathBuf,
#[arg(value_name = "root-key-select", required = true, ignore_case = true)]
pub root_key_select: String,
#[arg(short, long, value_name = "vmpl", default_value = "1")]
pub vmpl: u32,
#[arg(short, long = "guest_field_select", value_name = "gfs", value_parser = clparser::parse_int_auto_radix::<u64>, default_value = "0")]
pub gfs: u64,
#[arg(short = 's', long = "guest_svn", value_name = "gsvn", value_parser = clparser::parse_int_auto_radix::<u32>, default_value = "0")]
pub gsvn: u32,
#[arg(short, long = "tcb_version", value_name = "tcbv", value_parser = clparser::parse_int_auto_radix::<u64>, default_value = "0")]
pub tcbv: u64,
#[arg(short, long = "launch_mit_vector", value_name = "lmv", value_parser = clparser::parse_int_auto_radix::<u64>)]
pub lmv: Option<u64>,
}
pub fn get_derived_key(args: KeyArgs) -> Result<()> {
let root_key_select = match args.root_key_select.as_str() {
"vcek" => false,
"vmrk" => true,
_ => return Err(anyhow::anyhow!("Invalid input. Enter either vcek or vmrk")),
};
if args.vmpl > 3 {
return Err(anyhow::anyhow!(
"Invalid Virtual Machine Privilege Level. Must betwee"
));
}
if args.gfs > 0b1111111 {
return Err(anyhow::anyhow!("Invalid Guest Field Select option."));
}
let msg_ver = if args.lmv.is_some() { 2 } else { 1 };
let request = DerivedKey::new(
root_key_select,
GuestFieldSelect(args.gfs),
args.vmpl,
args.gsvn,
args.tcbv,
args.lmv,
);
let mut sev_fw = Firmware::open().context("failed to open SEV firmware device.")?;
let derived_key: [u8; 32] = sev_fw
.get_derived_key(Some(msg_ver), request)
.context("Failed to request derived key")?;
let key_path: PathBuf = args.key_path;
let mut key_file = if key_path.exists() {
std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(key_path)
.context("Unable to overwrite derived key file contents")?
} else {
fs::File::create(key_path).context("Unable to create derived key file contents")?
};
bincode::serialize_into(&mut key_file, &derived_key)
.context("Could not serialize derived key into file.")?;
Ok(())
}
pub fn read_key(key_path: PathBuf) -> Result<Vec<u8>, anyhow::Error> {
let mut key_file = fs::File::open(key_path)?;
let mut key = Vec::new();
key_file.read_to_end(&mut key)?;
Ok(key)
}