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
152 changes: 150 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ build = "build/main.rs"
test-data = []

[dependencies]
attest-data.git = "https://github.com/oxidecomputer/dice-util"
# these dependencies both come from the `dice-util` repo and should be pinned to the same git rev.
attest-data = { git = "https://github.com/oxidecomputer/dice-util", rev = "d7472bfa91aee859c3fe0bdc1dbb1e320285228e" }
dice-verifier = { git = "https://github.com/oxidecomputer/dice-util", rev = "d7472bfa91aee859c3fe0bdc1dbb1e320285228e", features = ["mock"] }

const-oid = { version = "0.9.5", features = ["db"] }
dice-verifier = { git = "https://github.com/oxidecomputer/dice-util", features = ["mock"] }
ed25519-dalek = { version = "2.1", default-features = false }
getrandom = { version = "0.3.4", features = ["std"] }
hex = "0.4.3"
Expand All @@ -32,3 +34,4 @@ anyhow.version = "1.0.100"

[dev-dependencies]
vm-attest = { path = ".", features = ["test-data"] }
tokio = { version = "1", features = ["full"] }
32 changes: 18 additions & 14 deletions src/rot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ pub enum VmInstanceRotError {
/// This type represents the `propolis` process that backs a VM. This type has
/// an interface similar to the `vm_attest::VmInstanceAttester` but we require
pub struct VmInstanceRot {
oxattest_mock: Box<dyn OxAttest + Send>,
oxattest_mock: Box<dyn OxAttest + Send + Sync>,
}

impl VmInstanceRot {
/// Create an instance of the `VmInstanceRot` type. A `Box`ed type
/// implementing the dice_verifier::Attest is provided to the constructor.
/// This type connects the `VmInstanceRot` to the oxide platform rot, or
/// possibly a mock implementation thereof.
pub fn new(oxattest_mock: Box<dyn OxAttest + Send>) -> Self {
pub fn new(oxattest_mock: Box<dyn OxAttest + Send + Sync>) -> Self {
Self { oxattest_mock }
}

Expand All @@ -57,7 +57,7 @@ impl VmInstanceRot {
/// attestation from the platform rot is then combined with all data
/// required to verify it in a `VmInstanceAttestation` and returned to the
/// caller.
pub fn attest(
pub async fn attest(
&self,
instance_conf: &VmInstanceConf,
qualifying_data: &QualifyingData,
Expand All @@ -74,7 +74,7 @@ impl VmInstanceRot {
// smuggle the updated qualifying data through the `Nonce`
// type down to the Oxide Platform RoT
let nonce = Nonce::N32(attest_data::Array(msg.finalize().into()));
let attest = self.oxattest_mock.attest(&nonce)?;
let attest = self.oxattest_mock.attest(&nonce).await?;

// serialize the attestation back to hubpack
// TODO: this should be a JSON encoding
Expand All @@ -84,7 +84,7 @@ impl VmInstanceRot {
attestation.truncate(len);

// collect logs
let oxide_log = self.oxattest_mock.get_measurement_log()?;
let oxide_log = self.oxattest_mock.get_measurement_log().await?;

let mut data = vec![0u8; Log::MAX_SIZE];
let len = hubpack::serialize(&mut data, &oxide_log)
Expand All @@ -101,7 +101,7 @@ impl VmInstanceRot {
});

// get cert chain
let ox_cert_chain = self.oxattest_mock.get_certificates()?;
let ox_cert_chain = self.oxattest_mock.get_certificates().await?;

let mut cert_chain = Vec::new();
for cert in ox_cert_chain {
Expand Down Expand Up @@ -174,25 +174,27 @@ mod test {
QualifyingData::from(Into::<[u8; 32]>::into(digest.finalize()))
}

#[test]
fn attest() {
#[tokio::test]
async fn attest() {
let (attest, instance_cfg) = setup();
let qualifying_data = mock_qualifying_data();

let _ = attest
.attest(&instance_cfg, &qualifying_data)
.await
.expect("VmInstanceRotMock attest");
}

#[test]
fn verify_cert_chain() {
#[tokio::test]
async fn verify_cert_chain() {
use std::fs;

let (attest, instance_cfg) = setup();
let qualifying_data = mock_qualifying_data();

let plat_attest = attest
.attest(&instance_cfg, &qualifying_data)
.await
.expect("VmInstanceRotMock attest");

let root_cert = fs::read(config::PKI_ROOT).unwrap_or_else(|e| {
Expand All @@ -218,14 +220,15 @@ mod test {
assert_eq!(&root_cert[0], verified_root);
}

#[test]
fn verify_attestation() {
#[tokio::test]
async fn verify_attestation() {
let (attest, instance_cfg) = setup();
// qualifying data from VM to VmInstanceRot
let vm_qualifying_data = mock_qualifying_data();

let plat_attest = attest
.attest(&instance_cfg, &vm_qualifying_data)
.await
.expect("VmInstanceRotMock get_cert_chain");

// Reconstruct the 32 bytes passed from `VmInstanceAttestMock` down to
Expand Down Expand Up @@ -284,8 +287,8 @@ mod test {
assert!(result.is_ok());
}

#[test]
fn appraise_log() {
#[tokio::test]
async fn appraise_log() {
use dice_verifier::{MeasurementSet, ReferenceMeasurements};
use rats_corim::Corim;

Expand All @@ -299,6 +302,7 @@ mod test {

let plat_attest = attest
.attest(&instance_cfg, &qualifying_data)
.await
.expect("VmInstanceRotMock get_cert_chain");

// construct a `VmInstanceConf` from test data
Expand Down
Loading