quote verification with intel-tee-quote-verification

This commit is contained in:
Hendrik Eeckhaut
2025-04-02 14:59:23 +02:00
commit 542474308c
12 changed files with 617 additions and 0 deletions

View File

@@ -0,0 +1 @@
target/

View File

@@ -0,0 +1 @@
/target

View File

@@ -0,0 +1,387 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "bindgen"
version = "0.65.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5"
dependencies = [
"bitflags 1.3.2",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn",
"which",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "errno"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "glob"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
[[package]]
name = "home"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [
"windows-sys",
]
[[package]]
name = "intel-tee-quote-verification-rs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea8b29c761628cbd67198dca9687231ba2ff1076040499cfb5c771a7c0e0b12d"
dependencies = [
"intel-tee-quote-verification-sys",
]
[[package]]
name = "intel-tee-quote-verification-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93c8bc48d598fa48310e41f65a706e0beb2a74f5f9e5a26c5c2ca6cd83416fcc"
dependencies = [
"bindgen",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.171"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
[[package]]
name = "libloading"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "prettyplease"
version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb"
dependencies = [
"proc-macro2",
"syn",
]
[[package]]
name = "proc-macro2"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "2.0.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tee_quote_verification"
version = "0.1.0"
dependencies = [
"intel-tee-quote-verification-rs",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

View File

@@ -0,0 +1,8 @@
[package]
name = "tee_quote_verification"
version = "0.1.0"
edition = "2024"
[dependencies]
intel-tee-quote-verification-rs = "0.3.0"

View File

@@ -0,0 +1,57 @@
# ---------- BUILD STAGE ----------
FROM ubuntu:22.04 AS builder
ENV DEBIAN_FRONTEND=noninteractive
# Install Rust
RUN apt-get update && apt-get install -y curl build-essential \
&& curl https://sh.rustup.rs -sSf | sh -s -- -y \
&& . "$HOME/.cargo/env"
ENV PATH="/root/.cargo/bin:${PATH}"
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
pkg-config libssl-dev clang llvm-dev libclang-dev \
ca-certificates software-properties-common gnupg wget
# Add Intel SGX repo (Jammy/22.04)
RUN wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add -
RUN echo "deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" \
> /etc/apt/sources.list.d/intel-sgx.list
# Install SGX quote verification libraries + headers
RUN apt-get update && apt-get install -y --no-install-recommends \
libsgx-dcap-quote-verify libsgx-dcap-quote-verify-dev
# Copy source
WORKDIR /app
COPY . .
# Build the binary
RUN cargo build --release
# ---------- RUNTIME STAGE ----------
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
# Add Intel SGX repo to get runtime libs
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates curl wget gnupg \
&& wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add - \
&& echo "deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" \
> /etc/apt/sources.list.d/intel-sgx.list \
&& apt-get update && apt-get install -y --no-install-recommends \
libsgx-dcap-quote-verify libsgx-dcap-default-qpl \
&& rm -rf /var/lib/apt/lists/*
# Create working directory
WORKDIR /app
# Copy binary and any runtime data
COPY --from=builder /app/target/release/tee_quote_verification .
COPY etc/sgx_default_qcnl.conf /etc/sgx_default_qcnl.conf
# Run the program
CMD ["./tee_quote_verification"]

View File

@@ -0,0 +1,81 @@
{
// *** ATTENTION : This file is in JSON format so the keys are case sensitive. Don't change them.
//PCCS server address
"pccs_url": "https://global.acccache.azure.net/sgx/certification/v3/"
// To accept insecure HTTPS certificate, set this option to false
,"use_secure_cert": true
// You can use the Intel PCS or another PCCS to get quote verification collateral. Retrieval of PCK
// Certificates will always use the PCCS described in pccs_url. When collateral_service is not defined, both
// PCK Certs and verification collateral will be retrieved using pccs_url
//,"collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/"
,"collateral_service": "https://global.acccache.azure.net/sgx/certification/v3/"
// Type of update to TCB Info. Possible value: early, standard. Default is standard.
// early indicates an early access to updated TCB Info provided as part of a TCB recovery event
// (commonly the day of public disclosure of the items in scope)
// standard indicates standard access to updated TCB Info provided as part of a TCB recovery event
// (commonly approximately 6 weeks after public disclosure of the items in scope)
//, "tcb_update_type" : "standard"
// If you use a PCCS service to get the quote verification collateral, you can specify which PCCS API version is to be used.
// The legacy 3.0 API will return CRLs in HEX encoded DER format and the sgx_ql_qve_collateral_t.version will be set to 3.0, while
// the new 3.1 API will return raw DER format and the sgx_ql_qve_collateral_t.version will be set to 3.1. The pccs_api_version
// setting is ignored if collateral_service is set to the Intel PCS. In this case, the pccs_api_version is forced to be 3.1
// internally. Currently, only values of 3.0 and 3.1 are valid. Note, if you set this to 3.1, the PCCS use to retrieve
// verification collateral must support the new 3.1 APIs.
//,"pccs_api_version": "3.1"
// Maximum retry times for QCNL. If RETRY is not defined or set to 0, no retry will be performed.
// It will first wait one second and then for all forthcoming retries it will double the waiting time.
// By using retry_delay you disable this exponential backoff algorithm
,"retry_times": 6
// Sleep this amount of seconds before each retry when a transfer has failed with a transient error
,"retry_delay": 10
// If local_pck_url is defined, the QCNL will try to retrieve PCK cert chain from local_pck_url first,
// and failover to pccs_url as in legacy mode.
//,"local_pck_url": "http://localhost:8081/sgx/certification/v4/"
// If local_pck_url is not defined, set pck_cache_expire_hours to a none-zero value will enable local cache.
// The PCK certificates will be cached in memory and then to the disk drive.
// The local cache files will be sequentially searched in the following directories until located in one of them:
// Linux : $AZDCAP_CACHE, $XDG_CACHE_HOME, $HOME, $TMPDIR, /tmp/
// Windows : $AZDCAP_CACHE, $LOCALAPPDATA\..\..\LocalLow
// Please be aware that the environment variable pertains to the account executing the process that loads QPL,
// not the account used to log in. For instance, if QPL is loaded by QGS, then those environment variables relate to
// the "qgsd" account, which is the account that runs the QGS daemon.
// You can remove the local cache files either manually or by using the QPL API, sgx_qpl_clear_cache. If you opt to
// delete them manually, navigate to the aforementioned caching directories, find the folder named .dcap-qcnl, and delete it.
// Restart the service after all cache folders were deleted. The same method applies to "verify_collateral_cache_expire_hours"
,"pck_cache_expire_hours": 168
// To set cache expire time for quote verification collateral in hours
// See the above comment for pck_cache_expire_hours for more information on the local cache.
,"verify_collateral_cache_expire_hours": 168
// When the "local_cache_only" parameter is set to true, the QPL/QCNL will exclusively use PCK certificates
// from local cache files and will not request any PCK certificates from service providers, whether local or remote.
// To ensure that the PCK cache is available for use, an administrator must pre-populate the cache folders with
// the appropriate cache files. To generate these cache files for specific platforms, the administrator can use
// the PCCS admin tool. Once the cache files are generated, the administrator must distribute them to each platform
// that requires provisioning.
,"local_cache_only": false
// You can add custom request headers and parameters to the get certificate API.
// But the default PCCS implementation just ignores them.
//,"custom_request_options" : {
// "get_cert" : {
// "headers": {
// "head1": "value1"
// },
// "params": {
// "param1": "value1",
// "param2": "value2"
// }
// }
//}
}

View File

@@ -0,0 +1,38 @@
# Intel TEE Quote Verification in Docker
This repository contains code to verify SGX quotes for TLSNotary notary servers running in Intel SGX Trusted Execution Environments (TEEs).
## Overview
This Rust program leverages Intel's `tee-quote-verification` library to automatically fetch and validate Intel's certificates. Since this library is only supported on Linux systems, we use Docker to handle dependencies and ensure compatibility.
## Getting the Quote
To retrieve the SGX quote from a notary server:
1. Visit the info page of the notary server.
2. Copy the `rawQuote` field.
3. Decode the hex-encoded quote.
You can perform these steps in a single command:
```sh
curl https://notary.pse.dev/v0.1.0-alpha.9/info | jq -r '.quote.rawQuote' | xxd -r -p > quote.dat
```
This command fetches the `rawQuote`, decodes it from hex, and saves it as `quote.dat`.
## Verifying the Quote
The binary has native library dependencies. To simplify running the quote verifier, it can be built and executed within a Docker container.
To verify the quote, run:
```bash
./verify.sh quote.dat
```
This script will:
1. Build the Docker container (if it hasnt been built already).
2. Run the quote verification program inside the container.

View File

@@ -0,0 +1,27 @@
use intel_tee_quote_verification_rs::*;
use std::env;
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
eprintln!("Usage: {} <quote_file>", args[0]);
std::process::exit(1);
}
let quote_path = &args[1];
let quote_bytes = std::fs::read(quote_path).expect("Failed to read quote file");
// Use current UNIX time
let current_time = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
let result = tee_verify_quote(&quote_bytes, None, current_time, None, None);
match result {
Ok(_) => println!("Quote verification succeeded"),
Err(e) => println!("Quote verification failed: {:?}", e),
}
}

View File

@@ -0,0 +1,17 @@
#!/bin/sh
set -e
if [ $# -ne 1 ]; then
echo "Usage: $0 path/to/quote.dat"
exit 1
fi
QUOTE_FILE=$(realpath "$1")
echo "🔧 Building Docker image (if needed)..."
docker build --platform=linux/amd64 --quiet --tag quote-runner .
echo "🚀 Running quote verifier"
docker run --platform=linux/amd64 --rm \
-v "$QUOTE_FILE:/app/quote.dat" \
quote-runner \
./tee_quote_verification /app/quote.dat

BIN
test-input/quote_9.dat Normal file

Binary file not shown.

BIN
test-input/quote_dev.dat Normal file

Binary file not shown.

Binary file not shown.