sev-snp-utils

AMD SEV-SNP rust utils and primitives.

Testing

Instead of cargo test, run:

shell make test

Environment

| Variable | Default | Description | |----------------------------|--------------------|-----------------------------------------------| | SEVSNPCACHEPATH | /var/cache/sev-snp | Path to store downloaded certs. | | SEVSNPCACHEENTRIES_VCEK | 100 | Max cache entries for VCEK certs (in-memory). |

Attestation

Report

Request

To request a report from a SEV-SNP capable CPU (the same functionality as sev-guest-get-report):

```rust use sevsnputils::{AttestationReport, Requester};

fn main() { let report = AttestationReport::request() .expect("failed to request guest report");

println!("version: {:?}", report.version);

// Or raw bytes
let report_bytes = AttestationReport::request_raw()
    .expect("failed to request guest report");

println!("bytes len: {:?}", report_bytes.len());

} ```

Parsing

Parse a guest_report.bin file from sev-guest-get-report (or one saved from AttestationReport::request_raw()):

```rust use sevsnputils::AttestationReport;

fn main() { let report = AttestationReport::fromfile("./guestreport.bin") .expect("failed to parse guest report");

println!("version: {:?}", report.version);
println!("guest_svn: {:?}", report.guest_svn);
println!("policy: {:?}", report.policy);
println!("platform_version: {:?}", report.platform_version.raw_decimal());
println!("measurement: {}", report.measurement_hex());
println!("report data: {}", report.report_data_hex());
println!("id key digest: {}", report.id_key_digest_hex());
println!("author key digest: {}", report.author_key_digest_hex());
println!("chip id: {}", report.chip_id_hex());
println!("hash: {}", report.sha384_hex());
println!("signature:");
println!("  r: {}", report.signature.r_hex());
println!("  s: {}", report.signature.s_hex());

} ```

Verification

The verification process:

Verify a guest_report.bin file:

```rust use sevsnputils::{AttestationReport, Verification, Policy};

async fn verifyguest() { let report = AttestationReport::fromfile("./guest_report.bin") .expect("failed to parse guest report");

let res = report.verify(Some(Policy::permissive())).await
    .expect("failed to call verify");

if !res {
    panic!("verification failed");
}

} ```

You may also use Policy::strict() or make your own policy:

rust let policy = Policy::new( true, // require_no_debug true, // require_no_ma true, // require_no_smt true, // require_id_key true // require_author_key );

Certs

You may also obtain the certificates to work with them directly:

```rust use sevsnputils::{ AttestationReport, KdsCertificates, CertFormat, getkdsarkaskcertsbytes, getkdsarkaskcerts, getkdsarkaskcertsandvalidate, validatearkaskvcekcerts, PRODUCTNAME_MILAN };

async fn getcerts() { let report = AttestationReport::fromfile("./guest_report.bin") .expect("failed to parse guest report");

// VCEK

// Raw bytes as PEM or DER (cached only on disk)
let pem_bytes = report.get_kds_vcek_cert_bytes(CertFormat::PEM).await
    .expect("failed to get VCEK PEM");

let der_bytes = report.get_kds_vcek_cert_bytes(CertFormat::DER).await
    .expect("failed to get VCEK DER");

// X509 (cached in-memory, prefer this method)
let cert = report.get_kds_vcek_cert().await
    .expect("failed to get VCEK cert");

// ARK & ASK

// Raw bytes as PEM or DER (cached only on disk)
let (ark_pem, ask_pem) = get_kds_ark_ask_certs_bytes(PRODUCT_NAME_MILAN, CertFormat::PEM).await
    .expect("failed to get ARK/ASK PEMs");

// X509 (cached in-memory, prefer this method)
let (ark_cert, ask_cert) = get_kds_ark_ask_certs(PRODUCT_NAME_MILAN).await
    .expect("failed to get ARK/ASK certs");

// X509 validated (cached in-memory, prefer this method)
let (ark_cert, ask_cert) = get_kds_ark_ask_certs_and_validate(PRODUCT_NAME_MILAN).await
    .expect("failed to get ARK/ASK certs");

// Validate
validate_ark_ask_vcek_certs(&ark_cert, &ask_cert, Some(&cert))
    .expect("failed to validate certs");

} ```