Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into pab/solidity-compatib…
Browse files Browse the repository at this point in the history
…le-pubkey-in-report-data
  • Loading branch information
pbeza committed Jan 15, 2025
2 parents a9b89ef + e5cca31 commit d79f7e5
Show file tree
Hide file tree
Showing 15 changed files with 742 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: cachix/install-nix-action@v27
- uses: cachix/install-nix-action@v30
- run: nix run nixpkgs#taplo -- fmt --check
6 changes: 3 additions & 3 deletions .github/workflows/nix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: cachix/install-nix-action@v27
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
access-tokens = github.com=${{ github.token }}
Expand All @@ -37,7 +37,7 @@ jobs:
runs-on: [ matterlabs-default-infra-runners ]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: cachix/install-nix-action@v27
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
access-tokens = github.com=${{ github.token }}
Expand Down Expand Up @@ -75,7 +75,7 @@ jobs:
- { nixpackage: 'container-verify-era-proof-attestation-sgx' }
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v27
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
access-tokens = github.com=${{ github.token }}
Expand Down
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
# teepot

Key Value store in a TEE with Remote Attestation for Authentication

## Introduction

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 Gramine runtime.

## Parts of this project

- `teepot`: The main rust crate that abstracts TEEs and key-value stores.
Expand All @@ -22,6 +14,18 @@ The key-value store is implemented using Hashicorp Vault running in an Intel SGX
- `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
for Authentication. The key-value store is implemented using Hashicorp Vault running in an Intel SGX enclave via the
Gramine runtime.

## Development

Expand Down Expand Up @@ -96,3 +100,9 @@ Attributes:
isv_svn: 0
debug_enclave: False
```

### TDX VM testing

```shell
nixos-rebuild -L --flake .#tdxtest build-vm && ./result/bin/run-tdxtest-vm
```
45 changes: 45 additions & 0 deletions assets/gcloud-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash

#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2025 Matter Labs
#

set -ex

NO=${NO:-1}

nix build -L .#tdx_google

gsutil cp result/tdx_base_1.vmdk gs://tdx_vms/

gcloud migration vms image-imports create \
--location=us-central1 \
--target-project=tdx-pilot \
--project=tdx-pilot \
--skip-os-adaptation \
--source-file=gs://tdx_vms/tdx_base_1.vmdk \
tdx-img-pre-"${NO}"

gcloud compute instances stop tdx-pilot --zone us-central1-c --project tdx-pilot || :
gcloud compute instances delete tdx-pilot --zone us-central1-c --project tdx-pilot || :

while gcloud migration vms image-imports list --location=us-central1 --project=tdx-pilot | grep -F RUNNING; do
sleep 1
done

gcloud compute images create \
--project tdx-pilot \
--guest-os-features=UEFI_COMPATIBLE,TDX_CAPABLE,GVNIC,VIRTIO_SCSI_MULTIQUEUE \
--storage-location=us-central1 \
--source-image=tdx-img-pre-"${NO}" \
tdx-img-f-"${NO}"

gcloud compute instances create tdx-pilot \
--machine-type c3-standard-4 --zone us-central1-c \
--confidential-compute-type=TDX \
--maintenance-policy=TERMINATE \
--image-project=tdx-pilot \
--project tdx-pilot \
--metadata=container_hub="docker.io",container_image="amd64/hello-world@sha256:e2fc4e5012d16e7fe466f5291c476431beaa1f9b90a5c2125b493ed28e2aba57" \
--image tdx-img-f-"${NO}"
123 changes: 62 additions & 61 deletions crates/teepot-tee-quote-verification-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2024 Matter Labs
// Copyright (c) 2024-2025 Matter Labs

