Introduce root_hash option

This commit is contained in:
Patryk Bęza 2024-07-10 20:01:41 +02:00
parent f90088be76
commit f3f6ea1dba
No known key found for this signature in database
GPG key ID: 9AD1B44D9F6258EC
4 changed files with 816 additions and 164 deletions

898
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,7 @@ homepage = "https://github.com/matter-labs/teepot"
actix-http = "3"
actix-tls = "3"
actix-web = { version = "4.5", features = ["rustls-0_22"] }
alloy-primitives = "0.7.7"
anyhow = "1.0.82"
awc = { version = "3.4", features = ["rustls-0_22-webpki-roots"] }
base64 = "0.22.0"
@ -34,7 +35,7 @@ getrandom = "0.2.14"
hex = { version = "0.4.3", features = ["std"], default-features = false }
intel-tee-quote-verification-rs = { package = "teepot-tee-quote-verification-rs", path = "crates/teepot-tee-quote-verification-rs", version = "0.2.3-alpha.1" }
intel-tee-quote-verification-sys = { version = "0.2.1" }
secp256k1 = { version = "0.29", features = ["rand-std"] }
secp256k1 = { version = "0.29", features = ["rand-std", "global-context"] }
log = "0.4"
num-integer = "0.1.46"
num-traits = "0.2.18"

View file

@ -8,6 +8,7 @@ repository.workspace = true
homepage.workspace = true
[dependencies]
alloy-primitives.workspace = true
anyhow.workspace = true
clap.workspace = true
hex.workspace = true

View file

@ -3,50 +3,80 @@
//! Tool for SGX attestation and batch signature verification
use anyhow::{bail, Context, Result};
use clap::Parser;
use alloy_primitives::B256;
use anyhow::{Context, Result};
use clap::{Args, Parser, Subcommand};
use secp256k1::{ecdsa::Signature, Message, PublicKey};
use std::fs;
use std::path::PathBuf;
use std::time::UNIX_EPOCH;
use teepot::client::TcbLevel;
use teepot::sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult};
use teepot::{
client::TcbLevel,
sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
};
#[derive(Parser, Debug)]
#[command(author = "Matter Labs", version, about = "TEE attestation verifier", long_about = None)]
#[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)]
struct Arguments {
/// File containing a batch signature signed within a TEE enclave.
#[clap(long)]
signature_file: Option<PathBuf>,
/// File with attestation quote proving signature originated from a TEE enclave.
#[clap(long)]
#[clap()]
attestation_file: PathBuf,
/// An optional subcommand, for instance, for optional signature verification.
#[clap(subcommand)]
command: Option<SubCommands>,
}
#[derive(Args, Debug)]
struct SignatureArgs {
/// File containing a batch signature signed within a TEE enclave.
#[arg(long)]
signature_file: PathBuf,
/// Batch root hash for signature verification.
#[arg(long)]
root_hash: B256,
}
#[derive(Subcommand, Debug)]
enum SubCommands {
/// Provide both signature_file and root_hash
SignVerify(SignatureArgs),
}
fn main() -> Result<()> {
let args = Arguments::parse();
let attestation_quote_bytes = fs::read(&args.attestation_file)?;
let quote_verification_result = verify_attestation_quote(&attestation_quote_bytes)?;
print_quote_verification_summary(&quote_verification_result);
if let Some(signature_file) = args.signature_file {
let reportdata = &quote_verification_result.quote.report_body.reportdata;
let verifying_key = PublicKey::from_slice(reportdata)?;
// let signature_bytes = fs::read(&args.signature_file)?;
// let signature = Signature::from_compact(&signature_bytes)?;
let signature = fs::read(&args.signature_file)?.map(Signature::from_compact)?;
let message = Message::from_slice(reportdata)?; // TODO
if signature.verify(&message, &verifying_key).is_ok() {
println!("Signature verified successfully");
} else {
println!("Failed to verify signature");
match &args.command {
Some(SubCommands::SignVerify(signature_args)) => {
verify_signature(&quote_verification_result, signature_args)?;
}
None => {}
}
Ok(())
}
fn verify_attestation_quote<'a>(
attestation_quote_bytes: &'a Vec<u8>,
) -> Result<QuoteVerificationResult<'a>> {
fn verify_signature(
quote_verification_result: &QuoteVerificationResult,
signature_args: &SignatureArgs,
) -> Result<()> {
let reportdata = &quote_verification_result.quote.report_body.reportdata;
let public_key = PublicKey::from_slice(reportdata)?;
println!("Public key from attestation quote: {}", public_key);
let signature_bytes = fs::read(&signature_args.signature_file)?;
let signature = Signature::from_compact(&signature_bytes)?;
let root_hash_msg = Message::from_digest_slice(&signature_args.root_hash.0)?;
if signature.verify(&root_hash_msg, &public_key).is_ok() {
println!("Signature verified successfully");
} else {
println!("Failed to verify signature");
}
Ok(())
}
fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result<QuoteVerificationResult> {
println!(
"Verifying quote ({} bytes)...",
attestation_quote_bytes.len()
@ -60,7 +90,7 @@ fn verify_attestation_quote<'a>(
.context("Failed to verify quote with collateral")
}
fn print_quote_verification_summary<'a>(quote_verification_result: &QuoteVerificationResult<'a>) {
fn print_quote_verification_summary(quote_verification_result: &QuoteVerificationResult) {
let QuoteVerificationResult {
collateral_expired,
result,