chore: split-out vault code from teepot in teepot-vault

Signed-off-by: Harald Hoyer <harald@matterlabs.dev>
This commit is contained in:
Harald Hoyer 2025-02-18 13:37:34 +01:00
parent 63c16b1177
commit f8bd9e6a08
Signed by: harald
GPG key ID: F519A1143B3FBE32
61 changed files with 450 additions and 308 deletions

51
Cargo.lock generated
View file

@ -5559,6 +5559,7 @@ dependencies = [
"clap 4.5.30", "clap 4.5.30",
"serde", "serde",
"teepot", "teepot",
"teepot-vault",
"tracing", "tracing",
"tracing-log 0.2.0", "tracing-log 0.2.0",
"tracing-subscriber", "tracing-subscriber",
@ -5578,6 +5579,7 @@ dependencies = [
"serde_json", "serde_json",
"sha2", "sha2",
"teepot", "teepot",
"teepot-vault",
"tracing", "tracing",
"tracing-actix-web", "tracing-actix-web",
"tracing-log 0.2.0", "tracing-log 0.2.0",
@ -5595,6 +5597,7 @@ dependencies = [
"rustls", "rustls",
"serde_json", "serde_json",
"teepot", "teepot",
"teepot-vault",
"tracing", "tracing",
"tracing-log 0.2.0", "tracing-log 0.2.0",
"tracing-subscriber", "tracing-subscriber",
@ -5604,19 +5607,14 @@ dependencies = [
name = "teepot" name = "teepot"
version = "0.3.0" version = "0.3.0"
dependencies = [ dependencies = [
"actix-http",
"actix-web",
"anyhow", "anyhow",
"async-trait", "async-trait",
"awc",
"base64 0.22.1", "base64 0.22.1",
"bytemuck", "bytemuck",
"bytes",
"clap 4.5.30", "clap 4.5.30",
"config", "config",
"const-oid", "const-oid",
"enumset", "enumset",
"futures-core",
"getrandom 0.3.1", "getrandom 0.3.1",
"hex", "hex",
"num-integer", "num-integer",
@ -5627,7 +5625,6 @@ dependencies = [
"opentelemetry-semantic-conventions 0.28.0", "opentelemetry-semantic-conventions 0.28.0",
"opentelemetry_sdk 0.28.0", "opentelemetry_sdk 0.28.0",
"p256", "p256",
"pgp",
"pkcs8 0.10.2", "pkcs8 0.10.2",
"reqwest 0.12.12", "reqwest 0.12.12",
"rsa", "rsa",
@ -5635,7 +5632,6 @@ dependencies = [
"secp256k1 0.30.0", "secp256k1 0.30.0",
"serde", "serde",
"serde_json", "serde_json",
"serde_with 3.12.0",
"sha2", "sha2",
"sha3", "sha3",
"signature 2.2.0", "signature 2.2.0",
@ -5649,10 +5645,8 @@ dependencies = [
"tracing-log 0.2.0", "tracing-log 0.2.0",
"tracing-subscriber", "tracing-subscriber",
"tracing-test", "tracing-test",
"webpki-roots",
"x509-cert", "x509-cert",
"zeroize", "zeroize",
"zksync_basic_types",
] ]
[[package]] [[package]]
@ -5664,7 +5658,7 @@ dependencies = [
"awc", "awc",
"clap 4.5.30", "clap 4.5.30",
"serde_json", "serde_json",
"teepot", "teepot-vault",
"tracing", "tracing",
"tracing-log 0.2.0", "tracing-log 0.2.0",
"tracing-subscriber", "tracing-subscriber",
@ -5678,6 +5672,35 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "teepot-vault"
version = "0.3.0"
dependencies = [
"actix-http",
"actix-web",
"anyhow",
"awc",
"base64 0.22.1",
"bytes",
"clap 4.5.30",
"const-oid",
"futures-core",
"hex",
"pgp",
"rustls",
"serde",
"serde_json",
"serde_with 3.12.0",
"sha2",
"tdx-attest-rs",
"teepot",
"teepot-tee-quote-verification-rs",
"thiserror 2.0.11",
"tracing",
"webpki-roots",
"x509-cert",
]
[[package]] [[package]]
name = "teepot-write" name = "teepot-write"
version = "0.3.0" version = "0.3.0"
@ -5687,7 +5710,7 @@ dependencies = [
"awc", "awc",
"clap 4.5.30", "clap 4.5.30",
"serde_json", "serde_json",
"teepot", "teepot-vault",
"tracing", "tracing",
"tracing-log 0.2.0", "tracing-log 0.2.0",
"tracing-subscriber", "tracing-subscriber",
@ -6396,6 +6419,7 @@ dependencies = [
"pgp", "pgp",
"serde_json", "serde_json",
"teepot", "teepot",
"teepot-vault",
"tracing", "tracing",
] ]
@ -6408,7 +6432,7 @@ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"clap 4.5.30", "clap 4.5.30",
"serde_json", "serde_json",
"teepot", "teepot-vault",
"tracing", "tracing",
"tracing-log 0.2.0", "tracing-log 0.2.0",
"tracing-subscriber", "tracing-subscriber",
@ -6432,10 +6456,7 @@ version = "0.3.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap 4.5.30", "clap 4.5.30",
"hex",
"secp256k1 0.30.0",
"teepot", "teepot",
"zksync_basic_types",
] ]
[[package]] [[package]]

View file

@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["crates/*", "bin/*"] members = ["crates/*", "bin/*", "crates/teepot-vault/bin/*"]
resolver = "2" resolver = "2"
[profile.release] [profile.release]
@ -16,7 +16,6 @@ repository = "https://github.com/matter-labs/teepot"
homepage = "https://github.com/matter-labs/teepot" homepage = "https://github.com/matter-labs/teepot"
[workspace.dependencies] [workspace.dependencies]
actix-http = "3"
actix-web = { version = "4.5", features = ["rustls-0_23"] } actix-web = { version = "4.5", features = ["rustls-0_23"] }
anyhow = "1.0.82" anyhow = "1.0.82"
async-trait = "0.1.86" async-trait = "0.1.86"
@ -28,7 +27,6 @@ clap = { version = "4.5", features = ["std", "derive", "env", "error-context", "
config = { version = "0.15.8", default-features = false, features = ["yaml", "json", "toml", "async"] } config = { version = "0.15.8", default-features = false, features = ["yaml", "json", "toml", "async"] }
const-oid = { version = "0.9", default-features = false } const-oid = { version = "0.9", default-features = false }
enumset = { version = "1.1", features = ["serde"] } enumset = { version = "1.1", features = ["serde"] }
futures-core = { version = "0.3.30", features = ["alloc"], default-features = false }
getrandom = { version = "0.3.1", features = ["std"] } getrandom = { version = "0.3.1", features = ["std"] }
gpt = "4.0.0" gpt = "4.0.0"
hex = { version = "0.4.3", features = ["std"], default-features = false } hex = { version = "0.4.3", features = ["std"], default-features = false }
@ -58,6 +56,7 @@ sha3 = "0.10.8"
signature = "2.2.0" signature = "2.2.0"
tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCenterAttestationPrimitives.git", rev = "aa239d25a437a28f3f4de92c38f5b6809faac842" } tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCenterAttestationPrimitives.git", rev = "aa239d25a437a28f3f4de92c38f5b6809faac842" }
teepot = { path = "crates/teepot" } teepot = { path = "crates/teepot" }
teepot-vault = { path = "crates/teepot-vault" }
testaso = "0.1.0" testaso = "0.1.0"
thiserror = "2.0.11" thiserror = "2.0.11"
tokio = { version = "1", features = ["sync", "macros", "rt-multi-thread", "fs", "time", "signal"] } tokio = { version = "1", features = ["sync", "macros", "rt-multi-thread", "fs", "time", "signal"] }
@ -68,9 +67,5 @@ tracing-log = "0.2"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "ansi"] } tracing-subscriber = { version = "0.3", features = ["env-filter", "json", "ansi"] }
tracing-test = { version = "0.2.5", features = ["no-env-filter"] } tracing-test = { version = "0.2.5", features = ["no-env-filter"] }
url = "2.5.2" 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"] }
zeroize = { version = "1.7.0", features = ["serde"] } zeroize = { version = "1.7.0", features = ["serde"] }
zksync_basic_types = "=0.1.0"
zksync_types = "=0.1.0"
zksync_web3_decl = "=0.1.0"

View file

@ -2,17 +2,12 @@
## Parts of this project ## Parts of this project
- `teepot`: The main rust crate that abstracts TEEs and key-value stores. ### teepot - lib
- `tee-vault-unseal`: An enclave that uses the Vault API to unseal a vault as a proxy.
- `vault-unseal`: A client utility, that talks to `tee-vault-unseal` to unseal a vault. - `teepot`: The main rust crate that abstracts TEEs.
- `tee-vault-admin`: An enclave that uses the Vault API to administer a vault as a proxy.
- `vault-admin`: A client utility, that talks to `tee-vault-admin` to administer a vault.
- `teepot-read` : A pre-exec utility that reads from the key-value store and passes the key-value pairs as environment
variables to the enclave.
- `teepot-write` : A pre-exec utility that reads key-values from the environment variables and writes them to the
key-value store.
- `verify-attestation`: A client utility that verifies the attestation of an enclave. - `verify-attestation`: A client utility that verifies the attestation of an enclave.
- `tee-key-preexec`: A pre-exec utility that generates a p256 secret key and passes it as an environment variable to the - `tee-key-preexec`: A pre-exec utility that generates a p256 secret key and passes it as an environment variable to
the
enclave along with the attestation quote containing the hash of the public key. enclave along with the attestation quote containing the hash of the public key.
- `tdx_google`: A base VM running on Google Cloud TDX. It receives a container URL via the instance metadata, - `tdx_google`: A base VM running on Google Cloud TDX. It receives a container URL via the instance metadata,
measures the sha384 of the URL to RTMR3 and launches the container. measures the sha384 of the URL to RTMR3 and launches the container.
@ -21,12 +16,23 @@
and a UKI (unified kernel image). and a UKI (unified kernel image).
- `sha384-extend`: A utility to calculate RTMR registers after extending them with a digest. - `sha384-extend`: A utility to calculate RTMR registers after extending them with a digest.
## Vault ### Vault
Part of this project is a key-value store that runs in a Trusted Execution Environment (TEE) and uses Remote Attestation Part of this project is a key-value store that runs in a Trusted Execution Environment (TEE) and uses Remote Attestation
for Authentication. The key-value store is implemented using Hashicorp Vault running in an Intel SGX enclave via the for Authentication. The key-value store is implemented using Hashicorp Vault running in an Intel SGX enclave via the
Gramine runtime. Gramine runtime.
- `teepot-vault`: A crate lib with for the TEE key-value store components:
- `tee-vault-unseal`: An enclave that uses the Vault API to unseal a vault as a proxy.
- `vault-unseal`: A client utility, that talks to `tee-vault-unseal` to unseal a vault.
- `tee-vault-admin`: An enclave that uses the Vault API to administer a vault as a proxy.
- `vault-admin`: A client utility, that talks to `tee-vault-admin` to administer a vault.
- `teepot-read` : A pre-exec utility that reads from the key-value store and passes the key-value pairs as
environment
variables to the enclave.
- `teepot-write` : A pre-exec utility that reads key-values from the environment variables and writes them to the
key-value store.
## Development ## Development
### Prerequisites ### Prerequisites
@ -77,7 +83,7 @@ $ nix run .#fmt
### Build as the CI would ### Build as the CI would
```shell ```shell
$ nix run github:nixos/nixpkgs/nixos-23.11#nixci $ nix run github:nixos/nixpkgs/nixos-24.11#nixci -- build
``` ```
### Build and test individual container ### Build and test individual container

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Matter Labs // Copyright (c) 2024-2025 Matter Labs
//! Pre-exec for binary running in a TEE needing attestation of a secret signing key //! Pre-exec for binary running in a TEE needing attestation of a secret signing key
@ -17,7 +17,7 @@ use std::io::Write;
use std::os::unix::process::CommandExt; use std::os::unix::process::CommandExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
use teepot::server::pki::make_signed_cert; use teepot::pki::make_signed_cert;
use tracing::error; use tracing::error;
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Simple TEE self-attestation test //! Simple TEE self-attestation test
@ -8,7 +8,7 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use teepot::server::attestation::get_quote_and_collateral; use teepot::quote::attestation::get_quote_and_collateral;
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};

View file

@ -10,7 +10,4 @@ repository.workspace = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
clap.workspace = true clap.workspace = true
hex.workspace = true
secp256k1.workspace = true
teepot.workspace = true teepot.workspace = true
zksync_basic_types.workspace = true

View file

@ -3,19 +3,14 @@
//! Tool for SGX attestation and batch signature verification //! Tool for SGX attestation and batch signature verification
use anyhow::{anyhow, bail, Context, Result}; use anyhow::{bail, Context, Result};
use clap::{Args, Parser, Subcommand}; use clap::Parser;
use core::convert::TryInto;
use hex::encode;
use secp256k1::Message;
use std::{fs, io::Read, path::PathBuf, str::FromStr, time::UNIX_EPOCH}; use std::{fs, io::Read, path::PathBuf, str::FromStr, time::UNIX_EPOCH};
use teepot::{ use teepot::{
client::TcbLevel,
ethereum::recover_signer,
prover::reportdata::ReportData,
quote::{error, tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult}, quote::{error, tee_qv_get_collateral, verify_quote_with_collateral, QuoteVerificationResult},
sgx::TcbLevel,
}; };
use zksync_basic_types::H256;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)] #[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)]
@ -23,9 +18,6 @@ struct Arguments {
/// Attestation quote proving the signature originated from a TEE enclave. /// Attestation quote proving the signature originated from a TEE enclave.
#[clap(name = "attestation_file", value_parser)] #[clap(name = "attestation_file", value_parser)]
attestation: ArgSource, attestation: ArgSource,
/// An optional subcommand, for instance, for optional signature verification.
#[clap(subcommand)]
command: Option<SubCommands>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -45,22 +37,6 @@ impl FromStr for ArgSource {
} }
} }
#[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: H256,
}
#[derive(Subcommand, Debug)]
enum SubCommands {
/// Verify a batch signature signed within a TEE enclave.
SignVerify(SignatureArgs),
}
fn main() -> Result<()> { fn main() -> Result<()> {
let args = Arguments::parse(); let args = Arguments::parse();
let attestation_quote_bytes = match args.attestation { let attestation_quote_bytes = match args.attestation {
@ -75,40 +51,6 @@ fn main() -> Result<()> {
}; };
let quote_verification_result = verify_attestation_quote(&attestation_quote_bytes)?; let quote_verification_result = verify_attestation_quote(&attestation_quote_bytes)?;
print_quote_verification_summary(&quote_verification_result); print_quote_verification_summary(&quote_verification_result);
match &args.command {
Some(SubCommands::SignVerify(signature_args)) => {
verify_signature(&quote_verification_result, signature_args)?;
}
None => {}
}
Ok(())
}
fn verify_signature(
quote_verification_result: &QuoteVerificationResult,
signature_args: &SignatureArgs,
) -> Result<()> {
let report_data = ReportData::try_from(quote_verification_result.quote.get_report_data())?;
let ethereum_address_from_quote = match report_data {
ReportData::V1(report_data_v1) => report_data_v1.ethereum_address,
_ => return Err(anyhow!("Unsupported report data version")),
};
let signature_bytes: &[u8] = &fs::read(&signature_args.signature_file)?;
let root_hash = Message::from_digest_slice(signature_args.root_hash.as_bytes())?;
let ethereum_address_from_signature = recover_signer(&signature_bytes.try_into()?, &root_hash)?;
let verification_successful = ethereum_address_from_signature == ethereum_address_from_quote;
println!(
"Signature '{}' {}. Ethereum address from attestation quote: {}. Ethereum address from signature: {}.",
encode(signature_bytes),
if verification_successful {
"verified successfully"
} else {
"verification failed"
},
encode(ethereum_address_from_quote),
encode(ethereum_address_from_signature)
);
Ok(()) Ok(())
} }

View file

@ -21,6 +21,6 @@ tokio.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
url.workspace = true url.workspace = true
zksync_basic_types.workspace = true zksync_basic_types = "=0.1.0"
zksync_types.workspace = true zksync_types = "=0.1.0"
zksync_web3_decl.workspace = true zksync_web3_decl = "=0.1.0"

View file

@ -9,13 +9,13 @@ use secp256k1::{
Message, SECP256K1, Message, SECP256K1,
}; };
use teepot::{ use teepot::{
client::TcbLevel,
ethereum::{public_key_to_ethereum_address, recover_signer}, ethereum::{public_key_to_ethereum_address, recover_signer},
prover::reportdata::ReportData, prover::reportdata::ReportData,
quote::{ quote::{
error::QuoteContext, tee_qv_get_collateral, verify_quote_with_collateral, error::QuoteContext, tee_qv_get_collateral, verify_quote_with_collateral,
QuoteVerificationResult, Report, QuoteVerificationResult, Report,
}, },
sgx::TcbLevel,
}; };
use tracing::{debug, info, trace, warn}; use tracing::{debug, info, trace, warn};
use zksync_basic_types::{L1BatchNumber, H256}; use zksync_basic_types::{L1BatchNumber, H256};

