Skip to content

Commit 25fdba0

Browse files
committed
Make endorsements an optional argument for policies
This is needed for binaries that don't have corresponding endorsements and are purely verified by the policy. I.e. binaries that are not published into the transparency log like Confidential Borg binaries. Fixes: 369775157 Change-Id: Iebbd559ea799423bc082bffb6cbd088bd6cfb26d
1 parent 8d4254d commit 25fdba0

File tree

10 files changed

+72
-30
lines changed

10 files changed

+72
-30
lines changed

oak_attestation_verification/src/policy/application.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ impl ApplicationPolicy {
3939
}
4040
}
4141

42-
// We have to use [`Policy<[u8], Variant>`] instead of [`EventPolicy`], because
42+
// We have to use [`Policy<[u8]>`] instead of [`EventPolicy`], because
4343
// Rust doesn't yet support implementing trait aliases.
4444
// <https://github.com/rust-lang/rfcs/blob/master/text/1733-trait-alias.md>
45-
impl Policy<[u8], Variant> for ApplicationPolicy {
45+
impl Policy<[u8]> for ApplicationPolicy {
4646
fn verify(
4747
&self,
4848
encoded_event: &[u8],
@@ -53,12 +53,12 @@ impl Policy<[u8], Variant> for ApplicationPolicy {
5353
"type.googleapis.com/oak.attestation.v1.ApplicationLayerData",
5454
encoded_event,
5555
)?;
56-
let endorsement: ApplicationEndorsement =
56+
let endorsement: Option<ApplicationEndorsement> =
5757
encoded_endorsement.try_into().map_err(anyhow::Error::msg)?;
5858

5959
let expected_values = acquire_application_event_expected_values(
6060
milliseconds_since_epoch,
61-
Some(&endorsement),
61+
endorsement.as_ref(),
6262
&self.reference_values,
6363
)
6464
.context("couldn't verify application endorsements")?;

oak_attestation_verification/src/policy/binary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl BinaryPolicy {
3636
}
3737
}
3838

39-
impl Policy<[u8], Variant> for BinaryPolicy {
39+
impl Policy<[u8]> for BinaryPolicy {
4040
fn verify(
4141
&self,
4242
encoded_event: &[u8],

oak_attestation_verification/src/policy/container.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ impl ContainerPolicy {
4747
}
4848
}
4949

50-
// We have to use [`Policy<[u8], Variant>`] instead of [`EventPolicy`], because
50+
// We have to use [`Policy<[u8]>`] instead of [`EventPolicy`], because
5151
// Rust doesn't yet support implementing trait aliases.
5252
// <https://github.com/rust-lang/rfcs/blob/master/text/1733-trait-alias.md>
53-
impl Policy<[u8], Variant> for ContainerPolicy {
53+
impl Policy<[u8]> for ContainerPolicy {
5454
fn verify(
5555
&self,
5656
encoded_event: &[u8],
@@ -61,12 +61,12 @@ impl Policy<[u8], Variant> for ContainerPolicy {
6161
"type.googleapis.com/oak.attestation.v1.ContainerLayerData",
6262
encoded_event,
6363
)?;
64-
let endorsement: ContainerEndorsement =
64+
let endorsement: Option<ContainerEndorsement> =
6565
encoded_endorsement.try_into().map_err(anyhow::Error::msg)?;
6666

6767
let expected_values = acquire_container_event_expected_values(
6868
milliseconds_since_epoch,
69-
Some(&endorsement),
69+
endorsement.as_ref(),
7070
&self.reference_values,
7171
)
7272
.context("couldn't verify container endorsements")?;

oak_attestation_verification/src/policy/firmware.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@ impl FirmwarePolicy {
3636
}
3737
}
3838

39-
impl Policy<[u8], Variant> for FirmwarePolicy {
39+
impl Policy<[u8]> for FirmwarePolicy {
4040
fn verify(
4141
&self,
4242
firmware_measurement: &[u8],
4343
encoded_endorsement: &Variant,
4444
milliseconds_since_epoch: i64,
4545
) -> anyhow::Result<EventAttestationResults> {
4646
let initial_measurement = convert_amd_sev_snp_initial_measurement(firmware_measurement);
47-
let endorsement: FirmwareEndorsement =
47+
let endorsement: Option<FirmwareEndorsement> =
4848
encoded_endorsement.try_into().map_err(anyhow::Error::msg)?;
4949

5050
let expected_values = acquire_stage0_expected_values(
5151
milliseconds_since_epoch,
52-
Some(&endorsement),
52+
endorsement.as_ref(),
5353
&self.reference_values,
5454
)
5555
.context("getting stage0 values")?;

oak_attestation_verification/src/policy/kernel.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl KernelPolicy {
3939
}
4040
}
4141

42-
impl Policy<[u8], Variant> for KernelPolicy {
42+
impl Policy<[u8]> for KernelPolicy {
4343
fn verify(
4444
&self,
4545
encoded_event: &[u8],
@@ -51,12 +51,12 @@ impl Policy<[u8], Variant> for KernelPolicy {
5151
"type.googleapis.com/oak.attestation.v1.Stage0Measurements",
5252
encoded_event,
5353
)?);
54-
let endorsement: KernelEndorsement =
54+
let endorsement: Option<KernelEndorsement> =
5555
encoded_endorsement.try_into().map_err(anyhow::Error::msg)?;
5656

5757
let expected_values = acquire_kernel_event_expected_values(
5858
milliseconds_since_epoch,
59-
Some(&endorsement),
59+
endorsement.as_ref(),
6060
&self.reference_values,
6161
)
6262
.context("couldn't verify kernel endorsements")?;

oak_attestation_verification/src/policy/platform.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl AmdSevSnpPolicy {
4040
}
4141
}
4242

43-
impl Policy<AttestationReport, Variant> for AmdSevSnpPolicy {
43+
impl Policy<AttestationReport> for AmdSevSnpPolicy {
4444
fn verify(
4545
&self,
4646
attestation_report: &AttestationReport,

oak_attestation_verification/src/policy/system.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl SystemPolicy {
3838
}
3939
}
4040

41-
impl Policy<[u8], Variant> for SystemPolicy {
41+
impl Policy<[u8]> for SystemPolicy {
4242
fn verify(
4343
&self,
4444
encoded_event: &[u8],
@@ -49,12 +49,12 @@ impl Policy<[u8], Variant> for SystemPolicy {
4949
"type.googleapis.com/oak.attestation.v1.SystemLayerData",
5050
encoded_event,
5151
)?;
52-
let endorsement: SystemEndorsement =
52+
let endorsement: Option<SystemEndorsement> =
5353
encoded_endorsement.try_into().map_err(anyhow::Error::msg)?;
5454

5555
let expected_values = acquire_system_event_expected_values(
5656
milliseconds_since_epoch,
57-
Some(&endorsement),
57+
endorsement.as_ref(),
5858
&self.reference_values,
5959
)
6060
.context("couldn't verify system endorsement")?;

oak_attestation_verification/src/verifier.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -432,23 +432,34 @@ fn verify_event_log(
432432
policies: &[Box<dyn EventPolicy>],
433433
milliseconds_since_epoch: i64,
434434
) -> anyhow::Result<Vec<EventAttestationResults>> {
435-
if event_log.encoded_events.len() != event_endorsements.len() {
436-
anyhow::bail!(
437-
"event log length ({}) is not equal to the number of endorsements ({})",
438-
event_log.encoded_events.len(),
439-
event_endorsements.len()
440-
);
441-
}
442435
if policies.len() != event_log.encoded_events.len() {
443436
anyhow::bail!(
444437
"number of policies ({}) is not equal to the event log length ({})",
445438
policies.len(),
446439
event_log.encoded_events.len()
447440
);
448441
}
442+
if event_log.encoded_events.len() < event_endorsements.len() {
443+
anyhow::bail!(
444+
"event log length ({}) is smaller than the number of endorsements ({})",
445+
event_log.encoded_events.len(),
446+
event_endorsements.len()
447+
);
448+
}
449+
450+
// Pad `event_endorsements` with an empty [`Variant`] to the same length as the
451+
// event log.
452+
let empty_endorsement = Variant::default();
453+
let mut padded_event_endorsements: Vec<&Variant> = event_endorsements.iter().collect();
454+
if event_log.encoded_events.len() > event_endorsements.len() {
455+
padded_event_endorsements.extend(
456+
core::iter::repeat(&empty_endorsement)
457+
.take(event_log.encoded_events.len() - event_endorsements.len()),
458+
);
459+
}
449460

450461
let verification_iterator =
451-
izip!(policies.iter(), event_log.encoded_events.iter(), event_endorsements.iter());
462+
izip!(policies.iter(), event_log.encoded_events.iter(), padded_event_endorsements.iter());
452463
let event_attestation_results = verification_iterator
453464
.map(|(event_policy, event, event_endorsement)| {
454465
event_policy.verify(event, event_endorsement, milliseconds_since_epoch).unwrap_or(

oak_attestation_verification_types/src/policy.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ use oak_proto_rust::oak::{attestation::v1::EventAttestationResults, Variant};
2222
/// Verification Policy correspond to the "Appraisal Policy for Evidence"
2323
/// provided by the RATS standard.
2424
/// <https://datatracker.ietf.org/doc/html/rfc9334#section-8.5>
25-
pub trait Policy<V: ?Sized, N: ?Sized>: Send + Sync {
25+
pub trait Policy<V: ?Sized>: Send + Sync {
2626
fn verify(
2727
&self,
2828
evidence: &V,
29-
endorsement: &N,
29+
endorsement: &Variant,
3030
milliseconds_since_epoch: i64,
3131
) -> anyhow::Result<EventAttestationResults>;
3232
}
3333

3434
/// Verification Policy that takes an encoded Event and an encoded Event
3535
/// Endorsement and performs attestation verification for this specific Event.
36-
pub trait EventPolicy = Policy<[u8], Variant>;
36+
pub trait EventPolicy = Policy<[u8]>;

oak_proto_rust/src/variant.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ use crate::oak::{
2323
Variant,
2424
};
2525

26+
impl Variant {
27+
pub fn is_empty(&self) -> bool {
28+
self.id.is_empty()
29+
}
30+
}
31+
32+
impl From<Option<Variant>> for Variant {
33+
fn from(value: Option<Variant>) -> Self {
34+
value.unwrap_or_default()
35+
}
36+
}
37+
2638
/// A random ID for each endorsement protocol buffer type that appears as ID
2739
/// in the oak::Variant encoding.
2840
const AMD_SEV_SNP_PLATFORM_ENDORSEMENT_ID: [u8; 16] =
@@ -88,6 +100,25 @@ impl TryFrom<&Variant> for ApplicationEndorsement {
88100
}
89101
}
90102

103+
macro_rules! impl_try_from_variant_to_option {
104+
($value_type:ty) => {
105+
impl TryFrom<&Variant> for Option<$value_type> {
106+
type Error = &'static str;
107+
fn try_from(value: &Variant) -> Result<Self, Self::Error> {
108+
let result = if !value.is_empty() { Some(value.try_into()?) } else { None };
109+
Ok(result)
110+
}
111+
}
112+
};
113+
}
114+
115+
impl_try_from_variant_to_option!(AmdSevSnpEndorsement);
116+
impl_try_from_variant_to_option!(FirmwareEndorsement);
117+
impl_try_from_variant_to_option!(KernelEndorsement);
118+
impl_try_from_variant_to_option!(SystemEndorsement);
119+
impl_try_from_variant_to_option!(ContainerEndorsement);
120+
impl_try_from_variant_to_option!(ApplicationEndorsement);
121+
91122
impl From<AmdSevSnpEndorsement> for Variant {
92123
fn from(value: AmdSevSnpEndorsement) -> Self {
93124
Variant { id: AMD_SEV_SNP_PLATFORM_ENDORSEMENT_ID.to_vec(), value: value.encode_to_vec() }

0 commit comments

Comments
 (0)