// SPDX-License-Identifier: BSD-3-Clause
/*
Expand Down Expand Up @@ -39,22 +39,14 @@
//! This is a safe wrapper for **sgx-dcap-quoteverify-sys**.
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use std::slice;
use std::{marker::PhantomData, ops::Deref, slice};

use intel_tee_quote_verification_sys as qvl_sys;

pub use qvl_sys::quote3_error_t;
pub use qvl_sys::sgx_ql_qe_report_info_t;
pub use qvl_sys::sgx_ql_qv_result_t;
pub use qvl_sys::sgx_ql_qv_supplemental_t;
pub use qvl_sys::sgx_ql_qve_collateral_t;
pub use qvl_sys::sgx_ql_request_policy_t;
pub use qvl_sys::sgx_qv_path_type_t;
pub use qvl_sys::tdx_ql_qve_collateral_t;
pub use qvl_sys::tee_supp_data_descriptor_t;
pub use qvl_sys::{
quote3_error_t, sgx_ql_qe_report_info_t, sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t,
sgx_ql_qve_collateral_t, sgx_ql_request_policy_t, sgx_qv_path_type_t, tdx_ql_qve_collateral_t,
tee_qv_free_collateral, tee_supp_data_descriptor_t,
};

/// When the Quoting Verification Library is linked to a process, it needs to know the proper enclave loading policy.
/// The library may be linked with a long lived process, such as a service, where it can load the enclaves and leave
Expand Down Expand Up @@ -328,43 +320,6 @@ pub struct Collateral {
pub qe_identity: Box<[u8]>,
}

impl TryFrom<&sgx_ql_qve_collateral_t> for Collateral {
type Error = ();

fn try_from(value: &sgx_ql_qve_collateral_t) -> Result<Self, Self::Error> {
fn to_boxed_slice(p: *mut ::std::os::raw::c_char, size: u32) -> Result<Box<[u8]>, ()> {
if p.is_null() {
return Err(());
}
Ok(Box::from(unsafe {
slice::from_raw_parts(p as _, size as _)
}))
}

Ok(Collateral {
major_version: unsafe { value.__bindgen_anon_1.__bindgen_anon_1.major_version },
minor_version: unsafe { value.__bindgen_anon_1.__bindgen_anon_1.minor_version },
tee_type: value.tee_type,
pck_crl_issuer_chain: to_boxed_slice(
value.pck_crl_issuer_chain,
value.pck_crl_issuer_chain_size,
)?,
root_ca_crl: to_boxed_slice(value.root_ca_crl, value.root_ca_crl_size)?,
pck_crl: to_boxed_slice(value.pck_crl, value.pck_crl_size)?,
tcb_info_issuer_chain: to_boxed_slice(
value.tcb_info_issuer_chain,
value.tcb_info_issuer_chain_size,
)?,
tcb_info: to_boxed_slice(value.tcb_info, value.tcb_info_size)?,
qe_identity_issuer_chain: to_boxed_slice(
value.qe_identity_issuer_chain,
value.qe_identity_issuer_chain_size,
)?,
qe_identity: to_boxed_slice(value.qe_identity, value.qe_identity_size)?,
})
}
}

// referential struct
struct SgxQlQveCollateralT<'a> {
inner: sgx_ql_qve_collateral_t,
Expand Down Expand Up @@ -432,22 +387,68 @@ impl Deref for SgxQlQveCollateralT<'_> {
/// - *SGX_QL_ERROR_UNEXPECTED*
///
pub fn tee_qv_get_collateral(quote: &[u8]) -> Result<Collateral, quote3_error_t> {
fn try_into_collateral(
buf: *const sgx_ql_qve_collateral_t,
buf_len: u32,
) -> Result<Collateral, quote3_error_t> {
fn try_into_boxed_slice(
p: *mut ::std::os::raw::c_char,
size: u32,
) -> Result<Box<[u8]>, quote3_error_t> {
if p.is_null() || !p.is_aligned() {
return Err(quote3_error_t::SGX_QL_ERROR_MAX);
}
Ok(Box::from(unsafe {
slice::from_raw_parts(p as _, size as _)
}))
}

if buf.is_null()
|| (buf_len as usize) < size_of::<sgx_ql_qve_collateral_t>()
|| !buf.is_aligned()
{
return Err(quote3_error_t::SGX_QL_ERROR_MAX);
}

// SAFETY: buf is not null, buf_len is not zero, and buf is aligned.
let collateral = unsafe { *buf };

Ok(Collateral {
major_version: unsafe { collateral.__bindgen_anon_1.__bindgen_anon_1.major_version },
minor_version: unsafe { collateral.__bindgen_anon_1.__bindgen_anon_1.minor_version },
tee_type: collateral.tee_type,
pck_crl_issuer_chain: try_into_boxed_slice(
collateral.pck_crl_issuer_chain,
collateral.pck_crl_issuer_chain_size,
)?,
root_ca_crl: try_into_boxed_slice(collateral.root_ca_crl, collateral.root_ca_crl_size)?,
pck_crl: try_into_boxed_slice(collateral.pck_crl, collateral.pck_crl_size)?,
tcb_info_issuer_chain: try_into_boxed_slice(
collateral.tcb_info_issuer_chain,
collateral.tcb_info_issuer_chain_size,
)?,
tcb_info: try_into_boxed_slice(collateral.tcb_info, collateral.tcb_info_size)?,
qe_identity_issuer_chain: try_into_boxed_slice(
collateral.qe_identity_issuer_chain,
collateral.qe_identity_issuer_chain_size,
)?,
qe_identity: try_into_boxed_slice(collateral.qe_identity, collateral.qe_identity_size)?,
})
}

let mut buf = std::ptr::null_mut();
let mut buf_len = 0u32;

match unsafe {
qvl_sys::tee_qv_get_collateral(quote.as_ptr(), quote.len() as u32, &mut buf, &mut buf_len)
} {
quote3_error_t::SGX_QL_SUCCESS => {
assert!(!buf.is_null());
assert!(buf_len > 0);
assert_eq!(
(buf as usize) % mem::align_of::<sgx_ql_qve_collateral_t>(),
0
);
// SAFETY: buf is not null, buf_len is not zero, and buf is aligned.
let orig_collateral = &unsafe { *(buf as *const sgx_ql_qve_collateral_t) };
Collateral::try_from(orig_collateral).map_err(|_| quote3_error_t::SGX_QL_ERROR_MAX)
let collateral = try_into_collateral(buf as _, buf_len);

match unsafe { tee_qv_free_collateral(buf) } {
quote3_error_t::SGX_QL_SUCCESS => collateral,
error_code => Err(error_code),
}
}
error_code => Err(error_code),
}
Expand Down
4 changes: 3 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
};

outputs = inputs:
let src = ./.; in
let
src = ./.;
in
inputs.snowfall-lib.mkFlake {
inherit inputs;
inherit src;
Expand Down
3 changes: 3 additions & 0 deletions lib/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{ ... }: {
nixosGenerate = import ./nixos-generate.nix;
}
33 changes: 33 additions & 0 deletions lib/nixos-generate.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{ pkgs
, nixosSystem
, formatModule
, system
, specialArgs ? { }
, modules ? [ ]
}:
let
image = nixosSystem {
inherit pkgs specialArgs;
modules =
[
formatModule
(
{ lib, ... }: {
options = {
fileExtension = lib.mkOption {
type = lib.types.str;
description = "Declare the path of the wanted file in the output directory";
default = "";
};
formatAttr = lib.mkOption {
type = lib.types.str;
description = "Declare the default attribute to build";
};
};
}
)
]
++ modules;
};
in
image.config.system.build.${image.config.formatAttr}
38 changes: 38 additions & 0 deletions packages/container-tee-key-preexec-dcap/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2024 Matter Labs
{ teepot
, pkgs
, bash
, coreutils
, container-name ? "teepot-key-preexec-dcap"
, tag ? null
}: let
entrypoint = "${bash}/bin/bash";
in
pkgs.lib.tee.sgxGramineContainer {
name = container-name;
inherit tag entrypoint;

packages = [ teepot.teepot.tee_key_preexec coreutils bash ];

manifest = {
loader = {
argv = [
entrypoint
"-c"
("${teepot.teepot.tee_key_preexec}/bin/tee-key-preexec -- bash -c "
+ "'echo \"SIGNING_KEY=$SIGNING_KEY\"; echo \"TEE_TYPE=$TEE_TYPE\";exec base64 \"$ATTESTATION_QUOTE_FILE_PATH\";'")
];

log_level = "error";
env = {
RUST_BACKTRACE = "1";
RUST_LOG = "trace";
};
};
sgx = {
edmm_enable = true;
max_threads = 2;
};
};
}
Loading

0 comments on commit d79f7e5

Please sign in to comment.