View file

@ -0,0 +1,35 @@
[package]
name = "teepot-vault"
description = "TEE secret manager"
license.workspace = true
version.workspace = true
edition.workspace = true
authors.workspace = true
repository.workspace = true
[dependencies]
actix-http = "3"
actix-web.workspace = true
anyhow.workspace = true
awc.workspace = true
bytes.workspace = true
clap.workspace = true
const-oid.workspace = true
futures-core = { version = "0.3.30", features = ["alloc"], default-features = false }
hex.workspace = true
intel-tee-quote-verification-rs.workspace = true
pgp.workspace = true
rustls.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_with.workspace = true
sha2.workspace = true
tdx-attest-rs.workspace = true
teepot.workspace = true
thiserror.workspace = true
tracing.workspace = true
webpki-roots = "0.26.1"
x509-cert.workspace = true
[dev-dependencies]
base64.workspace = true

View file

@ -13,6 +13,7 @@ anyhow.workspace = true
clap.workspace = true clap.workspace = true
serde.workspace = true serde.workspace = true
teepot.workspace = true teepot.workspace = true
teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-log.workspace = true tracing-log.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Matter Labs // Copyright (c) 2024-2025 Matter Labs
//! Server to handle requests to the Vault TEE //! Server to handle requests to the Vault TEE
@ -11,14 +11,17 @@ use anyhow::{Context, Result};
use clap::Parser; use clap::Parser;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;
use teepot::client::vault::VaultConnection;
use teepot::server::attestation::{get_quote_and_collateral, VaultAttestationArgs};
use teepot::server::pki::make_self_signed_cert;
use teepot::sgx::{parse_tcb_levels, EnumSet, TcbLevel}; use teepot::sgx::{parse_tcb_levels, EnumSet, TcbLevel};
use teepot_vault::{
client::vault::VaultConnection,
server::{
attestation::{get_quote_and_collateral, VaultAttestationArgs},
pki::make_self_signed_cert,
},
};
use tracing::{error, trace}; use tracing::{error, trace};
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::Registry; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)] #[command(author, version, about, long_about = None)]

