Skip to content

Commit

Permalink
Extract stage1 attestation logic so it can be used for integration tests
Browse files Browse the repository at this point in the history
Change-Id: If4bf0e66afbb508b9bbe7fcaf47f768673baa28c
  • Loading branch information
jul-sh committed Sep 19, 2024
1 parent 3c6463c commit 51db5a1
Show file tree
Hide file tree
Showing 11 changed files with 168 additions and 72 deletions.
21 changes: 17 additions & 4 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ members = [
"oak_containers/orchestrator",
"oak_containers_sdk",
"oak_containers/stage1",
"oak_containers/stage1_dice",
"oak_containers/syslogd",
"oak_core",
"oak_crypto",
Expand Down Expand Up @@ -138,6 +139,7 @@ oak_restricted_kernel_orchestrator = { path = "./oak_restricted_kernel_orchestra
oak_session = { path = "./oak_session" }
oak_sev_guest = { path = "./oak_sev_guest", default-features = false }
oak_sev_snp_attestation_report = { path = "./oak_sev_snp_attestation_report" }
oak_containers_stage1_dice = { path = "./oak_containers/stage1_dice" }
oak_stage0_dice = { path = "./stage0_dice" }
oak_simple_io = { path = "./oak_simple_io" }
oak_tdx_guest = { path = "./oak_tdx_guest" }
Expand Down
5 changes: 1 addition & 4 deletions oak_containers/stage1/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,21 @@ oak_grpc_utils = { workspace = true }

[dependencies]
anyhow = "*"
ciborium = { version = "*", default-features = false }
clap = { version = "*", features = ["derive"] }
coset = { version = "*", features = ["std"] }
futures-util = "*"
oak_attestation = { workspace = true }
oak_crypto = { workspace = true }
oak_dice = { workspace = true }
oak_proto_rust = { workspace = true }
oak_grpc = { workspace = true }
oak_containers_stage1_dice = { workspace = true }
nix = { version = "0.27.1", features = ["mman"] }
p256 = { version = "*" }
prost = { workspace = true }
prost-types = "*"
rand_core = { version = "*", default-features = false, features = [
"getrandom",
] }
rtnetlink = "*"
sha2 = { version = "*", default-features = false }
tar = "*"
tokio = { version = "*", features = [
"rt-multi-thread",
Expand Down
52 changes: 4 additions & 48 deletions oak_containers/stage1/src/dice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,9 @@ use core::ops::RangeBounds;
use std::fs::{read_dir, read_to_string, OpenOptions};

use anyhow::Context;
use ciborium::Value;
use coset::cwt::ClaimName;
use nix::sys::mman::{mmap, munmap, MapFlags, ProtFlags};
use oak_attestation::dice::{stage0_dice_data_and_event_log_to_proto, DiceAttester};
use oak_dice::{
cert::{LAYER_2_CODE_MEASUREMENT_ID, SHA2_256_ID, SYSTEM_IMAGE_LAYER_ID},
evidence::STAGE0_MAGIC,
};
use oak_proto_rust::oak::{
attestation::v1::{DiceData, EventLog},
RawDigest,
};
use oak_dice::evidence::STAGE0_MAGIC;
use oak_proto_rust::oak::attestation::v1::EventLog;
use prost::Message;
use x86_64::PhysAddr;
use zerocopy::FromBytes;
Expand All @@ -49,39 +40,6 @@ const MEMMAP_PATH: &str = "/sys/firmware/memmap";
/// The path for reading the physical memory from the mem device.
const PHYS_MEM_PATH: &str = "/dev/mem";

/// Returns the SHA2-256 digest of the system image bytes and the event
/// digest as vectors of additional CWT claims.
pub fn get_system_image_measurement_claims(
digest: &RawDigest,
event: oak_proto_rust::oak::attestation::v1::Event,
) -> oak_attestation::dice::LayerData {
let encoded_event = event.encode_to_vec();
let event_digest =
oak_attestation::dice::MeasureDigest::measure_digest(&encoded_event.as_slice());
oak_attestation::dice::LayerData {
additional_claims: vec![
(
ClaimName::PrivateUse(SYSTEM_IMAGE_LAYER_ID),
Value::Map(vec![(
Value::Integer(LAYER_2_CODE_MEASUREMENT_ID.into()),
Value::Map(vec![(
Value::Integer(SHA2_256_ID.into()),
Value::Bytes(digest.sha2_256.clone()),
)]),
)]),
),
(
ClaimName::PrivateUse(oak_dice::cert::EVENT_ID),
Value::Map(vec![(
Value::Integer(SHA2_256_ID.into()),
Value::Bytes(event_digest.sha2_256),
)]),
),
],
encoded_event,
}
}

#[derive(Debug)]
struct MemoryRange {
start: PhysAddr,
Expand Down Expand Up @@ -224,12 +182,10 @@ impl SensitiveDiceDataMemory {

/// Extracts the DICE evidence and ECA key from the Stage 0 DICE data
/// located at the given physical address.
pub fn read_into_attester(self) -> anyhow::Result<DiceAttester> {
pub fn read_into_attester(self) -> anyhow::Result<oak_attestation::dice::DiceAttester> {
let stage0_dice_data = self.read_stage0_dice_data()?;
let eventlog = self.read_eventlog()?;
let dice_data: DiceData =
stage0_dice_data_and_event_log_to_proto(stage0_dice_data, eventlog)?;
dice_data.try_into()
oak_containers_stage1_dice::stage0_dice_data_into_dice_attester(stage0_dice_data, eventlog)
}
}

Expand Down
18 changes: 3 additions & 15 deletions oak_containers/stage1/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ use nix::{
unistd::{chdir, chroot},
};
use oak_attestation::attester::Serializable;
use oak_proto_rust::oak::attestation::v1::{Event, SystemLayerData};
use prost::Message;
use tokio::process::Command;
use tonic::transport::Uri;
use x86_64::PhysAddr;
Expand Down Expand Up @@ -120,20 +118,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
buf
};

let system_image_digest = oak_attestation::dice::MeasureDigest::measure_digest(&buf.as_slice());
let event = Event {
tag: "stage1".to_string(),
event: Some(prost_types::Any {
type_url: "type.googleapis.com/oak.attestation.v1.SystemLayerData".to_string(),
value: SystemLayerData { system_image: Some(system_image_digest.clone()) }
.encode_to_vec(),
}),
};
let layer_data = dice::get_system_image_measurement_claims(&system_image_digest, event);

// For safety we generate the DICE data for the next layer before processing the
// compressed system image. This consumes the `Attester` which also clears
// the ECA private key provided by Stage 0.
// compressed system image. This consumes the `DiceBuilder` which also
// clears the ECA private key provided by Stage 0.
let layer_data = oak_containers_stage1_dice::get_layer_data(&buf);
attester.add_layer(layer_data)?;
let dice_data = attester.serialize();

Expand Down
40 changes: 40 additions & 0 deletions oak_containers/stage1_dice/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#
# Copyright 2024 The Project Oak Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

load("@rules_rust//rust:defs.bzl", "rust_library")

package(
default_visibility = ["//:internal"],
licenses = ["notice"],
)

rust_library(
name = "stage1_dice",
srcs = glob(
["src/**"],
),
crate_name = "oak_containers_stage1_dice",
deps = [
"//oak_attestation",
"//oak_dice",
"//oak_proto_rust",
"@oak_crates_index//:anyhow",
"@oak_crates_index//:ciborium",
"@oak_crates_index//:coset",
"@oak_crates_index//:prost",
"@oak_crates_index//:prost-types",
],
)
16 changes: 16 additions & 0 deletions oak_containers/stage1_dice/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "oak_containers_stage1_dice"
version = "0.1.0"
edition = "2021"
authors = ["Andri Saar <andrisaar@google.com>"]
license = "Apache-2.0"

[dependencies]
anyhow = "*"
ciborium = { version = "*", default-features = false }
coset = { version = "*", features = ["std"] }
oak_attestation = { workspace = true }
oak_dice = { workspace = true }
oak_proto_rust = { workspace = true }
prost = { workspace = true }
prost-types = "*"
72 changes: 72 additions & 0 deletions oak_containers/stage1_dice/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// Copyright 2023 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#![feature(iterator_try_collect)]
#![feature(never_type)]

use ciborium::Value;
use coset::cwt::ClaimName;
use oak_dice::cert::{LAYER_2_CODE_MEASUREMENT_ID, SHA2_256_ID, SYSTEM_IMAGE_LAYER_ID};
use oak_proto_rust::oak::{
attestation::v1::{DiceData, Event, SystemLayerData},
RawDigest,
};
use prost::Message;

pub fn stage0_dice_data_into_dice_attester(
stage0_dice_data: oak_dice::evidence::Stage0DiceData,
eventlog: oak_proto_rust::oak::attestation::v1::EventLog,
) -> anyhow::Result<oak_attestation::dice::DiceAttester> {
let dice_data: DiceData =
oak_attestation::dice::stage0_dice_data_and_event_log_to_proto(stage0_dice_data, eventlog)?;
dice_data.try_into()
}

pub fn get_layer_data(system_image: &[u8]) -> oak_attestation::dice::LayerData {
let digest = oak_attestation::dice::MeasureDigest::measure_digest(&system_image);
let event = Event {
tag: "stage1".to_string(),
event: Some(prost_types::Any {
type_url: "type.googleapis.com/oak.attestation.v1.SystemLayerData".to_string(),
value: SystemLayerData { system_image: Some(digest.clone()) }.encode_to_vec(),
}),
};
let encoded_event = event.encode_to_vec();
let event_digest =
oak_attestation::dice::MeasureDigest::measure_digest(&encoded_event.as_slice());
oak_attestation::dice::LayerData {
additional_claims: vec![
(
ClaimName::PrivateUse(SYSTEM_IMAGE_LAYER_ID),
Value::Map(vec![(
Value::Integer(LAYER_2_CODE_MEASUREMENT_ID.into()),
Value::Map(vec![(
Value::Integer(SHA2_256_ID.into()),
Value::Bytes(digest.sha2_256.clone()),
)]),
)]),
),
(
ClaimName::PrivateUse(oak_dice::cert::EVENT_ID),
Value::Map(vec![(
Value::Integer(SHA2_256_ID.into()),
Value::Bytes(event_digest.sha2_256),
)]),
),
],
encoded_event,
}
}
2 changes: 2 additions & 0 deletions oak_containers_sdk/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ rust_library(
"@oak_crates_index//:async-trait",
],
deps = [
"//oak_attestation",
"//oak_containers/stage1_dice",
"//oak_crypto",
"//oak_dice",
"//oak_proto_rust",
Expand Down
2 changes: 2 additions & 0 deletions oak_containers_sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ oak_grpc_utils = { workspace = true }
[dependencies]
anyhow = "*"
async-trait = { version = "*", default-features = false }
oak_attestation = { workspace = true }
oak_dice = { workspace = true }
oak_proto_rust = { workspace = true }
oak_grpc = { workspace = true }
oak_crypto = { workspace = true }
oak_stage0_dice = { workspace = true }
oak_containers_stage1_dice = { workspace = true }
prost = "*"
prost-types = "*"
tokio = { version = "*", features = ["rt-multi-thread", "macros", "sync"] }
Expand Down
10 changes: 9 additions & 1 deletion oak_containers_sdk/src/standalone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn standalone_endorsed_evidence_containing_only_public_keys(
) -> EndorsedEvidence {
// TODO: b/347970899 - Create mock events and dice data for the subsequent
// layers.
let (mut _mock_event_log, _mock_stage0_dice_data): (
let (mock_event_log, mock_stage0_dice_data): (
oak_proto_rust::oak::attestation::v1::EventLog,
oak_dice::evidence::Stage0DiceData,
) = {
Expand All @@ -65,6 +65,14 @@ pub fn standalone_endorsed_evidence_containing_only_public_keys(
);
(mock_event_log, stage0_dice_data)
};
let mut attester = oak_containers_stage1_dice::stage0_dice_data_into_dice_attester(
mock_stage0_dice_data,
mock_event_log,
)
.expect("failed to create dice attester");
let layer_data = oak_containers_stage1_dice::get_layer_data(&[]);
attester.add_layer(layer_data).expect("failred to add stage1 layer data");

EndorsedEvidence {
evidence: Some(Evidence {
// TODO: b/347970899 - Create something here that will be compatible with the
Expand Down

0 comments on commit 51db5a1

Please sign in to comment.