feat: add TDX support

Signed-off-by: Harald Hoyer <harald@matterlabs.dev>
This commit is contained in:
Harald Hoyer 2024-12-20 09:07:36 +01:00
parent f4fba51e3e
commit 4610475fae
Signed by: harald
GPG key ID: F519A1143B3FBE32
18 changed files with 2316 additions and 369 deletions

View file

@ -9,9 +9,7 @@
use anyhow::{Context, Result};
use clap::Parser;
use secp256k1::{rand, Keypair, PublicKey, Secp256k1, SecretKey};
use std::ffi::OsString;
use std::os::unix::process::CommandExt;
use std::process::Command;
use std::{ffi::OsString, os::unix::process::CommandExt, process::Command};
use teepot::quote::get_quote;
use tracing::error;
use tracing_log::LogTracer;
@ -47,15 +45,15 @@ fn main_with_error() -> Result<()> {
let verifying_key = PublicKey::from_keypair(&keypair);
let verifying_key_bytes = verifying_key.serialize();
let tee_type = match get_quote(verifying_key_bytes.as_ref()) {
Ok(quote) => {
Ok((tee_type, quote)) => {
// save quote to file
std::fs::write(TEE_QUOTE_FILE, quote)?;
"sgx"
tee_type.to_string()
}
Err(e) => {
error!("Failed to get quote: {}", e);
std::fs::write(TEE_QUOTE_FILE, [])?;
"none"
"none".to_string()
}
};

View file

@ -9,7 +9,7 @@ use secp256k1::{ecdsa::Signature, Message, PublicKey};
use std::{fs, io::Read, path::PathBuf, str::FromStr, time::UNIX_EPOCH};
use teepot::{
client::TcbLevel,
sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
quote::{error, tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
};
use zksync_basic_types::H256;
@ -84,7 +84,7 @@ fn verify_signature(
quote_verification_result: &QuoteVerificationResult,
signature_args: &SignatureArgs,
) -> Result<()> {
let reportdata = &quote_verification_result.quote.report_body.reportdata;
let reportdata = &quote_verification_result.quote.get_report_data();
let public_key = PublicKey::from_slice(reportdata)?;
println!("Public key from attestation quote: {}", public_key);
let signature_bytes = fs::read(&signature_args.signature_file)?;
@ -103,8 +103,10 @@ fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result<QuoteVerif
"Verifying quote ({} bytes)...",
attestation_quote_bytes.len()
);
let collateral =
tee_qv_get_collateral(attestation_quote_bytes).context("Failed to get collateral")?;
let collateral = error::QuoteContext::context(
tee_qv_get_collateral(attestation_quote_bytes),
"Failed to get collateral",
)?;
let unix_time: i64 = std::time::SystemTime::now()
.duration_since(UNIX_EPOCH)?
.as_secs() as _;
@ -128,7 +130,6 @@ fn print_quote_verification_summary(quote_verification_result: &QuoteVerificatio
println!("\tInfo: Advisory ID: {advisory}");
}
println!("Quote verification result: {}", tcblevel);
println!("mrsigner: {}", hex::encode(quote.report_body.mrsigner));
println!("mrenclave: {}", hex::encode(quote.report_body.mrenclave));
println!("reportdata: {}", hex::encode(quote.report_body.reportdata));
println!("{:#}", &quote.report);
}

View file

@ -1,21 +1,22 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs
use crate::{args::AttestationPolicyArgs, client::JsonRpcClient};
use anyhow::{Context, Result};
use hex::encode;
use secp256k1::{constants::PUBLIC_KEY_SIZE, ecdsa::Signature, Message, PublicKey};
use teepot::{
client::TcbLevel,
sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
quote::{
error::QuoteContext, tee_qv_get_collateral, verify_quote_with_collateral,
QuoteVerificationResult, Report,
},
};
use tracing::{debug, info, warn};
use zksync_basic_types::{L1BatchNumber, H256};
use crate::args::AttestationPolicyArgs;
use crate::client::JsonRpcClient;
pub async fn verify_batch_proof(
quote_verification_result: &QuoteVerificationResult<'_>,
quote_verification_result: &QuoteVerificationResult,
attestation_policy: &AttestationPolicyArgs,
node_client: &impl JsonRpcClient,
signature: &[u8],
@ -28,7 +29,7 @@ pub async fn verify_batch_proof(
let batch_no = batch_number.0;
let public_key = PublicKey::from_slice(
&quote_verification_result.quote.report_body.reportdata[..PUBLIC_KEY_SIZE],
&quote_verification_result.quote.get_report_data()[..PUBLIC_KEY_SIZE],
)?;
debug!(batch_no, "public key: {}", public_key);
@ -45,8 +46,10 @@ pub async fn verify_batch_proof(
}
pub fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result<QuoteVerificationResult> {
let collateral =
tee_qv_get_collateral(attestation_quote_bytes).context("Failed to get collateral!")?;
let collateral = QuoteContext::context(
tee_qv_get_collateral(attestation_quote_bytes),
"Failed to get collateral!",
)?;
let unix_time: i64 = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_secs() as _;
@ -66,17 +69,19 @@ pub fn log_quote_verification_summary(quote_verification_result: &QuoteVerificat
warn!("Freshly fetched collateral expired!");
}
let tcblevel = TcbLevel::from(*result);
let advisories = if advisories.is_empty() {
"None".to_string()
} else {
advisories
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ")
};
info!(
"Quote verification result: {}. mrsigner: {}, mrenclave: {}, reportdata: {}. Advisory IDs: {}.",
tcblevel,
hex::encode(quote.report_body.mrsigner),
hex::encode(quote.report_body.mrenclave),
hex::encode(quote.report_body.reportdata),
if advisories.is_empty() {
"None".to_string()
} else {
advisories.iter().map(ToString::to_string).collect::<Vec<_>>().join(", ")
}
"Quote verification result: {tcblevel}. {report}. Advisory IDs: {advisories}.",
report = &quote.report
);
}
@ -88,7 +93,7 @@ fn verify_signature(signature: &[u8], public_key: PublicKey, root_hash: H256) ->
fn is_quote_matching_policy(
attestation_policy: &AttestationPolicyArgs,
quote_verification_result: &QuoteVerificationResult<'_>,
quote_verification_result: &QuoteVerificationResult,
) -> bool {
let quote = &quote_verification_result.quote;
let tcblevel = TcbLevel::from(quote_verification_result.result);
@ -100,16 +105,20 @@ fn is_quote_matching_policy(
);
return false;
}
check_policy(
attestation_policy.sgx_mrsigners.as_deref(),
&quote.report_body.mrsigner,
"mrsigner",
) && check_policy(
attestation_policy.sgx_mrenclaves.as_deref(),
&quote.report_body.mrenclave,
"mrenclave",
)
match &quote.report {
Report::SgxEnclave(report_body) => {
check_policy(
attestation_policy.sgx_mrsigners.as_deref(),
&report_body.mr_signer,
"mrsigner",
) && check_policy(
attestation_policy.sgx_mrenclaves.as_deref(),
&report_body.mr_enclave,
"mrenclave",
)
}
_ => false,
}
}
fn check_policy(policy: Option<&str>, actual_value: &[u8], field_name: &str) -> bool {