View file

@ -18,6 +18,7 @@ rustls.workspace = true
serde_json.workspace = true serde_json.workspace = true
sha2.workspace = true sha2.workspace = true
teepot.workspace = true teepot.workspace = true
teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-actix-web.workspace = true tracing-actix-web.workspace = true
tracing-log.workspace = true tracing-log.workspace = true

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! post commands //! post commands
@ -9,12 +9,12 @@ use anyhow::{anyhow, Context, Result};
use awc::http::StatusCode; use awc::http::StatusCode;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::sync::Arc; use std::sync::Arc;
use teepot::client::vault::VaultConnection; use teepot_vault::client::vault::VaultConnection;
use teepot::json::http::{ use teepot_vault::json::http::{
VaultCommandRequest, VaultCommandResponse, VaultCommands, VaultCommandsResponse, VaultCommandRequest, VaultCommandResponse, VaultCommands, VaultCommandsResponse,
}; };
use teepot::json::secrets::{AdminConfig, AdminState}; use teepot_vault::json::secrets::{AdminConfig, AdminState};
use teepot::server::{signatures::VerifySig, HttpResponseError, Status}; use teepot_vault::server::{signatures::VerifySig, HttpResponseError, Status};
use tracing::instrument; use tracing::instrument;
/// Post command /// Post command

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! digest //! digest
@ -9,9 +9,9 @@ use anyhow::{Context, Result};
use awc::http::StatusCode; use awc::http::StatusCode;
use serde_json::json; use serde_json::json;
use std::sync::Arc; use std::sync::Arc;
use teepot::client::vault::VaultConnection; use teepot_vault::client::vault::VaultConnection;
use teepot::json::secrets::AdminState; use teepot_vault::json::secrets::AdminState;
use teepot::server::{HttpResponseError, Status}; use teepot_vault::server::{HttpResponseError, Status};
use tracing::instrument; use tracing::instrument;
/// Get last digest /// Get last digest

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2025 Matter Labs // Copyright (c) 2023-2024 Matter Labs
//! Server to handle requests to the Vault TEE //! Server to handle requests to the Vault TEE
@ -17,14 +17,14 @@ use digest::get_digest;
use rustls::ServerConfig; use rustls::ServerConfig;
use sign::post_sign; use sign::post_sign;
use std::{net::Ipv6Addr, sync::Arc}; use std::{net::Ipv6Addr, sync::Arc};
use teepot::{ use teepot::sgx::{parse_tcb_levels, EnumSet, TcbLevel};
use teepot_vault::{
json::http::{SignRequest, VaultCommandRequest, DIGEST_URL}, json::http::{SignRequest, VaultCommandRequest, DIGEST_URL},
server::{ server::{
attestation::{get_quote_and_collateral, VaultAttestationArgs}, attestation::{get_quote_and_collateral, VaultAttestationArgs},
new_json_cfg, new_json_cfg,
pki::make_self_signed_cert, pki::make_self_signed_cert,
}, },
sgx::{parse_tcb_levels, EnumSet, TcbLevel},
}; };
use tracing::{error, info}; use tracing::{error, info};
use tracing_actix_web::TracingLogger; use tracing_actix_web::TracingLogger;
@ -81,6 +81,8 @@ async fn main() -> Result<()> {
info!("Starting HTTPS server at port {}", args.port); info!("Starting HTTPS server at port {}", args.port);
info!("Quote verified! Connection secure!");
let server_state = Arc::new(ServerState { let server_state = Arc::new(ServerState {
report_data, report_data,
vault_attestation: args.attestation, vault_attestation: args.attestation,
@ -116,9 +118,9 @@ async fn main() -> Result<()> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use serde_json::json; use serde_json::json;
use teepot::json::http::{VaultCommand, VaultCommands}; use teepot_vault::json::http::{VaultCommand, VaultCommands};
const TEST_DATA: &str = include_str!("../../../crates/teepot/tests/data/test.json"); const TEST_DATA: &str = include_str!("../../../tests/data/test.json");
#[test] #[test]
fn test_vault_commands() { fn test_vault_commands() {

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! post signing request //! post signing request
@ -9,14 +9,14 @@ use actix_web::web;
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::sync::Arc; use std::sync::Arc;
use teepot::client::vault::VaultConnection;
use teepot::json::http::{SignRequest, SignRequestData, SignResponse};
use teepot::json::secrets::{AdminConfig, AdminState, SGXSigningKey};
use teepot::server::signatures::VerifySig as _;
use teepot::server::{HttpResponseError, Status};
use teepot::sgx::sign::PrivateKey as _; use teepot::sgx::sign::PrivateKey as _;
use teepot::sgx::sign::{Author, Signature}; use teepot::sgx::sign::{Author, Signature};
use teepot::sgx::sign::{Body, RS256PrivateKey}; use teepot::sgx::sign::{Body, RS256PrivateKey};
use teepot_vault::client::vault::VaultConnection;
use teepot_vault::json::http::{SignRequest, SignRequestData, SignResponse};
use teepot_vault::json::secrets::{AdminConfig, AdminState, SGXSigningKey};
use teepot_vault::server::signatures::VerifySig as _;
use teepot_vault::server::{HttpResponseError, Status};
use tracing::instrument; use tracing::instrument;
/// Sign command /// Sign command

View file

@ -15,6 +15,7 @@ clap.workspace = true
rustls.workspace = true rustls.workspace = true
serde_json.workspace = true serde_json.workspace = true
teepot.workspace = true teepot.workspace = true
teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-log.workspace = true tracing-log.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
use crate::{get_vault_status, UnsealServerState, Worker}; use crate::{get_vault_status, UnsealServerState, Worker};
use actix_web::error::ErrorBadRequest; use actix_web::error::ErrorBadRequest;
@ -7,10 +7,10 @@ use actix_web::{web, HttpResponse};
use anyhow::{anyhow, Context, Result}; use anyhow::{anyhow, Context, Result};
use awc::http::StatusCode; use awc::http::StatusCode;
use serde_json::json; use serde_json::json;
use teepot::client::TeeConnection; use teepot_vault::client::TeeConnection;
use teepot::json::http::{Init, InitResponse, VaultInitRequest}; use teepot_vault::json::http::{Init, InitResponse, VaultInitRequest};
use teepot::json::secrets::AdminConfig; use teepot_vault::json::secrets::AdminConfig;
use teepot::server::{HttpResponseError, Status}; use teepot_vault::server::{HttpResponseError, Status};
use tracing::{debug, error, info, instrument, trace}; use tracing::{debug, error, info, instrument, trace};
#[instrument(level = "info", name = "/v1/sys/init", skip_all)] #[instrument(level = "info", name = "/v1/sys/init", skip_all)]

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2025 Matter Labs // Copyright (c) 2023-2024 Matter Labs
//! Server to initialize and unseal the Vault TEE. //! Server to initialize and unseal the Vault TEE.
@ -15,27 +15,19 @@ use awc::Client;
use clap::Parser; use clap::Parser;
use init::post_init; use init::post_init;
use rustls::ServerConfig; use rustls::ServerConfig;
use std::{ use std::fmt::Debug;
fmt::Debug, use std::io::Read;
io::Read, use std::net::Ipv6Addr;
net::Ipv6Addr, use std::path::PathBuf;
path::PathBuf, use std::sync::{Arc, RwLock};
sync::{Arc, RwLock}, use std::time::Duration;
time::Duration, use teepot::pki::make_self_signed_cert;
}; use teepot::sgx::{parse_tcb_levels, EnumSet, TcbLevel};
use teepot::{ use teepot_vault::client::{AttestationArgs, TeeConnection};
client::{AttestationArgs, TeeConnection}, use teepot_vault::json::http::{Init, Unseal};
json::{ use teepot_vault::json::secrets::AdminConfig;
http::{Init, Unseal}, use teepot_vault::server::attestation::{get_quote_and_collateral, VaultAttestationArgs};
secrets::AdminConfig, use teepot_vault::server::new_json_cfg;
},
server::{
attestation::{get_quote_and_collateral, VaultAttestationArgs},
new_json_cfg,
pki::make_self_signed_cert,
},
sgx::{parse_tcb_levels, EnumSet, TcbLevel},
};
use tracing::{error, info}; use tracing::{error, info};
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
use crate::{get_vault_status, UnsealServerConfig, UnsealServerState, Worker, VAULT_TOKEN_HEADER}; use crate::{get_vault_status, UnsealServerConfig, UnsealServerState, Worker, VAULT_TOKEN_HEADER};
use actix_web::http::StatusCode; use actix_web::http::StatusCode;
@ -12,11 +12,11 @@ use std::fs::File;
use std::future::Future; use std::future::Future;
use std::io::Read; use std::io::Read;
use std::time::Duration; use std::time::Duration;
use teepot::client::vault::VaultConnection; use teepot_vault::client::vault::VaultConnection;
use teepot::client::TeeConnection; use teepot_vault::client::TeeConnection;
use teepot::json::http::Unseal; use teepot_vault::json::http::Unseal;
use teepot::json::secrets::{AdminConfig, AdminState}; use teepot_vault::json::secrets::{AdminConfig, AdminState};
use teepot::server::{HttpResponseError, Status}; use teepot_vault::server::{HttpResponseError, Status};
use tracing::{debug, error, info, instrument, trace}; use tracing::{debug, error, info, instrument, trace};
#[instrument(level = "info", name = "/v1/sys/unseal", skip_all)] #[instrument(level = "info", name = "/v1/sys/unseal", skip_all)]

View file

@ -15,7 +15,7 @@ anyhow.workspace = true
awc.workspace = true awc.workspace = true
clap.workspace = true clap.workspace = true
serde_json.workspace = true serde_json.workspace = true
teepot.workspace = true teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-log.workspace = true tracing-log.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Get the secrets from a Vault TEE and pass them as environment variables to a command //! Get the secrets from a Vault TEE and pass them as environment variables to a command
@ -12,8 +12,8 @@ use serde_json::Value;
use std::collections::HashMap; use std::collections::HashMap;
use std::os::unix::process::CommandExt; use std::os::unix::process::CommandExt;
use std::process::Command; use std::process::Command;
use teepot::client::vault::VaultConnection; use teepot_vault::client::vault::VaultConnection;
use teepot::server::attestation::VaultAttestationArgs; use teepot_vault::server::attestation::VaultAttestationArgs;
use tracing::{debug, info, warn}; use tracing::{debug, info, warn};
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};

View file

@ -15,7 +15,7 @@ anyhow.workspace = true
awc.workspace = true awc.workspace = true
clap.workspace = true clap.workspace = true
serde_json.workspace = true serde_json.workspace = true
teepot.workspace = true teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-log.workspace = true tracing-log.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Write secrets to a Vault TEE from environment variables //! Write secrets to a Vault TEE from environment variables
@ -9,10 +9,8 @@
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use clap::Parser; use clap::Parser;
use serde_json::Value; use serde_json::Value;
use std::collections::HashMap; use std::{collections::HashMap, env};
use std::env; use teepot_vault::{client::vault::VaultConnection, server::attestation::VaultAttestationArgs};
use teepot::client::vault::VaultConnection;
use teepot::server::attestation::VaultAttestationArgs;
use tracing::{debug, info, warn}; use tracing::{debug, info, warn};
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};

View file

@ -16,4 +16,5 @@ hex.workspace = true
pgp.workspace = true pgp.workspace = true
serde_json.workspace = true serde_json.workspace = true
teepot.workspace = true teepot.workspace = true
teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true

View file

@ -13,8 +13,8 @@ Verified signature for `81A312C59D679D930FA9E8B06D728F29A2DBABF8`
--sgx-mrsigner c5591a72b8b86e0d8814d6e8750e3efe66aea2d102b8ba2405365559b858697d \ --sgx-mrsigner c5591a72b8b86e0d8814d6e8750e3efe66aea2d102b8ba2405365559b858697d \
--sgx-allowed-tcb-levels SwHardeningNeeded \ --sgx-allowed-tcb-levels SwHardeningNeeded \
--server https://127.0.0.1:8444 \ --server https://127.0.0.1:8444 \
bin/tee-vault-admin/tests/data/test.json \ crates/teepot-vault/tests/data/test.json \
bin/tee-vault-admin/tests/data/test.json.asc crates/teepot-vault/tests/data/test.json.asc
2023-08-04T10:51:14.919941Z INFO vault_admin: Quote verified! Connection secure! 2023-08-04T10:51:14.919941Z INFO vault_admin: Quote verified! Connection secure!
2023-08-04T10:51:14.920430Z INFO tee_client: Getting attestation report 2023-08-04T10:51:14.920430Z INFO tee_client: Getting attestation report

View file

@ -12,16 +12,18 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use teepot::{ use teepot::{
log::{setup_logging, LogLevelParser},
sgx::sign::Signature,
};
use teepot_vault::{
client::{AttestationArgs, TeeConnection}, client::{AttestationArgs, TeeConnection},
json::http::{ json::http::{
SignRequest, SignRequestData, SignResponse, VaultCommandRequest, VaultCommands, SignRequest, SignRequestData, SignResponse, VaultCommandRequest, VaultCommands,
VaultCommandsResponse, DIGEST_URL, VaultCommandsResponse, DIGEST_URL,
}, },
log::{setup_logging, LogLevelParser},
server::signatures::verify_sig, server::signatures::verify_sig,
sgx::sign::Signature,
}; };
use tracing::{error, info, level_filters::LevelFilter}; use tracing::{error, level_filters::LevelFilter};
#[derive(Args, Debug)] #[derive(Args, Debug)]
struct SendArgs { struct SendArgs {

View file

@ -13,7 +13,7 @@ anyhow.workspace = true
base64.workspace = true base64.workspace = true
clap.workspace = true clap.workspace = true
serde_json.workspace = true serde_json.workspace = true
teepot.workspace = true teepot-vault.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-log.workspace = true tracing-log.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true

View file

@ -1,18 +1,18 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
use anyhow::{anyhow, bail, Context, Result}; use anyhow::{anyhow, bail, Context, Result};
use base64::{engine::general_purpose, Engine as _}; use base64::{engine::general_purpose, Engine as _};
use clap::{Args, Parser, Subcommand}; use clap::{Args, Parser, Subcommand};
use serde_json::Value; use serde_json::Value;
use std::fs::File; use std::{fs::File, io::Read};
use std::io::Read; use teepot_vault::{
use teepot::client::{AttestationArgs, TeeConnection}; client::{AttestationArgs, TeeConnection},
use teepot::json::http::{Init, InitResponse, Unseal}; json::http::{Init, InitResponse, Unseal},
};
use tracing::{error, info, trace, warn}; use tracing::{error, info, trace, warn};
use tracing_log::LogTracer; use tracing_log::LogTracer;
use tracing_subscriber::Registry; use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry};
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
#[derive(Args, Debug)] #[derive(Args, Debug)]
pub struct InitArgs { pub struct InitArgs {

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2025 Matter Labs // Copyright (c) 2023-2024 Matter Labs
//! Helper functions for CLI clients to verify Intel SGX enclaves and other TEEs. //! Helper functions for CLI clients to verify Intel SGX enclaves and other TEEs.
@ -8,15 +8,7 @@
pub mod vault; pub mod vault;
use crate::{ use crate::server::pki::{RaTlsCollateralExtension, RaTlsQuoteExtension};
quote::Report,
server::pki::{RaTlsCollateralExtension, RaTlsQuoteExtension},
sgx::Quote,
};
pub use crate::{
quote::{verify_quote_with_collateral, QuoteVerificationResult},
sgx::{parse_tcb_levels, sgx_ql_qv_result_t, EnumSet, TcbLevel},
};
use actix_web::http::header; use actix_web::http::header;
use anyhow::Result; use anyhow::Result;
use awc::{Client, Connector}; use awc::{Client, Connector};
@ -33,6 +25,11 @@ use rustls::{
}; };
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::{sync::Arc, time, time::Duration}; use std::{sync::Arc, time, time::Duration};
use teepot::{quote::Report, sgx::Quote};
pub use teepot::{
quote::{verify_quote_with_collateral, QuoteVerificationResult},
sgx::{parse_tcb_levels, sgx_ql_qv_result_t, EnumSet, TcbLevel},
};
use tracing::{debug, error, info, trace, warn}; use tracing::{debug, error, info, trace, warn};
use x509_cert::{ use x509_cert::{
der::{Decode as _, Encode as _}, der::{Decode as _, Encode as _},

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Helper functions for CLI clients to verify Intel SGX enclaves and other TEEs. //! Helper functions for CLI clients to verify Intel SGX enclaves and other TEEs.
@ -9,15 +9,8 @@
use super::{AttestationArgs, TeeConnection}; use super::{AttestationArgs, TeeConnection};
use crate::{ use crate::{
json::http::{AuthRequest, AuthResponse}, json::http::{AuthRequest, AuthResponse},
quote::error::QuoteContext,
server::{pki::make_self_signed_cert, AnyHowResponseError, HttpResponseError, Status}, server::{pki::make_self_signed_cert, AnyHowResponseError, HttpResponseError, Status},
}; };
pub use crate::{
quote::{verify_quote_with_collateral, QuoteVerificationResult},
sgx::{
parse_tcb_levels, sgx_gramine_get_quote, sgx_ql_qv_result_t, Collateral, EnumSet, TcbLevel,
},
};
use actix_http::error::PayloadError; use actix_http::error::PayloadError;
use actix_web::{http::header, ResponseError}; use actix_web::{http::header, ResponseError};
use anyhow::{anyhow, bail, Context, Result}; use anyhow::{anyhow, bail, Context, Result};
@ -35,6 +28,13 @@ use std::{
sync::Arc, sync::Arc,
time, time,
}; };
use teepot::quote::error::QuoteContext;
pub use teepot::{
quote::{verify_quote_with_collateral, QuoteVerificationResult},
sgx::{
parse_tcb_levels, sgx_gramine_get_quote, sgx_ql_qv_result_t, Collateral, EnumSet, TcbLevel,
},
};
use tracing::{debug, error, info, trace}; use tracing::{debug, error, info, trace};
const VAULT_TOKEN_HEADER: &str = "X-Vault-Token"; const VAULT_TOKEN_HEADER: &str = "X-Vault-Token";

View file

@ -1,15 +1,12 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Common types for the teepot http JSON API //! Common types for the teepot http JSON API
use crate::sgx::Collateral;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use serde_with::base64::Base64; use serde_with::{base64::Base64, serde_as};
use serde_with::serde_as;
use std::fmt::Display; use std::fmt::Display;
use std::sync::Arc;
/// The unseal request data /// The unseal request data
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
@ -23,15 +20,6 @@ impl Unseal {
pub const URL: &'static str = "/v1/sys/unseal"; pub const URL: &'static str = "/v1/sys/unseal";
} }
/// The attestation response
#[derive(Debug, Serialize, Deserialize)]
pub struct AttestationResponse {
/// The quote
pub quote: Arc<[u8]>,
/// The collateral
pub collateral: Arc<Collateral>,
}
/// The init request data /// The init request data
#[serde_as] #[serde_as]
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]

View file

@ -1,12 +1,12 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Common types for the teepot secrets JSON API //! Common types for the teepot secrets JSON API
use crate::sgx::sign::Zeroizing;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::base64::Base64; use serde_with::base64::Base64;
use serde_with::serde_as; use serde_with::serde_as;
use teepot::sgx::sign::Zeroizing;
/// Configuration for the admin tee /// Configuration for the admin tee
#[serde_as] #[serde_as]

View file

@ -0,0 +1,24 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2025 Matter Labs
//! Helper functions to verify Intel SGX enclaves and other TEEs.
#![deny(missing_docs)]
#![deny(clippy::all)]
pub mod client;
pub mod json;
pub mod server;
pub mod tdx;
/// pad a byte slice to a fixed sized array
pub fn pad<const T: usize>(input: &[u8]) -> [u8; T] {
let mut output = [0; T];
let len = input.len();
if len > T {
output.copy_from_slice(&input[..T]);
} else {
output[..len].copy_from_slice(input);
}
output
}

View file

@ -0,0 +1,56 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2025 Matter Labs
//! Common attestation API for all TEEs
use crate::client::AttestationArgs;
use clap::Args;
use serde::{Deserialize, Serialize};
pub use teepot::{
quote::{
attestation::get_quote_and_collateral, error::QuoteContext, get_quote,
verify_quote_with_collateral, QuoteVerificationResult,
},
sgx::{parse_tcb_levels, Collateral, EnumSet, TcbLevel},
};
/// Options and arguments needed to attest a TEE
#[derive(Args, Debug, Clone, Serialize, Deserialize, Default)]
pub struct VaultAttestationArgs {
/// hex encoded SGX mrsigner of the enclave to attest
#[arg(long, env = "VAULT_SGX_MRSIGNER")]
pub vault_sgx_mrsigner: Option<String>,
/// hex encoded SGX mrenclave of the enclave to attest
#[arg(long, env = "VAULT_SGX_MRENCLAVE")]
pub vault_sgx_mrenclave: Option<String>,
/// URL of the server
#[arg(long, required = true, env = "VAULT_ADDR")]
pub vault_addr: String,
/// allowed TCB levels, comma separated:
/// Ok, ConfigNeeded, ConfigAndSwHardeningNeeded, SwHardeningNeeded, OutOfDate, OutOfDateConfigNeeded
#[arg(long, value_parser = parse_tcb_levels, env = "VAULT_SGX_ALLOWED_TCB_LEVELS")]
pub vault_sgx_allowed_tcb_levels: Option<EnumSet<TcbLevel>>,
}
impl From<VaultAttestationArgs> for AttestationArgs {
fn from(value: VaultAttestationArgs) -> Self {
AttestationArgs {
sgx_mrsigner: value.vault_sgx_mrsigner,
sgx_mrenclave: value.vault_sgx_mrenclave,
server: value.vault_addr,
sgx_allowed_tcb_levels: value.vault_sgx_allowed_tcb_levels,
}
}
}
impl From<&VaultAttestationArgs> for AttestationArgs {
fn from(value: &VaultAttestationArgs) -> Self {
AttestationArgs {
sgx_mrsigner: value.vault_sgx_mrsigner.clone(),
sgx_mrenclave: value.vault_sgx_mrenclave.clone(),
server: value.vault_addr.clone(),
sgx_allowed_tcb_levels: value.vault_sgx_allowed_tcb_levels,
}
}
}

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! # tee-server //! # tee-server
@ -7,18 +7,19 @@
#![deny(clippy::all)] #![deny(clippy::all)]
pub mod attestation; pub mod attestation;
pub mod pki;
pub mod signatures; pub mod signatures;
use actix_web::http::StatusCode; use actix_web::{
use actix_web::web::Bytes; error, http::StatusCode, web::Bytes, HttpMessage, HttpRequest, HttpResponse, ResponseError,
use actix_web::{error, HttpRequest, HttpResponse}; };
use actix_web::{HttpMessage, ResponseError};
use anyhow::anyhow; use anyhow::anyhow;
use awc::error::{PayloadError, SendRequestError}; use awc::{
use awc::ClientResponse; error::{PayloadError, SendRequestError},
ClientResponse,
};
use futures_core::Stream; use futures_core::Stream;
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
pub use teepot::pki;
use tracing::error; use tracing::error;
/// Anyhow error with an HTTP status code /// Anyhow error with an HTTP status code

View file

@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2025 Matter Labs
//! Intel TDX helper functions.
pub mod rtmr;
pub use intel_tee_quote_verification_rs::Collateral;
use tdx_attest_rs::{tdx_att_get_quote, tdx_attest_error_t, tdx_report_data_t};
pub use teepot::sgx::tcblevel::{parse_tcb_levels, EnumSet, TcbLevel};
use teepot::sgx::QuoteError;
/// Get a TDX quote
pub fn tgx_get_quote(report_data_bytes: &[u8; 64]) -> Result<Box<[u8]>, QuoteError> {
let mut tdx_report_data = tdx_report_data_t { d: [0; 64usize] };
tdx_report_data.d.copy_from_slice(report_data_bytes);
let (error, quote) = tdx_att_get_quote(Some(&tdx_report_data), None, None, 0);
if error == tdx_attest_error_t::TDX_ATTEST_SUCCESS {
if let Some(quote) = quote {
Ok(quote.into())
} else {
Err(QuoteError::TdxAttGetQuote {
msg: "tdx_att_get_quote: No quote returned".into(),
inner: error,
})
}
} else {
Err(error.into())
}
}

View file

@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024-2025 Matter Labs
//! rtmr event data
use teepot::sgx::QuoteError;
/// The actual rtmr event data handled in DCAP
#[repr(C, packed)]
pub struct TdxRtmrEvent {
/// Always 1
version: u32,
/// The RTMR that will be extended. As defined in
/// https://github.com/confidential-containers/td-shim/blob/main/doc/tdshim_spec.md#td-measurement
/// we will use RTMR 3 for guest application code and configuration.
rtmr_index: u64,
/// Data that will be used to extend RTMR
extend_data: [u8; 48usize],
/// Not used in DCAP
event_type: u32,
/// Always 0
event_data_size: u32,
/// Not used in DCAP
event_data: Vec<u8>,
}
impl Default for TdxRtmrEvent {
fn default() -> Self {
Self {
extend_data: [0; 48],
version: 1,
rtmr_index: 3,
event_type: 0,
event_data_size: 0,
event_data: Vec::new(),
}
}
}
impl TdxRtmrEvent {
/// use the extend data
pub fn with_extend_data(mut self, extend_data: [u8; 48]) -> Self {
self.extend_data = extend_data;
self
}
/// extend the rtmr index
pub fn with_rtmr_index(mut self, rtmr_index: u64) -> Self {
self.rtmr_index = rtmr_index;
self
}
/// extending the index, consuming self
pub fn extend(self) -> Result<(), QuoteError> {
let event: Vec<u8> = self.into();
match tdx_attest_rs::tdx_att_extend(&event) {
tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => Ok(()),
error_code => Err(error_code.into()),
}
}
}
impl From<TdxRtmrEvent> for Vec<u8> {
fn from(val: TdxRtmrEvent) -> Self {
let event_ptr = &val as *const TdxRtmrEvent as *const u8;
let event_data_size = std::mem::size_of::<u8>() * val.event_data_size as usize;
let res_size = std::mem::size_of::<u32>() * 3
+ std::mem::size_of::<u64>()
+ std::mem::size_of::<[u8; 48]>()
+ event_data_size;
let mut res = vec![0; res_size];
unsafe {
for (i, chunk) in res.iter_mut().enumerate().take(res_size - event_data_size) {
*chunk = *event_ptr.add(i);
}
}
let event_data = val.event_data;
for i in 0..event_data_size {
res[i + res_size - event_data_size] = event_data[i];
}
res
}
}

View file

@ -1,6 +1,6 @@
[package] [package]
name = "teepot" name = "teepot"
description = "TEE secret manager" description = "TEE utilities"
# no MIT license, because of copied code from: # no MIT license, because of copied code from:
# * https://github.com/enarx/enarx # * https://github.com/enarx/enarx
# * https://github.com/enarx/sgx # * https://github.com/enarx/sgx
@ -11,18 +11,13 @@ authors.workspace = true
repository.workspace = true repository.workspace = true
[dependencies] [dependencies]
actix-http.workspace = true
actix-web.workspace = true
anyhow.workspace = true anyhow.workspace = true
async-trait.workspace = true async-trait.workspace = true
awc.workspace = true
bytemuck.workspace = true bytemuck.workspace = true
bytes.workspace = true
clap.workspace = true clap.workspace = true
config.workspace = true config.workspace = true
const-oid.workspace = true const-oid.workspace = true
enumset.workspace = true enumset.workspace = true
futures-core.workspace = true
getrandom.workspace = true getrandom.workspace = true
hex.workspace = true hex.workspace = true
intel-tee-quote-verification-rs.workspace = true intel-tee-quote-verification-rs.workspace = true
@ -34,7 +29,6 @@ opentelemetry-otlp.workspace = true
opentelemetry-semantic-conventions.workspace = true opentelemetry-semantic-conventions.workspace = true
opentelemetry_sdk.workspace = true opentelemetry_sdk.workspace = true
p256.workspace = true p256.workspace = true
pgp.workspace = true
pkcs8.workspace = true pkcs8.workspace = true
reqwest.workspace = true reqwest.workspace = true
rsa.workspace = true rsa.workspace = true
@ -42,7 +36,6 @@ rustls.workspace = true
secp256k1 = { workspace = true, features = ["recovery"] } secp256k1 = { workspace = true, features = ["recovery"] }
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
serde_with.workspace = true
sha2.workspace = true sha2.workspace = true
sha3.workspace = true sha3.workspace = true
signature.workspace = true signature.workspace = true
@ -52,7 +45,6 @@ tracing.workspace = true
tracing-futures.workspace = true tracing-futures.workspace = true
tracing-log.workspace = true tracing-log.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
webpki-roots.workspace = true
x509-cert.workspace = true x509-cert.workspace = true
zeroize.workspace = true zeroize.workspace = true
@ -61,4 +53,3 @@ base64.workspace = true
testaso.workspace = true testaso.workspace = true
tokio.workspace = true tokio.workspace = true
tracing-test.workspace = true tracing-test.workspace = true
zksync_basic_types.workspace = true

View file

@ -37,7 +37,6 @@ pub fn public_key_to_ethereum_address(public: &PublicKey) -> [u8; 20] {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use secp256k1::{Secp256k1, SecretKey}; use secp256k1::{Secp256k1, SecretKey};
use zksync_basic_types::H256;
use super::*; use super::*;
@ -71,10 +70,10 @@ mod tests {
assert_eq!(address, expected_address.as_slice()); assert_eq!(address, expected_address.as_slice());
// Generate a random root hash, create a message from the hash, and sign the message using // Take a root hash, create a message from the hash, and sign the message using
// the secret key // the secret key
let root_hash = H256::random(); let root_hash = b"12345678901234567890123456789012";
let root_hash_bytes = root_hash.as_bytes(); let root_hash_bytes = root_hash.as_slice();
let msg_to_sign = Message::from_digest(root_hash_bytes.try_into().unwrap()); let msg_to_sign = Message::from_digest(root_hash_bytes.try_into().unwrap());
let signature = sign_message(&secret_key, msg_to_sign).unwrap(); let signature = sign_message(&secret_key, msg_to_sign).unwrap();

View file

@ -6,14 +6,12 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(clippy::all)] #![deny(clippy::all)]
pub mod client;
pub mod config; pub mod config;
pub mod ethereum; pub mod ethereum;
pub mod json;
pub mod log; pub mod log;
pub mod pki;
pub mod prover; pub mod prover;
pub mod quote; pub mod quote;
pub mod server;
pub mod sgx; pub mod sgx;
pub mod tdx; pub mod tdx;

View file

@ -1,18 +1,15 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
//! Common attestation API for all TEEs //! Common attestation API for all TEEs
use crate::{ use crate::{
client::AttestationArgs,
json::http::AttestationResponse,
quote::{ quote::{
error::QuoteContext, get_quote, verify_quote_with_collateral, QuoteVerificationResult, error::QuoteContext, get_quote, verify_quote_with_collateral, QuoteVerificationResult,
}, },
sgx::{parse_tcb_levels, Collateral, EnumSet, TcbLevel}, sgx::{Collateral, EnumSet, TcbLevel},
}; };
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use clap::Args;
use intel_tee_quote_verification_rs::tee_qv_get_collateral; use intel_tee_quote_verification_rs::tee_qv_get_collateral;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
@ -28,6 +25,15 @@ struct Attestation {
earliest_expiration_date: i64, earliest_expiration_date: i64,
} }
/// The attestation response
#[derive(Debug, Serialize, Deserialize)]
pub struct AttestationResponse {
/// The quote
pub quote: Arc<[u8]>,
/// The collateral
pub collateral: Arc<Collateral>,
}
/// Returns the quote and collateral for the current TEE. /// Returns the quote and collateral for the current TEE.
/// ///
/// if `allowed_tcb_levels` is `None`, then any TCB level is accepted. /// if `allowed_tcb_levels` is `None`, then any TCB level is accepted.
@ -110,43 +116,3 @@ pub fn get_quote_and_collateral(
Ok(AttestationResponse { quote, collateral }) Ok(AttestationResponse { quote, collateral })
} }
/// Options and arguments needed to attest a TEE
#[derive(Args, Debug, Clone, Serialize, Deserialize, Default)]
pub struct VaultAttestationArgs {
/// hex encoded SGX mrsigner of the enclave to attest
#[arg(long, env = "VAULT_SGX_MRSIGNER")]
pub vault_sgx_mrsigner: Option<String>,
/// hex encoded SGX mrenclave of the enclave to attest
#[arg(long, env = "VAULT_SGX_MRENCLAVE")]
pub vault_sgx_mrenclave: Option<String>,
/// URL of the server
#[arg(long, required = true, env = "VAULT_ADDR")]
pub vault_addr: String,
/// allowed TCB levels, comma separated:
/// Ok, ConfigNeeded, ConfigAndSwHardeningNeeded, SwHardeningNeeded, OutOfDate, OutOfDateConfigNeeded
#[arg(long, value_parser = parse_tcb_levels, env = "VAULT_SGX_ALLOWED_TCB_LEVELS")]
pub vault_sgx_allowed_tcb_levels: Option<EnumSet<TcbLevel>>,
}
impl From<VaultAttestationArgs> for AttestationArgs {
fn from(value: VaultAttestationArgs) -> Self {
AttestationArgs {
sgx_mrsigner: value.vault_sgx_mrsigner,
sgx_mrenclave: value.vault_sgx_mrenclave,
server: value.vault_addr,
sgx_allowed_tcb_levels: value.vault_sgx_allowed_tcb_levels,
}
}
}
impl From<&VaultAttestationArgs> for AttestationArgs {
fn from(value: &VaultAttestationArgs) -> Self {
AttestationArgs {
sgx_mrsigner: value.vault_sgx_mrsigner.clone(),
sgx_mrenclave: value.vault_sgx_mrenclave.clone(),
server: value.vault_addr.clone(),
sgx_allowed_tcb_levels: value.vault_sgx_allowed_tcb_levels,
}
}
}

View file

@ -1,10 +1,12 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2023-2024 Matter Labs // Copyright (c) 2023-2025 Matter Labs
// Parts of it are Copyright (c) 2024 Phala Network // Parts of it are Copyright (c) 2024 Phala Network
// and copied from https://github.com/Phala-Network/dcap-qvl // and copied from https://github.com/Phala-Network/dcap-qvl
//! Get a quote from a TEE //! Get a quote from a TEE
pub mod attestation;
pub mod error; pub mod error;
use crate::{ use crate::{

View file

@ -11,13 +11,13 @@ $ docker compose up
```bash ```bash
cd teepot cd teepot
gpg --export username@example.com | base64 > gpgkey.pub gpg --export username@example.com | base64 > assets/gpgkey.pub
export GPG_TTY="$(tty)" export GPG_TTY="$(tty)"
gpg-connect-agent updatestartuptty /bye gpg-connect-agent updatestartuptty /bye
RUST_LOG=info cargo run -p vault-unseal -- --sgx-mrsigner c5591a72b8b86e0d8814d6e8750e3efe66aea2d102b8ba2405365559b858697d --sgx-allowed-tcb-levels SwHardeningNeeded --server https://20.172.154.218:8443 init --unseal-threshold 1 -u bin/tee-vault-admin/tests/data/gpgkey.pub --admin-threshold 1 -a bin/tee-vault-admin/tests/data/gpgkey.pub --admin-tee-mrenclave 21c8c1a4dbcce04798f5119eb47203084bc74e564a3c954d1a21172c656cb801 RUST_LOG=info cargo run -p vault-unseal -- --sgx-mrsigner c5591a72b8b86e0d8814d6e8750e3efe66aea2d102b8ba2405365559b858697d --sgx-allowed-tcb-levels SwHardeningNeeded --server https://20.172.154.218:8443 init --unseal-threshold 1 -u assets/gpgkey.pub --admin-threshold 1 -a assets/gpgkey.pub --admin-tee-mrenclave 21c8c1a4dbcce04798f5119eb47203084bc74e564a3c954d1a21172c656cb801
Finished dev [unoptimized + debuginfo] target(s) in 0.09s Finished dev [unoptimized + debuginfo] target(s) in 0.09s
Running `target/debug/vault-unseal --sgx-mrsigner c5591a72b8b86e0d8814d6e8750e3efe66aea2d102b8ba2405365559b858697d --sgx-allowed-tcb-levels SwHardeningNeeded --server 'https://20.172.154.218:8443' init --unseal-threshold 1 -u bin/tee-vault-admin/tests/data/gpgkey.pub --admin-threshold 1 -a bin/tee-vault-admin/tests/data/gpgkey.pub --admin-tee-mrenclave 21c8c1a4dbcce04798f5119eb47203084bc74e564a3c954d1a21172c656cb801` Running `target/debug/vault-unseal --sgx-mrsigner c5591a72b8b86e0d8814d6e8750e3efe66aea2d102b8ba2405365559b858697d --sgx-allowed-tcb-levels SwHardeningNeeded --server 'https://20.172.154.218:8443' init --unseal-threshold 1 -u assets/gpgkey.pub --admin-threshold 1 -a assets/gpgkey.pub --admin-tee-mrenclave 21c8c1a4dbcce04798f5119eb47203084bc74e564a3c954d1a21172c656cb801`
2023-08-23T14:47:56.902422Z INFO tee_client: Getting attestation report 2023-08-23T14:47:56.902422Z INFO tee_client: Getting attestation report
2023-08-23T14:47:57.340877Z INFO tee_client: Checked or set server certificate public key hash `b4bf52fdb37431c8531fb310be389c2d17ad9bd41d662e10308c9147c007d0d0` 2023-08-23T14:47:57.340877Z INFO tee_client: Checked or set server certificate public key hash `b4bf52fdb37431c8531fb310be389c2d17ad9bd41d662e10308c9147c007d0d0`
2023-08-23T14:47:57.741599Z INFO tee_client: Verifying attestation report 2023-08-23T14:47:57.741599Z INFO tee_client: Verifying attestation report
@ -155,9 +155,9 @@ container.
--server https://127.0.0.1:8443 \ --server https://127.0.0.1:8443 \
init \ init \
--unseal-threshold 1 \ --unseal-threshold 1 \
--unseal-pgp-key-file ./tests/data/gpgkey.pub \ --unseal-pgp-key-file ./assets/gpgkey.pub \
--admin-threshold 1 \ --admin-threshold 1 \
--admin-pgp-key-file ./tests/data/gpgkey.pub \ --admin-pgp-key-file ./assets/gpgkey.pub \
--admin-tee-mrenclave 98a540dd7056584e2009c7cf7374f932fbb8e30a4c66cc815c9809620653f751 --admin-tee-mrenclave 98a540dd7056584e2009c7cf7374f932fbb8e30a4c66cc815c9809620653f751
``` ```

View file

@ -37,11 +37,12 @@ let
fileset = unions [ fileset = unions [
# Default files from crane (Rust and cargo files) # Default files from crane (Rust and cargo files)
(craneLib.fileset.commonCargoSources inputs.src) (craneLib.fileset.commonCargoSources inputs.src)
(fileFilter (file: file.hasExt "hcl") (inputs.src + "/bin")) (fileFilter (file: file.hasExt "hcl") (inputs.src + "/crates/teepot-vault/bin"))
# deny.toml and friends # deny.toml and friends
(fileFilter (file: file.hasExt "toml") inputs.src) (fileFilter (file: file.hasExt "toml") inputs.src)
# Custom test data files # Custom test data files
(maybeMissing (inputs.src + "/crates/teepot/tests/data")) (maybeMissing (inputs.src + "/crates/teepot/tests/data"))
(maybeMissing (inputs.src + "/crates/teepot-vault/tests/data"))
]; ];
}; };