Skip to content

Commit 0655858

Browse files
authored
Merge pull request #148 from flashbots/peg/refactor-attestation-crate
Refactor attestation generation, verification and measurement logic to separate crate
2 parents 81e1acc + 1feece2 commit 0655858

22 files changed

Lines changed: 141 additions & 85 deletions

Cargo.lock

Lines changed: 33 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = [".", "attestation-provider-server", "attested-tls"]
2+
members = [".", "attestation-provider-server", "attested-tls", "attestation"]
33

44
[package]
55
name = "attested-tls-proxy"

attestation/Cargo.toml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
[package]
2+
name = "attestation"
3+
version = "0.0.1"
4+
edition = "2024"
5+
license = "MIT"
6+
description = "Attestation generation and verification, and measurement policy handling"
7+
repository = "https://github.com/flashbots/attested-tls-proxy"
8+
keywords = ["attestation", "CVM", "TDX"]
9+
10+
[dependencies]
11+
tokio = { version = "1.48.0", features = ["fs"] }
12+
tokio-rustls = { version = "0.26.4", default-features = false, features = [
13+
"ring",
14+
] }
15+
x509-parser = "0.18.0"
16+
thiserror = "2.0.17"
17+
anyhow = "1.0.100"
18+
pem-rfc7468 = { version = "0.7.0", features = ["std"] }
19+
configfs-tsm = "0.0.2"
20+
rand_core = { version = "0.6.4", features = ["getrandom"] }
21+
dcap-qvl = { git = "https://github.com/flashbots/dcap-qvl.git", branch = "peg/azure-outdated-tcp-override", features = ["danger-allow-tcb-override"] }
22+
hex = "0.4.3"
23+
http = "1.3.1"
24+
serde_json = "1.0.145"
25+
serde = "1.0.228"
26+
base64 = "0.22.1"
27+
reqwest = { version = "0.12.23", default-features = false, features = [
28+
"rustls-tls-webpki-roots-no-provider",
29+
] }
30+
tracing = "0.1.41"
31+
parity-scale-codec = "3.7.5"
32+
openssl = "0.10.75"
33+
num-bigint = "0.4.6"
34+
webpki = { package = "rustls-webpki", version = "0.103.8" }
35+
time = "0.3.47"
36+
once_cell = "1.21.3"
37+
38+
# Used for azure vTPM attestation support
39+
az-tdx-vtpm = { version = "0.7.4", optional = true }
40+
tss-esapi = { version = "7.6.0", optional = true }
41+
42+
# Used by test helpers
43+
tdx-quote = { version = "0.0.5", features = ["mock"], optional = true }
44+
45+
[dev-dependencies]
46+
tempfile = "3.23.0"
47+
tdx-quote = { version = "0.0.5", features = ["mock"] }
48+
49+
[features]
50+
default = []
51+
52+
# Adds support for Microsoft Azure attestation generation and verification
53+
azure = ["tss-esapi", "az-tdx-vtpm"]
54+
55+
# Exposes helper functions for testing - do not enable in production as this allows dangerous configuration
56+
test-helpers = []
57+
58+
# Allows mock quotes used in tests
59+
mock = ["tdx-quote"]

attested-tls/src/attestation/azure/ak_certificate.rs renamed to attestation/src/azure/ak_certificate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Generation and verification of AK certificates from the vTPM
2-
use crate::attestation::azure::{MaaError, nv_index};
2+
use crate::azure::{MaaError, nv_index};
33
use once_cell::sync::Lazy;
44
use std::time::Duration;
55
use tokio_rustls::rustls::pki_types::{CertificateDer, TrustAnchor, UnixTime};
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ use serde::{Deserialize, Serialize};
1212
use thiserror::Error;
1313
use x509_parser::prelude::*;
1414

15-
use crate::attestation::{
16-
dcap::verify_dcap_attestation_with_given_timestamp, measurements::MultiMeasurements,
17-
};
15+
use crate::{dcap::verify_dcap_attestation_with_given_timestamp, measurements::MultiMeasurements};
1816

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

345343
#[cfg(test)]
346344
mod tests {
347-
use crate::attestation::measurements::MeasurementPolicy;
345+
use crate::measurements::MeasurementPolicy;
348346

349347
use super::*;
350348

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

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

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

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

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

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

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

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

445443
let err = verify_azure_attestation_with_given_timestamp(
File renamed without changes.
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Data Center Attestation Primitives (DCAP) evidence generation and verification
2-
use crate::attestation::{AttestationError, measurements::MultiMeasurements};
2+
use crate::{AttestationError, measurements::MultiMeasurements};
33

44
use configfs_tsm::QuoteGenerationError;
55
use dcap_qvl::{
@@ -168,13 +168,13 @@ pub enum DcapVerificationError {
168168

169169
#[cfg(test)]
170170
mod tests {
171-
use crate::attestation::measurements::MeasurementPolicy;
171+
use crate::measurements::MeasurementPolicy;
172172

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

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

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

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

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

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

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

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ pub mod azure;
55
pub mod dcap;
66
pub mod measurements;
77

8+
#[cfg(any(test, feature = "test-helpers"))]
9+
pub mod test_helpers;
10+
811
use measurements::MultiMeasurements;
912
use parity_scale_codec::{Decode, Encode};
1013
use serde::{Deserialize, Serialize};
@@ -16,7 +19,7 @@ use std::{
1619

1720
use thiserror::Error;
1821

19-
use crate::attestation::{dcap::DcapVerificationError, measurements::MeasurementPolicy};
22+
use crate::{dcap::DcapVerificationError, measurements::MeasurementPolicy};
2023

2124
const GCP_METADATA_API: &str =
2225
"http://metadata.google.internal/computeMetadata/v1/project/project-id";

attested-tls/src/attestation/measurements.rs renamed to attestation/src/measurements.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! Measurements and policy for enforcing them when validating a remote attestation
2-
use crate::attestation::{AttestationError, AttestationType, dcap::DcapVerificationError};
2+
use crate::{AttestationError, AttestationType, dcap::DcapVerificationError};
33
use std::{collections::HashMap, path::PathBuf};
44
use std::{fmt, fmt::Formatter};
55

attestation/src/test_helpers.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
use crate::{MultiMeasurements, measurements::DcapMeasurementRegister};
2+
use std::collections::HashMap;
3+
4+
/// All-zero measurment values used in some tests
5+
pub fn mock_dcap_measurements() -> MultiMeasurements {
6+
MultiMeasurements::Dcap(HashMap::from([
7+
(DcapMeasurementRegister::MRTD, [0u8; 48]),
8+
(DcapMeasurementRegister::RTMR0, [0u8; 48]),
9+
(DcapMeasurementRegister::RTMR1, [0u8; 48]),
10+
(DcapMeasurementRegister::RTMR2, [0u8; 48]),
11+
(DcapMeasurementRegister::RTMR3, [0u8; 48]),
12+
]))
13+
}

0 commit comments

Comments
 (0)