mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 07:03:56 +02:00
chore: split-out vault code from teepot
in teepot-vault
Signed-off-by: Harald Hoyer <harald@matterlabs.dev>
This commit is contained in:
parent
63c16b1177
commit
f8bd9e6a08
61 changed files with 450 additions and 308 deletions
51
Cargo.lock
generated
51
Cargo.lock
generated
|
@ -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]]
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
46
README.md
46
README.md
|
@ -2,31 +2,37 @@
|
||||||
|
|
||||||
## 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.
|
|
||||||
- `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.
|
|
||||||
- `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.
|
|
||||||
- `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.
|
|
||||||
- `tdx-extend`: A utility to extend an RTMR register with a hash value.
|
|
||||||
- `rtmr-calc`: A utility to calculate RTMR1 and RTMR2 from a GPT disk, the linux kernel, the linux initrd
|
|
||||||
and a UKI (unified kernel image).
|
|
||||||
- `sha384-extend`: A utility to calculate RTMR registers after extending them with a digest.
|
|
||||||
|
|
||||||
## Vault
|
- `teepot`: The main rust crate that abstracts TEEs.
|
||||||
|
- `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
|
||||||
|
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,
|
||||||
|
measures the sha384 of the URL to RTMR3 and launches the container.
|
||||||
|
- `tdx-extend`: A utility to extend an RTMR register with a hash value.
|
||||||
|
- `rtmr-calc`: A utility to calculate RTMR1 and RTMR2 from a GPT disk, the linux kernel, the linux initrd
|
||||||
|
and a UKI (unified kernel image).
|
||||||
|
- `sha384-extend`: A utility to calculate RTMR registers after extending them with a digest.
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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("e_verification_result);
|
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 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(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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};
|
||||||
|
|
35
crates/teepot-vault/Cargo.toml
Normal file
35
crates/teepot-vault/Cargo.toml
Normal 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
|
|
@ -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
|
|
@ -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)]
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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() {
|
|
@ -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
|
|
@ -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
|
|
@ -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)]
|
|
@ -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};
|
|
@ -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)]
|
|
@ -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
|
|
@ -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};
|
|
@ -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
|
|
@ -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};
|
|
@ -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
|
|
@ -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
|
|
@ -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 {
|
|
@ -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
|
|
@ -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 {
|
|
@ -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 _},
|
|
@ -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";
|
|
@ -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)]
|
|
@ -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]
|
24
crates/teepot-vault/src/lib.rs
Normal file
24
crates/teepot-vault/src/lib.rs
Normal 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
|
||||||
|
}
|
56
crates/teepot-vault/src/server/attestation.rs
Normal file
56
crates/teepot-vault/src/server/attestation.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
32
crates/teepot-vault/src/tdx/mod.rs
Normal file
32
crates/teepot-vault/src/tdx/mod.rs
Normal 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())
|
||||||
|
}
|
||||||
|
}
|
90
crates/teepot-vault/src/tdx/rtmr.rs
Normal file
90
crates/teepot-vault/src/tdx/rtmr.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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::{
|
||||||
|
|
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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"))
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue