mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 15:13:56 +02:00
feat: add file output for attestation collateral and quote data
- Write attestation collateral and quote details to various files.
This commit is contained in:
parent
63b9d6f6ee
commit
71de3a53bc
6 changed files with 159 additions and 11 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -6455,6 +6455,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"url",
|
||||
"x509-cert",
|
||||
"zksync_basic_types",
|
||||
"zksync_types",
|
||||
"zksync_web3_decl",
|
||||
|
|
|
@ -69,7 +69,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "ansi"
|
|||
tracing-test = { version = "0.2.5", features = ["no-env-filter"] }
|
||||
url = "2.5.2"
|
||||
webpki-roots = "0.26.1"
|
||||
x509-cert = { version = "0.2", features = ["builder", "signature"] }
|
||||
x509-cert = { version = "0.2", features = ["builder", "signature", "pem"] }
|
||||
zeroize = { version = "1.7.0", features = ["serde"] }
|
||||
zksync_basic_types = "=0.1.0"
|
||||
zksync_types = "=0.1.0"
|
||||
|
|
|
@ -21,6 +21,7 @@ tokio.workspace = true
|
|||
tracing.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
url.workspace = true
|
||||
x509-cert.workspace = true
|
||||
zksync_basic_types.workspace = true
|
||||
zksync_types.workspace = true
|
||||
zksync_web3_decl.workspace = true
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2023-2024 Matter Labs
|
||||
// Copyright (c) 2023-2025 Matter Labs
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use clap::{ArgGroup, Args, Parser};
|
||||
use std::time::Duration;
|
||||
use teepot::log::LogLevelParser;
|
||||
use teepot::sgx::{parse_tcb_levels, EnumSet, TcbLevel};
|
||||
use teepot::{
|
||||
log::LogLevelParser,
|
||||
sgx::{parse_tcb_levels, EnumSet, TcbLevel},
|
||||
};
|
||||
use tracing_subscriber::filter::LevelFilter;
|
||||
use url::Url;
|
||||
use zksync_basic_types::L1BatchNumber;
|
||||
|
@ -43,6 +45,9 @@ pub struct Arguments {
|
|||
/// Criteria for valid attestation policy. Invalid proofs will be rejected.
|
||||
#[clap(flatten)]
|
||||
pub attestation_policy: AttestationPolicyArgs,
|
||||
/// Save artifacts needed for verification
|
||||
#[clap(short = 's', long = "save")]
|
||||
pub save: bool,
|
||||
}
|
||||
|
||||
/// Attestation policy implemented as a set of criteria that must be met by SGX attestation.
|
||||
|
|
|
@ -91,6 +91,7 @@ async fn verify_batches_proofs(
|
|||
&http_client,
|
||||
&node_client,
|
||||
&args.attestation_policy,
|
||||
args.save,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -141,6 +142,7 @@ async fn verify_batch_proofs(
|
|||
http_client: &Client,
|
||||
node_client: &MainNodeClient,
|
||||
attestation_policy: &AttestationPolicyArgs,
|
||||
save: bool,
|
||||
) -> Result<bool> {
|
||||
let proofs = get_proofs(stop_receiver, batch_number, http_client, rpc_url).await?;
|
||||
let batch_no = batch_number.0;
|
||||
|
@ -178,6 +180,7 @@ async fn verify_batch_proofs(
|
|||
node_client,
|
||||
&proof.signature.unwrap_or_default(),
|
||||
L1BatchNumber(proof.l1_batch_number),
|
||||
save,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -8,13 +8,16 @@ use secp256k1::{
|
|||
ecdsa::{RecoverableSignature, RecoveryId, Signature},
|
||||
Message, SECP256K1,
|
||||
};
|
||||
use std::fs;
|
||||
use teepot::{
|
||||
client::TcbLevel,
|
||||
ethereum::{public_key_to_ethereum_address, recover_signer},
|
||||
prover::reportdata::ReportData,
|
||||
quote::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult, Report},
|
||||
sgx::Collateral,
|
||||
};
|
||||
use tracing::{debug, info, trace, warn};
|
||||
use x509_cert::der::Encode;
|
||||
use zksync_basic_types::{L1BatchNumber, H256};
|
||||
|
||||
struct TeeProof {
|
||||
|
@ -32,7 +35,7 @@ impl TeeProof {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn verify(&self) -> Result<bool> {
|
||||
pub fn verify(&mut self) -> Result<bool> {
|
||||
match &self.report {
|
||||
ReportData::V0(report) => {
|
||||
debug!("ReportData::V0");
|
||||
|
@ -75,6 +78,9 @@ impl TeeProof {
|
|||
);
|
||||
if ethereum_address_from_signature == ethereum_address_from_report {
|
||||
info!("Had to use RecoveryId::{rec_id:?}");
|
||||
self.signature.push(
|
||||
u8::try_from(i32::from(rec_id)).context("recovery id to u8")? + 27,
|
||||
);
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
@ -100,15 +106,130 @@ impl TeeProof {
|
|||
}
|
||||
}
|
||||
|
||||
fn save_verification_artifacts(
|
||||
batch_number: L1BatchNumber,
|
||||
signature: &[u8],
|
||||
root_hash: &H256,
|
||||
attestation_quote_bytes: &[u8],
|
||||
collateral: &Collateral,
|
||||
) -> Result<()> {
|
||||
fs::write(
|
||||
format!("{}_signature.hex", batch_number),
|
||||
hex::encode(signature),
|
||||
)?;
|
||||
fs::write(
|
||||
format!("{}_root_hash.hex", batch_number),
|
||||
format!("{:x}", root_hash),
|
||||
)?;
|
||||
fs::write(
|
||||
format!("{}_quote.bin", batch_number),
|
||||
attestation_quote_bytes,
|
||||
)?;
|
||||
fs::write(
|
||||
format!("{}_quote.bin.hex", batch_number),
|
||||
hex::encode(attestation_quote_bytes),
|
||||
)?;
|
||||
|
||||
let certs = x509_cert::certificate::CertificateInner::<
|
||||
x509_cert::certificate::Rfc5280
|
||||
>::load_pem_chain(collateral.pck_crl_issuer_chain.split_last().unwrap().1)?;
|
||||
|
||||
let cert = certs
|
||||
.into_iter()
|
||||
.find(|cert| {
|
||||
cert.tbs_certificate
|
||||
.subject
|
||||
.to_string()
|
||||
.contains("PCK Platform CA")
|
||||
})
|
||||
.ok_or(anyhow!("PCK Platform CA cert not found"))?;
|
||||
|
||||
fs::write(
|
||||
format!("{}_platformDer.hex", batch_number),
|
||||
hex::encode(&cert.to_der()?),
|
||||
)
|
||||
.context("Failed to write PCK Platform CA to platformDer.hex")?;
|
||||
|
||||
debug!(
|
||||
"Platform CA serial {}",
|
||||
cert.tbs_certificate.serial_number.to_string()
|
||||
);
|
||||
|
||||
fs::write(
|
||||
format!("{}_rootCrlDer.hex", batch_number),
|
||||
collateral.root_ca_crl.split_last().unwrap().1,
|
||||
)
|
||||
.context("Failed to write root_ca_crl to rootCrlDer.hex")?;
|
||||
|
||||
fs::write(
|
||||
format!("{}_platformCrlDer.hex", batch_number),
|
||||
hex::encode(collateral.pck_crl.split_last().unwrap().1),
|
||||
)
|
||||
.context("Failed to write pck_crl to platformCrlDer.hex")?;
|
||||
|
||||
let certs = x509_cert::certificate::CertificateInner::<
|
||||
x509_cert::certificate::Rfc5280
|
||||
>::load_pem_chain(collateral.tcb_info_issuer_chain.split_last().unwrap().1)?;
|
||||
|
||||
let cert = certs
|
||||
.into_iter()
|
||||
.find(|cert| {
|
||||
cert.tbs_certificate
|
||||
.subject
|
||||
.to_string()
|
||||
.contains("TCB Signing")
|
||||
})
|
||||
.ok_or(anyhow!("TCB Signing cert not found"))?;
|
||||
|
||||
debug!("TCB cert {}", cert.tbs_certificate.subject.to_string());
|
||||
debug!(
|
||||
"TCB serial {}",
|
||||
cert.tbs_certificate.serial_number.to_string()
|
||||
);
|
||||
|
||||
fs::write(
|
||||
format!("{}_tcbDer.hex", batch_number),
|
||||
hex::encode(&cert.to_der()?),
|
||||
)
|
||||
.context("Failed to write TCB Signing CA to tcbDer.hex")?;
|
||||
|
||||
fs::write(
|
||||
format!("{}_tcb_info.json", batch_number),
|
||||
collateral.tcb_info.split_last().unwrap().1,
|
||||
)
|
||||
.context("Failed to write tcb_info to tcb_info.json")?;
|
||||
|
||||
let certs = x509_cert::certificate::CertificateInner::<
|
||||
x509_cert::certificate::Rfc5280
|
||||
>::load_pem_chain(collateral.qe_identity_issuer_chain.split_last().unwrap().1)?;
|
||||
|
||||
let _ = certs
|
||||
.into_iter()
|
||||
.find(|qe_cert| {
|
||||
qe_cert
|
||||
.tbs_certificate
|
||||
.serial_number
|
||||
.eq(&cert.tbs_certificate.serial_number)
|
||||
})
|
||||
.ok_or(anyhow!("QE identity cert != TCB cert"))?;
|
||||
|
||||
fs::write(
|
||||
format!("{}_qe_identity.json", batch_number),
|
||||
collateral.qe_identity.split_last().unwrap().1,
|
||||
)
|
||||
.context("Failed to write qe_identity to qe_identity.json")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn verify_batch_proof(
|
||||
attestation_quote_bytes: &[u8],
|
||||
attestation_policy: &AttestationPolicyArgs,
|
||||
node_client: &impl JsonRpcClient,
|
||||
signature: &[u8],
|
||||
batch_number: L1BatchNumber,
|
||||
save: bool,
|
||||
) -> Result<bool> {
|
||||
use std::fs;
|
||||
|
||||
let quote_verification_result = verify_attestation_quote(attestation_quote_bytes)?;
|
||||
|
||||
log_quote_verification_summary("e_verification_result);
|
||||
|
@ -116,12 +237,29 @@ pub async fn verify_batch_proof(
|
|||
if !is_quote_matching_policy(attestation_policy, "e_verification_result) {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let QuoteVerificationResult {
|
||||
quote, collateral, ..
|
||||
} = quote_verification_result;
|
||||
let root_hash = node_client.get_root_hash(batch_number).await?;
|
||||
let report_data_bytes = quote_verification_result.quote.get_report_data();
|
||||
let report_data_bytes = quote.get_report_data();
|
||||
|
||||
let report_data = ReportData::try_from(report_data_bytes)?;
|
||||
let tee_proof = TeeProof::new(report_data, root_hash, signature.to_vec());
|
||||
tee_proof.verify()
|
||||
|
||||
let mut tee_proof = TeeProof::new(report_data, root_hash, signature.to_vec());
|
||||
|
||||
let res = tee_proof.verify();
|
||||
|
||||
if save {
|
||||
save_verification_artifacts(
|
||||
batch_number,
|
||||
tee_proof.signature.as_slice(),
|
||||
&root_hash,
|
||||
attestation_quote_bytes,
|
||||
&collateral,
|
||||
)?;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result<QuoteVerificationResult> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue