Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ snpguest verify <SUBCOMMAND>

**Usage**
```bash
snpguest verify attestation $CERTS_DIR $ATT_REPORT_PATH [-t, --tcb] [-s, --signature]
snpguest verify attestation $CERTS_DIR $ATT_REPORT_PATH [-t, --tcb] [-s, --signature] [-m, --measurement] [-d, --host-data] [-r, --report-data]
```
**Arguments**

Expand All @@ -318,6 +318,9 @@ snpguest verify <SUBCOMMAND>

- `-t, --tcb`: Verify the Reported TCB section of the report only.
- `-s, --signature`: Verify the signature of the report only.
- `-m, --measurement`: Verify the measurement from the attestation report.
- `-d, --host-data`: Verify the host-data from the attestation report.
- `-r, --report-data`: Verify the report-data from the attestation report.

**Example**
```bash
Expand All @@ -327,6 +330,12 @@ snpguest verify <SUBCOMMAND>
snpguest verify attestation ./certs attestation-report.bin --tcb
# Verify Attestation Signature only
snpguest verify attestation ./certs attestation-report.bin --signature
# Verify Attestation Measurement only
snpguest verify attestation --measurement 0xf28aac58964258d8ae0b2e88a706fc7afd0bb524f6a291ac3eedeccb73f89d7cfcf2e4fb6045e7d5201e41d1726afa02 /home/amd/certs /home/amd/report.bin
# Verify Attestation host-data only
snpguest verify attestation --host-data 0x7e4a3f9c1b82a056d39f0d44e5c8a7b1f02394de6b58ac0d7e3c11af0042bd59 /home/amd/certs /home/amd/report.bin
# Verify Attestation report-data only
snpguest verify attestation --report-data 0x5482c1ffe29145d47cf678f7681e3b64a89909d6cf8ec0104cfacb0b0418f005f564ad14f5c1381c99b74903a780ea340e887c9b445e9c760bf0b74115b26d45 /home/amd/certs /home/amd/report.bin
```

### Global Options
Expand Down
13 changes: 13 additions & 0 deletions docs/snpguest.1.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -120,12 +120,25 @@ COMMANDS
An error will be raised if the attestation verification fails at any point.
The user can use the [-t, --tcb] flag to only validate the tcb contents of the report.
The user can use the [-s, --signature] flag to only validate the report signature.
The user can use the [-m, --measurement] flag to verify that the measurement in the attestation
report matches the expected measurement value (prefix with 0x for hex, without prefix it assumes
decimal values).
The user can use the [-d, --host-data] flag to verify that the host-data in the attestation
report matches the expected host-data value (prefix with 0x for hex, without prefix it assumes
decimal values).
The user can use the [-r, --report-data] flag to verify that the report-data in the attestation
report matches the expected report-data value (prefix with 0x for hex, without prefix it assumes
decimal values).
If the optional flags are not passed, just the signature will be verified.

options:
-h, --help show a help message
-p, --processor_model Specify the processor model to use for verification
-t, --tcb verify the tcb section of the report only
-s, --signature verify the signature of the report only
-m, --measurement provide an expected measurement to verify the measurement field in the attestation report
-d, --host-data provide the expected host-data to verify the host-data field in the attestation report
-r, --report-data provide the expected report-data to verify the report-data in the attestation report

*snpguest key*::
usage: snpguest key $KEY_PATH $ROOT_KEY_SELECT [-g, --guest_field_select] [-s, --guest_svn] [-t, --tcb_version] [-v, --vmpl]
Expand Down
99 changes: 98 additions & 1 deletion src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use openssl::{ecdsa::EcdsaSig, sha::Sha384};
use sev::certs::snp::Chain;
use sev::parser::ByteParser;

use hex::FromHex;

#[derive(Subcommand)]
pub enum VerifyCmd {
/// Verify the certificate chain.
Expand Down Expand Up @@ -201,6 +203,18 @@ mod attestation {
/// Run the Signature Verification Exclusively.
#[arg(short, long, conflicts_with = "tcb")]
pub signature: bool,

/// Optional measurement string (hex, 48 bytes / 96 chars)
#[arg(short, long, value_name = "measurement")]
pub measurement: Option<String>,

/// Optional host_data string (hex, 32 bytes / 64 chars)
#[arg(short = 'd', long, value_name = "host_data")]
pub host_data: Option<String>,

/// Optional report_data string (hex, 64 bytes / 128 chars)
#[arg(short, long, value_name = "report_data")]
pub report_data: Option<String>,
}

fn verify_attestation_signature(
Expand Down Expand Up @@ -418,7 +432,7 @@ mod attestation {
.context("Could not open attestation report")?
};

let proc_model = if let Some(proc_model) = args.processor_model {
let proc_model = if let Some(proc_model) = args.processor_model.clone() {
proc_model
} else {
let att_report = report::read_report(args.att_report_path.clone())
Expand Down Expand Up @@ -447,6 +461,89 @@ mod attestation {
verify_attestation_signature(vek, att_report, quiet)?;
}

// Verify optional fields if provided
if args.measurement.is_some() || args.host_data.is_some() || args.report_data.is_some() {
verify_report_fields(&args, &att_report, quiet)?;
}

Ok(())
}

fn decode_hex_or_decimal(input: &str) -> Result<Vec<u8>> {
// Look for "0x" at beginning. If it exists, treat as a hex.
if let Some(hex_str) = input.strip_prefix("0x") {
Ok(Vec::from_hex(hex_str)?)
} else {
Ok(input.as_bytes().to_vec())
}
}

fn verify_field(
field_name: &str,
expected: &[u8],
provided: &str,
expected_len: usize,
quiet: bool,
) -> Result<()> {
let actual = decode_hex_or_decimal(provided)?;

if actual.len() != expected_len {
return Err(anyhow::anyhow!(
"Expected {} characters for {}, got {}",
expected_len,
field_name,
actual.len()
));
}

if expected != actual.as_slice() {
return Err(anyhow::anyhow!(
"{} did not match:\n expected {}\n got {}",
field_name,
hex::encode(expected),
hex::encode(actual)
));
}
if !quiet {
println!("{} verified successfully.", field_name);
}

Ok(())
}

fn verify_report_fields(
args: &Args,
att_report: &AttestationReport,
quiet: bool,
) -> Result<()> {
if let Some(measure) = &args.measurement {
verify_field(
"Measurement",
att_report.measurement.as_slice(),
measure,
48,
quiet,
)?;
}
if let Some(host) = &args.host_data {
verify_field(
"Host Data",
att_report.host_data.as_slice(),
host,
32,
quiet,
)?;
}
if let Some(report) = &args.report_data {
verify_field(
"Report Data",
att_report.report_data.as_slice(),
report,
64,
quiet,
)?;
}

Ok(())
}

Expand Down