mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 15:13:56 +02:00
Unify verify-attestation-sgx and verify-attestation
Rationale: too much copy-paste
This commit is contained in:
parent
0a0811e99e
commit
78447ea307
6 changed files with 111 additions and 173 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -3670,15 +3670,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "verify-attestation"
|
||||
version = "0.1.2-alpha.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"hex",
|
||||
"teepot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "verify-attestation-sgx"
|
||||
version = "0.1.2-alpha.1"
|
||||
dependencies = [
|
||||
"alloy-primitives",
|
||||
"anyhow",
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
[package]
|
||||
name = "verify-attestation-sgx"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
|
||||
[dependencies]
|
||||
alloy-primitives.workspace = true
|
||||
anyhow.workspace = true
|
||||
clap.workspace = true
|
||||
hex.workspace = true
|
||||
secp256k1.workspace = true
|
||||
teepot.workspace = true
|
|
@ -1,113 +0,0 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2023-2024 Matter Labs
|
||||
|
||||
//! Tool for SGX attestation and batch signature verification
|
||||
|
||||
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,
|
||||
sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
|
||||
};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)]
|
||||
struct Arguments {
|
||||
/// File with attestation quote proving signature originated from a TEE enclave.
|
||||
#[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("e_verification_result);
|
||||
|
||||
match &args.command {
|
||||
Some(SubCommands::SignVerify(signature_args)) => {
|
||||
verify_signature("e_verification_result, signature_args)?;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_signature(
|
||||
quote_verification_result: &QuoteVerificationResult,
|
||||
signature_args: &SignatureArgs,
|
||||
) -> Result<()> {
|
||||
let reportdata = "e_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()
|
||||
);
|
||||
let collateral =
|
||||
tee_qv_get_collateral(&attestation_quote_bytes).context("Failed to get collateral")?;
|
||||
let unix_time: i64 = std::time::SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)?
|
||||
.as_secs() as _;
|
||||
verify_quote_with_collateral(&attestation_quote_bytes, Some(&collateral), unix_time)
|
||||
.context("Failed to verify quote with collateral")
|
||||
}
|
||||
|
||||
fn print_quote_verification_summary(quote_verification_result: &QuoteVerificationResult) {
|
||||
let QuoteVerificationResult {
|
||||
collateral_expired,
|
||||
result,
|
||||
|
||||
quote,
|
||||
advisories,
|
||||
..
|
||||
} = quote_verification_result;
|
||||
if *collateral_expired {
|
||||
println!("Freshly fetched collateral expired");
|
||||
}
|
||||
let tcblevel = TcbLevel::from(*result);
|
||||
for advisory in advisories {
|
||||
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));
|
||||
}
|
|
@ -7,6 +7,9 @@ license.workspace = true
|
|||
repository.workspace = true
|
||||
|
||||
[dependencies]
|
||||
alloy-primitives.workspace = true
|
||||
anyhow.workspace = true
|
||||
clap.workspace = true
|
||||
hex.workspace = true
|
||||
secp256k1.workspace = true
|
||||
teepot.workspace = true
|
||||
|
|
|
@ -1,60 +1,134 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright (c) 2023-2024 Matter Labs
|
||||
|
||||
//! Simple TEE attestation verification test
|
||||
//! Tool for SGX attestation and batch signature verification
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![deny(clippy::all)]
|
||||
use alloy_primitives::B256;
|
||||
use anyhow::{Context, Result};
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
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},
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use std::io::Read;
|
||||
use std::time::UNIX_EPOCH;
|
||||
use teepot::client::TcbLevel;
|
||||
use teepot::sgx::{tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult};
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)]
|
||||
struct Arguments {
|
||||
/// Attestation quote proving the signature originated from a TEE enclave.
|
||||
#[clap(value_parser)]
|
||||
attestation: ArgSource,
|
||||
/// An optional subcommand, for instance, for optional signature verification.
|
||||
#[clap(subcommand)]
|
||||
command: Option<SubCommands>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum ArgSource {
|
||||
File(PathBuf),
|
||||
Stdin,
|
||||
}
|
||||
|
||||
impl FromStr for ArgSource {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"-" => Ok(ArgSource::Stdin),
|
||||
_ => Ok(ArgSource::File(PathBuf::from(s))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
/// Verify a batch signature signed within a TEE enclave.
|
||||
SignVerify(SignatureArgs),
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// read myquote from stdin
|
||||
let mut myquote = Vec::new();
|
||||
std::io::stdin()
|
||||
.read_to_end(&mut myquote)
|
||||
.context("Failed to read quote from stdin")?;
|
||||
let args = Arguments::parse();
|
||||
let attestation_quote_bytes = match args.attestation {
|
||||
ArgSource::File(path) => fs::read(&path)?,
|
||||
ArgSource::Stdin => {
|
||||
let mut quote = Vec::new();
|
||||
std::io::stdin()
|
||||
.read_to_end(&mut quote)
|
||||
.context("Failed to read attestation quote from stdin")?;
|
||||
quote
|
||||
}
|
||||
};
|
||||
let quote_verification_result = verify_attestation_quote(&attestation_quote_bytes)?;
|
||||
print_quote_verification_summary("e_verification_result);
|
||||
match &args.command {
|
||||
Some(SubCommands::SignVerify(signature_args)) => {
|
||||
verify_signature("e_verification_result, signature_args)?;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
println!("Verifying quote ({} bytes)...", myquote.len());
|
||||
|
||||
let collateral = tee_qv_get_collateral(&myquote).context("Failed to get collateral")?;
|
||||
fn verify_signature(
|
||||
quote_verification_result: &QuoteVerificationResult,
|
||||
signature_args: &SignatureArgs,
|
||||
) -> Result<()> {
|
||||
let reportdata = "e_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()
|
||||
);
|
||||
let collateral =
|
||||
tee_qv_get_collateral(&attestation_quote_bytes).context("Failed to get collateral")?;
|
||||
let unix_time: i64 = std::time::SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.duration_since(UNIX_EPOCH)?
|
||||
.as_secs() as _;
|
||||
verify_quote_with_collateral(&attestation_quote_bytes, Some(&collateral), unix_time)
|
||||
.context("Failed to verify quote with collateral")
|
||||
}
|
||||
|
||||
fn print_quote_verification_summary(quote_verification_result: &QuoteVerificationResult) {
|
||||
let QuoteVerificationResult {
|
||||
collateral_expired,
|
||||
result,
|
||||
|
||||
quote,
|
||||
advisories,
|
||||
..
|
||||
} = verify_quote_with_collateral(&myquote, Some(&collateral), unix_time.saturating_add(60))
|
||||
.context("Failed to verify quote with collateral")?;
|
||||
|
||||
if collateral_expired {
|
||||
bail!("Freshly fetched collateral expired");
|
||||
} = quote_verification_result;
|
||||
if *collateral_expired {
|
||||
println!("Freshly fetched collateral expired");
|
||||
}
|
||||
|
||||
let tcblevel = TcbLevel::from(result);
|
||||
if tcblevel != TcbLevel::Ok {
|
||||
println!("Quote verification result: {}", tcblevel);
|
||||
}
|
||||
|
||||
let tcblevel = TcbLevel::from(*result);
|
||||
for advisory in advisories {
|
||||
println!("\tInfo: Advisory ID: {advisory}");
|
||||
}
|
||||
|
||||
println!("Quote verified successfully: {}", tcblevel);
|
||||
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));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
"vault_admin"
|
||||
"vault_unseal"
|
||||
"verify_attestation"
|
||||
"verify_attestation_sgx"
|
||||
];
|
||||
postInstall = ''
|
||||
removeReferencesToVendoredSources "$out" "$cargoVendorDir"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue