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
50 changes: 33 additions & 17 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = [".", "attestation-provider-server", "attested-tls"]
members = [".", "attestation-provider-server", "attested-tls", "attestation"]

[package]
name = "attested-tls-proxy"
Expand Down
59 changes: 59 additions & 0 deletions attestation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
[package]
name = "attestation"
version = "0.0.1"
edition = "2024"
license = "MIT"
description = "Attestation generation and verification, and measurement policy handling"
repository = "https://github.com/flashbots/attested-tls-proxy"
keywords = ["attestation", "CVM", "TDX"]

[dependencies]
tokio = { version = "1.48.0", features = ["fs"] }
tokio-rustls = { version = "0.26.4", default-features = false, features = [
"ring",
] }
x509-parser = "0.18.0"
thiserror = "2.0.17"
anyhow = "1.0.100"
pem-rfc7468 = { version = "0.7.0", features = ["std"] }
configfs-tsm = "0.0.2"
rand_core = { version = "0.6.4", features = ["getrandom"] }
dcap-qvl = { git = "https://github.com/flashbots/dcap-qvl.git", branch = "peg/azure-outdated-tcp-override", features = ["danger-allow-tcb-override"] }
hex = "0.4.3"
http = "1.3.1"
serde_json = "1.0.145"
serde = "1.0.228"
base64 = "0.22.1"
reqwest = { version = "0.12.23", default-features = false, features = [
"rustls-tls-webpki-roots-no-provider",
] }
tracing = "0.1.41"
parity-scale-codec = "3.7.5"
openssl = "0.10.75"
num-bigint = "0.4.6"
webpki = { package = "rustls-webpki", version = "0.103.8" }
time = "0.3.47"
once_cell = "1.21.3"

# Used for azure vTPM attestation support
az-tdx-vtpm = { version = "0.7.4", optional = true }
tss-esapi = { version = "7.6.0", optional = true }

# Used by test helpers
tdx-quote = { version = "0.0.5", features = ["mock"], optional = true }

[dev-dependencies]
tempfile = "3.23.0"
tdx-quote = { version = "0.0.5", features = ["mock"] }

[features]
default = []

# Adds support for Microsoft Azure attestation generation and verification
azure = ["tss-esapi", "az-tdx-vtpm"]

# Exposes helper functions for testing - do not enable in production as this allows dangerous configuration
test-helpers = []

# Allows mock quotes used in tests
mock = ["tdx-quote"]
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Generation and verification of AK certificates from the vTPM
use crate::attestation::azure::{MaaError, nv_index};
use crate::azure::{MaaError, nv_index};
use once_cell::sync::Lazy;
use std::time::Duration;
use tokio_rustls::rustls::pki_types::{CertificateDer, TrustAnchor, UnixTime};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
use x509_parser::prelude::*;

use crate::attestation::{
dcap::verify_dcap_attestation_with_given_timestamp, measurements::MultiMeasurements,
};
use crate::{dcap::verify_dcap_attestation_with_given_timestamp, measurements::MultiMeasurements};

