Skip to content
Open
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
5 changes: 3 additions & 2 deletions crates/attestation-provider-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ async fn main() -> anyhow::Result<()> {
None => MeasurementPolicy::accept_anything(),
};

let attestation_verifier =
AttestationVerifier::new(measurement_policy, None, cli.log_dcap_quote, false);
let attestation_verifier = AttestationVerifier::builder(measurement_policy)
.with_dump_dcap_quotes(cli.log_dcap_quote)
.build();

let attestation_message =
attestation_provider_client(server_addr, attestation_verifier).await?;
Expand Down
2 changes: 1 addition & 1 deletion crates/attestation/src/gcp/provenance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub enum GcpProvenanceError {
#[cfg(test)]
mod tests {
use std::{
io::{Read as _, Write as _},
io::Write as _,
net::SocketAddr,
sync::mpsc,
thread,
Expand Down
124 changes: 86 additions & 38 deletions crates/attestation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,69 +338,114 @@ impl AttestationGenerator {
}
}

/// How the verifier obtains DCAP collateral
#[derive(Clone, Debug)]
pub enum PccsMode {
/// No internal collateral cache. Collateral is always fetched from
/// remote source.
None,
/// Internal cache pre-filled with all available collateral at build
/// time.
Prewarmed,
/// Internal cache that starts empty and fetches on demand.
Lazy,
}

/// Allows remote attestations to be verified
#[derive(Clone, Debug)]
pub struct AttestationVerifier {
/// The measurement policy with accepted values and attestation types
pub measurement_policy: MeasurementPolicy,
/// If this is empty, anything will be accepted - but measurements are
/// always injected into HTTP headers, so that they can be verified
/// upstream A PCCS service to use - defaults to Intel PCS
pub pccs_url: Option<String>,
measurement_policy: MeasurementPolicy,
/// Whether to write quotes to files on disk
pub dump_dcap_quotes: bool,
dump_dcap_quotes: bool,
/// Whether to override outdated TCB when on Azure
///
/// This provides a workaround for a known outdated FMSPC used by Azure
pub override_azure_outdated_tcb: bool,
#[cfg_attr(not(feature = "azure-verifier"), allow(dead_code))]
override_azure_outdated_tcb: bool,
Comment on lines +364 to +365

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#[cfg_attr(not(feature = "azure-verifier"), allow(dead_code))]
override_azure_outdated_tcb: bool,
override_azure_outdated_tcb: bool,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think you meant to remove this?

/// Internal cache for collateral
pub internal_pccs: Option<Pccs>,
internal_pccs: Option<Pccs>,
/// Cached GCP firmware blobs indexed by MRTD
known_gcp_firmware: GcpFirmwareCache,
/// Cached PPIDs that have a valid GCP host-registry document
gcp_provenance_checker: GcpProvenanceChecker,
}

impl AttestationVerifier {
fn build(
measurement_policy: MeasurementPolicy,
pccs_url: Option<String>,
dump_dcap_quotes: bool,
override_azure_outdated_tcb: bool,
known_gcp_firmware: GcpFirmwareCache,
) -> Self {
Self {
measurement_policy,
pccs_url: pccs_url.clone(),
dump_dcap_quotes,
override_azure_outdated_tcb,
internal_pccs: Some(Pccs::new(pccs_url)),
known_gcp_firmware,
/// Options used to construct an [AttestationVerifier]
pub struct AttestationVerifierBuilder {
/// The measurement policy with accepted values and attestation types
measurement_policy: MeasurementPolicy,
/// Internal PCCS setting
pccs_mode: PccsMode,
/// A PCCS service to use - defaults to Intel PCS
pccs_url: Option<String>,
dump_dcap_quotes: bool,
/// Whether to override outdated TCB when on Azure
override_azure_outdated_tcb: bool,
}

impl AttestationVerifierBuilder {
pub fn build(self) -> AttestationVerifier {
let internal_pccs = match self.pccs_mode {
PccsMode::None => None,
PccsMode::Prewarmed => Some(Pccs::new(self.pccs_url)),
PccsMode::Lazy => Some(Pccs::new_without_prewarm(self.pccs_url)),
};

AttestationVerifier {
measurement_policy: self.measurement_policy,
dump_dcap_quotes: self.dump_dcap_quotes,
override_azure_outdated_tcb: self.override_azure_outdated_tcb,
internal_pccs,
known_gcp_firmware: GcpFirmwareCache::new(),
gcp_provenance_checker: GcpProvenanceChecker::new(),
}
}

pub fn new(
measurement_policy: MeasurementPolicy,
pccs_url: Option<String>,
dump_dcap_quotes: bool,
override_azure_outdated_tcb: bool,
) -> Self {
Self::build(
/// Whether to write quotes to files on disk
pub fn with_dump_dcap_quotes(mut self, dump_dcap_quotes: bool) -> Self {
self.dump_dcap_quotes = dump_dcap_quotes;
self
}

/// Whether to override outdated TCB when on Azure
///
/// This provides a workaround for a known outdated FMSPC used by Azure
/// When `azure-verifier` is disabled, this option has no effect because
/// Azure attestations are not supported.
pub fn with_override_azure_outdated_tcb(mut self, override_azure_outdated_tcb: bool) -> Self {
self.override_azure_outdated_tcb = override_azure_outdated_tcb;
self
}

pub fn with_pccs_mode(mut self, pccs_mode: PccsMode) -> Self {
self.pccs_mode = pccs_mode;
self
}

/// Set the URL used by internal PCCS
pub fn with_pccs_url(mut self, pccs_url: String) -> Self {
self.pccs_url = Some(pccs_url);
self
}
}

impl AttestationVerifier {
pub fn builder(measurement_policy: MeasurementPolicy) -> AttestationVerifierBuilder {
AttestationVerifierBuilder {
measurement_policy,
pccs_url,
dump_dcap_quotes,
override_azure_outdated_tcb,
gcp::GcpFirmwareCache::new(),
)
pccs_mode: PccsMode::None,
pccs_url: None,
dump_dcap_quotes: false,
override_azure_outdated_tcb: false,
}
}

/// Create an [AttestationVerifier] which will only allow no attestation
/// and will reject if one is given
pub fn expect_none() -> Self {
Self {
measurement_policy: MeasurementPolicy::expect_none(),
pccs_url: None,
dump_dcap_quotes: false,
override_azure_outdated_tcb: false,
internal_pccs: None,
Expand All @@ -414,7 +459,6 @@ impl AttestationVerifier {
pub fn mock() -> Self {
Self {
measurement_policy: MeasurementPolicy::mock(),
pccs_url: None,
dump_dcap_quotes: false,
override_azure_outdated_tcb: false,
internal_pccs: None,
Expand All @@ -428,7 +472,6 @@ impl AttestationVerifier {
pub fn mock_with_pccs(pccs_url: String) -> Self {
Self {
measurement_policy: MeasurementPolicy::mock(),
pccs_url: None,
dump_dcap_quotes: false,
override_azure_outdated_tcb: false,
internal_pccs: Some(Pccs::new(Some(pccs_url))),
Expand Down Expand Up @@ -619,6 +662,11 @@ impl AttestationVerifier {
pub fn has_remote_attestation(&self) -> bool {
self.measurement_policy.has_remote_attestation()
}

/// Returns the measurement policy used
pub fn measurement_policy(&self) -> &MeasurementPolicy {
&self.measurement_policy
}
}

/// Write attestation data to a log file
Expand Down
9 changes: 3 additions & 6 deletions crates/attested-tls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,9 +1104,7 @@ mod tests {

let mock_pcs_server = spawn_mock_pcs_server(MockPcsConfig::default()).await.unwrap();
let verifier = AttestationVerifier::mock_with_pccs(mock_pcs_server.base_url.clone());
if let Some(ref pccs) = verifier.internal_pccs {
pccs.ready().await.unwrap();
}
verifier.ready().await.unwrap();

let mut builder =
AttestedCertificateVerifier::build(verifier).with_crypto_provider(provider);
Expand Down Expand Up @@ -1559,9 +1557,8 @@ mod tests {
.unwrap();
let mock_pcs_server = spawn_mock_pcs_server(MockPcsConfig::default()).await.unwrap();
let verifier = AttestationVerifier::mock_with_pccs(mock_pcs_server.base_url.clone());
if let Some(ref pccs) = verifier.internal_pccs {
pccs.ready().await.unwrap();
}
verifier.ready().await.unwrap();

let verifier = AttestedCertificateVerifier::build(verifier)
.with_crypto_provider(provider)
.with_allowed_leaf_cert_pubkey(&key_pair.public_key_der())
Expand Down
5 changes: 2 additions & 3 deletions crates/attested-tls/tests/nested_tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,8 @@ async fn attested_client_config(provider: Arc<CryptoProvider>) -> ClientConfig {

let mock_pcs_server = spawn_mock_pcs_server(MockPcsConfig::default()).await.unwrap();
let verifier = AttestationVerifier::mock_with_pccs(mock_pcs_server.base_url.clone());
if let Some(ref pccs) = verifier.internal_pccs {
pccs.ready().await.unwrap();
}
verifier.ready().await.unwrap();

let verifier = AttestedCertificateVerifier::build(verifier)
.with_crypto_provider(provider.clone())
.finish()
Expand Down
Loading