diff --git a/src/report.rs b/src/report.rs index db41b38..2312c90 100644 --- a/src/report.rs +++ b/src/report.rs @@ -69,63 +69,106 @@ pub struct ReportArgs { help = "Provide file with data for attestation-report request. If provided with random flag, then the random data will be written in the provided path." )] pub request_file: PathBuf, + + #[structopt( + help = "Expect that the 64-byte report data will already be provided by the platform provider." + )] + pub platform: bool, } -// Request attestation report and write it into a file -pub fn get_report(args: ReportArgs, hv: bool) -> Result<()> { - let request_data = match args.random { - true => { - let request_buf = create_random_request(); - - // Overwrite data if file already exists - let request_file = if args.request_file.exists() { - std::fs::OpenOptions::new() - .write(true) - .truncate(true) - .open(args.request_file) - .context("Unable to overwrite request file contents")? - } else { - fs::File::create(args.request_file).context("Unable to create request file.")? - }; - write_hex(&mut BufWriter::new(request_file), &request_buf) - .context("Failed to write request data in request file")?; - request_buf +impl ReportArgs { + pub fn verify(&self, hyperv: bool) -> Result<()> { + if self.random && self.platform { + return Err(anyhow!( + "--random and --platform both enabled (not allowed). Consult man page." + )); } - false => { - let mut request_file = - File::open(args.request_file).context("Could not open the report request file.")?; - let mut request_buf: [u8; 64] = [0; 64]; - request_file - .read(&mut request_buf) - .context("Could not read report request file.")?; - request_buf + + if self.random && hv { + return Err(anyhow!( + "--random enabled yet Hyper-V guest detected (not allowed). Consult man page." + )); } - }; - // Get attestation report - let att_report = if hv { - hyperv::report::get(args.vmpl.unwrap_or(0))? + if self.platform && !hv { + return Err(anyhow!("--platform enabled yet Hyper-V guest not detected (not allowed). Consult man page.")); + } + + Ok(()) + } +} + +// Request attestation report and write it into a file +pub fn get_report(args: ReportArgs, hv: bool) -> Result<()> { + args.verify(hv)?; + + let data: Option<[u8; 64]> = if args.random { + Some(create_random_request()) + } else if args.platform { + None } else { - let mut sev_fw: Firmware = - Firmware::open().context("failed to open SEV firmware device.")?; - sev_fw - .get_report(None, Some(request_data), args.vmpl) - .context("Failed to get report.")? + /* + * Read from the request file. + */ + let mut bytes = [0u8; 64]; + let mut file = File::open(request_file)?; + file.read_exact(&mut bytes, 64); + + Some(bytes) }; - // Write attestation report into desired file - let mut attestation_file = if args.att_report_path.exists() { - std::fs::OpenOptions::new() - .write(true) - .truncate(true) - .open(args.att_report_path) - .context("Unable to overwrite attestation report file contents")? + let report = if hv { + hyperv::report::get(args.vmpl.unwrap_or(0))? } else { - fs::File::create(args.att_report_path) - .context("Unable to create attestation report file contents")? + let mut fw = Firmware::open().context("unable to open /dev/sev")?; + fw.get_report(None, data, args.vmpl) + .context("unable to fetch attestation report")? }; - bincode::serialize_into(&mut attestation_file, &att_report) - .context("Could not serialize attestation report into file.")?; + + /* + * Serialize and write attestation report. + */ + let mut file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(args.att_report_path)?; + + write!(&mut file, report).context(format!( + "unable to write attestation report to {}", + args.att_report_path.display() + ))?; + + /* + * Write reports report data (only for --random or --platform). + */ + if args.random { + reqdata_write(args.request_file, "random", &report) + .context("unable to write random request data")?; + } else if args.platform { + reqdata_write(args.request_file, "platform", &report) + .context("unable to write platform request data")?; + } Ok(()) } + +fn reqdata_write(from_args: Option, id: str, report: &AttestationReport) -> Result<()> { + let name = match from_args { + Some(path) => path, + None => { + let mut path = PathBuf::new(); + path.push(format!("{}-request-file.txt", id)); + + path + } + }; + + let mut file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(); + + write!(&mut file, report.report_data) +}