/// The attestation evidence payload that gets sent over the channel
#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -339,12 +337,12 @@ pub enum MaaError {
#[error("HCL runtime claims user-data does not match expected report input data")]
ClaimsUserDataInputMismatch,
#[error("DCAP verification: {0}")]
DcapVerification(#[from] crate::attestation::dcap::DcapVerificationError),
DcapVerification(#[from] crate::dcap::DcapVerificationError),
}

#[cfg(test)]
mod tests {
use crate::attestation::measurements::MeasurementPolicy;
use crate::measurements::MeasurementPolicy;

use super::*;

Expand All @@ -363,7 +361,7 @@ mod tests {
#[tokio::test]
async fn test_decode_hcl() {
// From cvm-reverse-proxy/internal/attestation/azure/tdx/testdata/hclreport.bin
let hcl_bytes: &'static [u8] = include_bytes!("../../../test-assets/hclreport.bin");
let hcl_bytes: &'static [u8] = include_bytes!("../../test-assets/hclreport.bin");

let hcl_report = hcl::HclReport::new(hcl_bytes.to_vec()).unwrap();
let hcl_var_data = hcl_report.var_data();
Expand All @@ -382,7 +380,7 @@ mod tests {
#[tokio::test]
async fn test_verify() {
let attestation_bytes: &'static [u8] =
include_bytes!("../../../test-assets/azure-tdx-1764662251380464271");
include_bytes!("../../test-assets/azure-tdx-1764662251380464271");

// To avoid this test stopping working when the certificate is no longer valid we pass in a
// timestamp
Expand Down Expand Up @@ -411,7 +409,7 @@ mod tests {
.unwrap();

let collateral_bytes: &'static [u8] =
include_bytes!("../../../test-assets/azure-collateral02.json");
include_bytes!("../../test-assets/azure-collateral02.json");

let collateral = serde_json::from_slice(collateral_bytes).unwrap();

Expand All @@ -432,14 +430,14 @@ mod tests {
#[tokio::test]
async fn test_verify_fails_on_input_mismatch() {
let attestation_bytes: &'static [u8] =
include_bytes!("../../../test-assets/azure-tdx-1764662251380464271");
include_bytes!("../../test-assets/azure-tdx-1764662251380464271");
let now = 1771423480;

let mut expected_input_data = input_data_from_attestation(attestation_bytes);
expected_input_data[63] ^= 0x01;

let collateral_bytes: &'static [u8] =
include_bytes!("../../../test-assets/azure-collateral02.json");
include_bytes!("../../test-assets/azure-collateral02.json");
let collateral = serde_json::from_slice(collateral_bytes).unwrap();

let err = verify_azure_attestation_with_given_timestamp(
Expand Down
12 changes: 6 additions & 6 deletions attested-tls/src/attestation/dcap.rs → attestation/src/dcap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Data Center Attestation Primitives (DCAP) evidence generation and verification
use crate::attestation::{AttestationError, measurements::MultiMeasurements};
use crate::{AttestationError, measurements::MultiMeasurements};

use configfs_tsm::QuoteGenerationError;
use dcap_qvl::{
Expand Down Expand Up @@ -168,13 +168,13 @@ pub enum DcapVerificationError {

#[cfg(test)]
mod tests {
use crate::attestation::measurements::MeasurementPolicy;
use crate::measurements::MeasurementPolicy;

use super::*;
#[tokio::test]
async fn test_dcap_verify() {
let attestation_bytes: &'static [u8] =
include_bytes!("../../test-assets/dcap-tdx-1766059550570652607");
include_bytes!("../test-assets/dcap-tdx-1766059550570652607");

// To avoid this test stopping working when the certificate is no longer valid we pass in a
// timestamp
Expand All @@ -199,7 +199,7 @@ mod tests {
.unwrap();

let collateral_bytes: &'static [u8] =
include_bytes!("../../test-assets/dcap-quote-collateral-00.json");
include_bytes!("../test-assets/dcap-quote-collateral-00.json");

let collateral = serde_json::from_slice(collateral_bytes).unwrap();

Expand All @@ -226,14 +226,14 @@ mod tests {
#[tokio::test]
async fn test_dcap_verify_azure_override() {
let attestation_bytes: &'static [u8] =
include_bytes!("../../test-assets/azure_failed_dcap_quote_10.bin");
include_bytes!("../test-assets/azure_failed_dcap_quote_10.bin");

// To avoid this test stopping working when the certificate is no longer valid we pass in a
// timestamp
let now = 1771414156;

let collateral_bytes: &'static [u8] =
include_bytes!("../../test-assets/azure-collateral.json");
include_bytes!("../test-assets/azure-collateral.json");

let collateral = serde_json::from_slice(collateral_bytes).unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ pub mod azure;
pub mod dcap;
pub mod measurements;

#[cfg(any(test, feature = "test-helpers"))]
pub mod test_helpers;

use measurements::MultiMeasurements;
use parity_scale_codec::{Decode, Encode};
use serde::{Deserialize, Serialize};
Expand All @@ -16,7 +19,7 @@ use std::{

use thiserror::Error;

use crate::attestation::{dcap::DcapVerificationError, measurements::MeasurementPolicy};
use crate::{dcap::DcapVerificationError, measurements::MeasurementPolicy};

const GCP_METADATA_API: &str =
"http://metadata.google.internal/computeMetadata/v1/project/project-id";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Measurements and policy for enforcing them when validating a remote attestation
use crate::attestation::{AttestationError, AttestationType, dcap::DcapVerificationError};
use crate::{AttestationError, AttestationType, dcap::DcapVerificationError};
use std::{collections::HashMap, path::PathBuf};
use std::{fmt, fmt::Formatter};

Expand Down
13 changes: 13 additions & 0 deletions attestation/src/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::{MultiMeasurements, measurements::DcapMeasurementRegister};
use std::collections::HashMap;

/// All-zero measurment values used in some tests
pub fn mock_dcap_measurements() -> MultiMeasurements {
MultiMeasurements::Dcap(HashMap::from([
(DcapMeasurementRegister::MRTD, [0u8; 48]),
(DcapMeasurementRegister::RTMR0, [0u8; 48]),
(DcapMeasurementRegister::RTMR1, [0u8; 48]),
(DcapMeasurementRegister::RTMR2, [0u8; 48]),
(DcapMeasurementRegister::RTMR3, [0u8; 48]),
]))
}
30 changes: 5 additions & 25 deletions attested-tls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,11 @@ sha2 = "0.10.9"
x509-parser = "0.18.0"
thiserror = "2.0.17"
webpki-roots = "1.0.4"
anyhow = "1.0.100"
pem-rfc7468 = { version = "0.7.0", features = ["std"] }
configfs-tsm = "0.0.2"
rand_core = { version = "0.6.4", features = ["getrandom"] }
dcap-qvl = { git = "https://github.com/flashbots/dcap-qvl.git", branch = "peg/azure-outdated-tcp-override", features = ["danger-allow-tcb-override"] }
hex = "0.4.3"
http = "1.3.1"
serde_json = "1.0.145"
serde = "1.0.228"
base64 = "0.22.1"
reqwest = { version = "0.12.23", default-features = false, features = [
"rustls-tls-webpki-roots-no-provider",
] }
tracing = "0.1.41"
parity-scale-codec = "3.7.5"
openssl = "0.10.75"
num-bigint = "0.4.6"
webpki = { package = "rustls-webpki", version = "0.103.8" }
time = "0.3.47"
once_cell = "1.21.3"

# Used for azure vTPM attestation support
az-tdx-vtpm = { version = "0.7.4", optional = true }
tss-esapi = { version = "7.6.0", optional = true }
attestation = { path = "../attestation" }

# Used for websocket support
tokio-tungstenite = { version = "0.28.0", optional = true }
Expand All @@ -57,18 +38,17 @@ http-body-util = { version = "0.1.3", optional = true }

# Used by test helpers
rcgen = { version = "0.14.5", optional = true }
tdx-quote = { version = "0.0.5", features = ["mock"], optional = true }

[dev-dependencies]
rcgen = "0.14.5"
tempfile = "3.23.0"
tdx-quote = { version = "0.0.5", features = ["mock"] }
attestation = { path = "../attestation", features = ["test-helpers", "mock"] }

[features]
default = ["ws", "rpc"]

# Adds support for Microsoft Azure attestation generation and verification
azure = ["tss-esapi", "az-tdx-vtpm"]
azure = ["attestation/azure"]

# Adds websocket support
ws = ["tokio-tungstenite", "futures-util"]
Expand All @@ -87,6 +67,6 @@ rpc = [
]

# Exposes helper functions for testing - do not enable in production as this allows dangerous configuration
test-helpers = ["rcgen"]
test-helpers = ["rcgen", "attestation/test-helpers"]

mock = ["tdx-quote"]
mock = ["attestation/mock"]
Loading