Skip to content

Commit

Permalink
report: Add --platform flag for Hyper-V
Browse files Browse the repository at this point in the history
Currently, with Hyper-V guests, the report_data of an attestation report
is generated beforehand by the platform. This indicates that a user
cannot write some optional data to be included in the report. With
--platform enabled, the pre-generated platform data will be written to
the file pointed to by $REQUEST_PATH (or "platform-request-file.txt" if
no $REQUEST_PATH is given as input).

Signed-off-by: Tyler Fanelli <tfanelli@redhat.com>
  • Loading branch information
tylerfanelli committed Jul 31, 2023
1 parent c7ad0fe commit 9c36a17
Showing 1 changed file with 90 additions and 47 deletions.
137 changes: 90 additions & 47 deletions src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<PathBuf>, 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)
}

0 comments on commit 9c36a17

Please sign in to comment.