From eb39705ff1bbe2104885a55a7bf27ed6df9c26c2 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Thu, 20 Mar 2025 10:25:24 +0100 Subject: [PATCH 1/2] feat: compat code for non `x86_64-linux` - do not build packages, which require `x86_64-linux` - use Phala `dcap-qvl` crate for remote attestation, if possible - nix: exclude `nixsgx` on non `x86_64-linux` platforms Signed-off-by: Harald Hoyer --- .github/workflows/nix-non-x86.yml | 38 ++ Cargo.lock | 557 ++++++++++++++++-- Cargo.toml | 3 +- bin/rtmr-calc/src/main.rs | 2 +- bin/tdx-extend/src/main.rs | 97 +-- bin/tee-key-preexec/src/main.rs | 36 +- bin/verify-attestation/src/main.rs | 13 +- .../src/verification/attestation.rs | 10 +- .../src/verification/policy.rs | 2 +- .../src/verification/reporting.rs | 5 +- .../Cargo.toml | 10 +- crates/teepot-vault/Cargo.toml | 2 - crates/teepot-vault/src/client/mod.rs | 18 +- crates/teepot-vault/src/client/vault.rs | 7 +- crates/teepot/Cargo.toml | 13 +- crates/teepot/src/pki/mod.rs | 5 +- crates/teepot/src/quote/attestation.rs | 12 +- crates/teepot/src/quote/error.rs | 53 +- crates/teepot/src/quote/intel.rs | 260 ++++++++ crates/teepot/src/quote/mod.rs | 166 ++---- crates/teepot/src/quote/phala.rs | 259 ++++++++ crates/teepot/src/quote/tcblevel.rs | 40 +- crates/teepot/src/sgx/mod.rs | 3 +- crates/teepot/src/tdx/mod.rs | 36 +- crates/teepot/src/tdx/rtmr.rs | 14 +- crates/teepot/tests/sgx_quote_verification.rs | 51 +- deny.toml | 1 + .../default.nix | 2 + packages/container-tdx-test/default.nix | 50 +- .../default.nix | 2 + .../default.nix | 2 + packages/container-vault-admin/default.nix | 2 + .../container-vault-sgx-azure/default.nix | 4 +- .../default.nix | 2 + packages/container-vault-unseal/default.nix | 51 +- .../default.nix | 54 +- .../default.nix | 56 +- packages/tdx_google/default.nix | 5 +- packages/teepot/default.nix | 40 +- packages/teepotCrate/default.nix | 10 +- shells/teepot/default.nix | 57 +- 41 files changed, 1531 insertions(+), 519 deletions(-) create mode 100644 .github/workflows/nix-non-x86.yml create mode 100644 crates/teepot/src/quote/intel.rs create mode 100644 crates/teepot/src/quote/phala.rs diff --git a/.github/workflows/nix-non-x86.yml b/.github/workflows/nix-non-x86.yml new file mode 100644 index 0000000..0872032 --- /dev/null +++ b/.github/workflows/nix-non-x86.yml @@ -0,0 +1,38 @@ +name: nix-non-x86 + +permissions: + contents: read + pull-requests: read + +on: + pull_request: + branches: ["main"] + push: + branches: ["main"] + tags: ["*"] + +jobs: + macos-latest: + runs-on: macos-latest + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + access-tokens = github.com=${{ github.token }} + trusted-public-keys = cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= tee-pot:SS6HcrpG87S1M6HZGPsfo7d1xJccCGev7/tXc5+I4jg= + substituters = https://cache.nixos.org/ https://attic.teepot.org/tee-pot + sandbox = true + - name: Setup Attic cache + uses: ryanccn/attic-action@v0 + with: + endpoint: https://attic.teepot.org/ + cache: tee-pot + token: ${{ secrets.ATTIC_TOKEN }} + + - name: nixci + # FIXME: this prevents it from running on macos + # https://github.com/NixOS/nix/pull/12570 + # run: nix run github:nixos/nixpkgs/nixos-24.11#nixci -- build + run: nix build -L .#teepot + diff --git a/Cargo.lock b/Cargo.lock index 9e9d369..0ac592f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,7 +50,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand", + "rand 0.8.5", "sha1", "smallvec", "tokio", @@ -278,7 +278,7 @@ dependencies = [ "getrandom 0.2.15", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -366,6 +366,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "asn1_der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" + [[package]] name = "async-stream" version = "0.3.6" @@ -448,7 +454,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand", + "rand 0.8.5", "rustls", "serde", "serde_json", @@ -540,7 +546,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -867,16 +873,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chrono" -version = "0.4.39" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", - "windows-targets", + "wasm-bindgen", + "windows-link", ] [[package]] @@ -1137,7 +1151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "subtle", "zeroize", ] @@ -1149,7 +1163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", - "rand_core", + "rand_core 0.6.4", "typenum", ] @@ -1269,6 +1283,12 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "data-encoding" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" + [[package]] name = "dbl" version = "0.3.2" @@ -1278,6 +1298,36 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dcap-qvl" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8bc5d87613fe4c0a7a980c3e9113d9f10b9f9404218e19333e0eff2eff4c9a" +dependencies = [ + "anyhow", + "asn1_der", + "base64", + "byteorder", + "chrono", + "const-oid", + "der", + "futures", + "hex", + "log", + "parity-scale-codec", + "pem", + "reqwest", + "ring", + "rustls-webpki", + "scale-info", + "serde", + "serde-human-bytes", + "serde_json", + "tracing", + "urlencoding", + "x509-cert", +] + [[package]] name = "der" version = "0.7.9" @@ -1509,7 +1559,7 @@ dependencies = [ "hkdf", "pem-rfc7468 0.7.0", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sec1", "subtle", "zeroize", @@ -1533,6 +1583,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "enumset" version = "1.1.5" @@ -1649,7 +1711,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -1666,7 +1728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ "byteorder", - "rand", + "rand 0.8.5", "rustc-hex", "static_assertions", ] @@ -1846,8 +1908,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1857,9 +1921,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.13.3+wasi-0.2.2", - "windows-targets", + "wasm-bindgen", + "windows-targets 0.52.6", ] [[package]] @@ -1949,7 +2015,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -2051,6 +2117,51 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "hickory-proto" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.8.5", + "thiserror 1.0.69", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror 1.0.69", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -2078,6 +2189,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "hostname" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" +dependencies = [ + "cfg-if", + "libc", + "windows", +] + [[package]] name = "http" version = "0.2.12" @@ -2178,6 +2300,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2489,6 +2612,18 @@ dependencies = [ "bindgen 0.65.1", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -2670,9 +2805,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.24.9" +version = "0.24.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a8e70baf945b6b5752fc8eb38c918a48f1234daf11355e07106d963f860089" +checksum = "ddb81adb1a5ae9182df379e374a79e24e992334e7346af4d065ae5b2acb8d4c6" dependencies = [ "http 1.2.0", "serde", @@ -2761,7 +2896,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2770,6 +2905,12 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -2815,6 +2956,15 @@ version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2944,7 +3094,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand", + "rand 0.8.5", "serde", "smallvec", "zeroize", @@ -3178,7 +3328,7 @@ dependencies = [ "glob", "opentelemetry", "percent-encoding", - "rand", + "rand 0.8.5", "serde_json", "thiserror 2.0.11", "tokio", @@ -3226,7 +3376,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "rand_core", + "rand_core 0.6.4", "sha2", ] @@ -3278,7 +3428,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3288,7 +3438,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" dependencies = [ "base64ct", - "rand_core", + "rand_core 0.6.4", "subtle", ] @@ -3329,6 +3479,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pem" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +dependencies = [ + "base64", + "serde", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -3404,7 +3564,7 @@ dependencies = [ "p256", "p384", "p521", - "rand", + "rand 0.8.5", "ripemd", "rsa", "sha1", @@ -3502,7 +3662,7 @@ version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -3601,6 +3761,60 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "quinn" +version = "0.11.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls", + "socket2", + "thiserror 2.0.11", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" +dependencies = [ + "bytes", + "getrandom 0.3.1", + "rand 0.9.0", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.11", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.38" @@ -3623,8 +3837,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "zerocopy 0.8.24", ] [[package]] @@ -3634,7 +3859,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -3646,6 +3881,15 @@ dependencies = [ "getrandom 0.2.15", ] +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.5.8" @@ -3718,6 +3962,7 @@ dependencies = [ "futures-core", "futures-util", "h2 0.4.8", + "hickory-resolver", "http 1.2.0", "http-body", "http-body-util", @@ -3733,7 +3978,10 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pemfile", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", @@ -3741,15 +3989,26 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", + "tokio-rustls", "tower 0.5.2", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "windows-registry", ] +[[package]] +name = "resolv-conf" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4" +dependencies = [ + "hostname", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -3806,7 +4065,7 @@ dependencies = [ "num-traits", "pkcs1", "pkcs8", - "rand_core", + "rand_core 0.6.4", "sha2", "signature", "spki", @@ -3917,6 +4176,9 @@ name = "rustls-pki-types" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +dependencies = [ + "web-time", +] [[package]] name = "rustls-platform-verifier" @@ -3978,6 +4240,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "schannel" version = "0.1.27" @@ -4023,7 +4310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ "bitcoin_hashes", - "rand", + "rand 0.8.5", "secp256k1-sys 0.10.1", ] @@ -4099,6 +4386,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-human-bytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ef65cb41f3f9cef63c431193229067e8b98b53c4d4c4ed38a8ca87c4d07676" +dependencies = [ + "hex", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.218" @@ -4116,6 +4413,7 @@ version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" dependencies = [ + "indexmap 2.7.1", "itoa", "memchr", "ryu", @@ -4294,7 +4592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -4339,7 +4637,7 @@ dependencies = [ "futures", "httparse", "log", - "rand", + "rand 0.8.5", "sha1", ] @@ -4626,10 +4924,14 @@ dependencies = [ "async-trait", "base64", "bytemuck", + "bytes", + "chrono", "clap 4.5.30", "config", "const-oid", + "dcap-qvl", "enumset", + "futures", "getrandom 0.3.1", "hex", "num-integer", @@ -4707,9 +5009,7 @@ dependencies = [ "serde_json", "serde_with 3.12.0", "sha2", - "tdx-attest-rs", "teepot", - "teepot-tee-quote-verification-rs", "thiserror 2.0.11", "tracing", "webpki-roots", @@ -4879,6 +5179,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tls_codec" version = "0.4.2" @@ -5049,7 +5364,7 @@ dependencies = [ "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", + "rand 0.8.5", "slab", "tokio", "tokio-util", @@ -5289,6 +5604,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf16_iter" version = "1.0.5" @@ -5541,6 +5862,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.8" @@ -5562,6 +5893,12 @@ dependencies = [ "rustix", ] +[[package]] +name = "widestring" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" + [[package]] name = "winapi" version = "0.3.9" @@ -5593,15 +5930,31 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + [[package]] name = "windows-registry" version = "0.2.0" @@ -5610,7 +5963,7 @@ checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result", "windows-strings", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5619,7 +5972,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5629,7 +5982,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ "windows-result", - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -5638,7 +6000,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -5647,7 +6009,22 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -5656,28 +6033,46 @@ 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_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5690,24 +6085,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[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.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5723,6 +6142,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wit-bindgen-rt" version = "0.33.0" @@ -5760,7 +6189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", - "rand_core", + "rand_core 0.6.4", "serde", "zeroize", ] @@ -5821,7 +6250,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "byteorder", - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive 0.8.24", ] [[package]] @@ -5835,6 +6273,17 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + [[package]] name = "zerofrom" version = "0.1.5" @@ -5931,7 +6380,7 @@ dependencies = [ "anyhow", "once_cell", "pin-project", - "rand", + "rand 0.8.5", "sha3", "thiserror 1.0.69", "time", @@ -5948,7 +6397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cf4af6d7e83c9ed0422a36c603b8bf84079ab510d295fda74f95ce49f62388" dependencies = [ "anyhow", - "rand", + "rand 0.8.5", "secrecy", "serde", "zksync_basic_types", @@ -5964,7 +6413,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f9fa69ef68e6a1955a1d7b33077103fb6d106b560fec0d599c6de268f5be03" dependencies = [ "anyhow", - "rand", + "rand 0.8.5", "thiserror 1.0.69", "zksync_concurrency", ] @@ -5993,7 +6442,7 @@ dependencies = [ "anyhow", "blake2", "hex", - "rand", + "rand 0.8.5", "secp256k1 0.27.0", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 508f166..695755a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = ["crates/*", "bin/*", "crates/teepot-vault/bin/*"] +exclude = ["crates/teepot-tee-quote-verification-rs"] resolver = "2" [profile.release] @@ -30,8 +31,6 @@ enumset = { version = "1.1", features = ["serde"] } getrandom = { version = "0.3.1", features = ["std"] } gpt = "4.0.0" hex = { version = "0.4.3", features = ["std"], default-features = false } -intel-tee-quote-verification-rs = { package = "teepot-tee-quote-verification-rs", path = "crates/teepot-tee-quote-verification-rs", version = "0.3.0" } -intel-tee-quote-verification-sys = { version = "0.2.1" } num-integer = "0.1.46" num-traits = "0.2.18" opentelemetry = { version = "0.28.0", features = ["default", "logs"] } diff --git a/bin/rtmr-calc/src/main.rs b/bin/rtmr-calc/src/main.rs index c49d95e..7a6cef5 100644 --- a/bin/rtmr-calc/src/main.rs +++ b/bin/rtmr-calc/src/main.rs @@ -12,7 +12,7 @@ use std::{ }; use teepot::{ log::{setup_logging, LogLevelParser}, - tdx::rtmr::UEFI_MARKER_DIGEST_BYTES, + tdx::UEFI_MARKER_DIGEST_BYTES, }; use tracing::{debug, info, level_filters::LevelFilter}; diff --git a/bin/tdx-extend/src/main.rs b/bin/tdx-extend/src/main.rs index 5a43f59..31aca89 100644 --- a/bin/tdx-extend/src/main.rs +++ b/bin/tdx-extend/src/main.rs @@ -6,53 +6,64 @@ #![deny(missing_docs)] #![deny(clippy::all)] -use anyhow::{Context, Result}; -use clap::Parser; -use teepot::{ - log::{setup_logging, LogLevelParser}, - tdx::rtmr::TdxRtmrEvent, - util::pad, -}; -use tracing::{error, level_filters::LevelFilter}; +use tracing::error; -/// Extend a TDX rtmr with a hash digest for measured boot. -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct Arguments { - /// digest in hex to extend the rtmr with - #[arg(long)] - digest: String, - /// the number or the rtmr - #[arg(long, default_value = "2")] - rtmr: u64, - /// Log level for the log output. - /// Valid values are: `off`, `error`, `warn`, `info`, `debug`, `trace` - #[clap(long, default_value_t = LevelFilter::WARN, value_parser = LogLevelParser)] - pub log_level: LevelFilter, +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] +mod os { + use anyhow::{Context as _, Result}; + use clap::Parser; + use teepot::{ + log::{setup_logging, LogLevelParser}, + tdx::rtmr::TdxRtmrEvent, + util::pad, + }; + use tracing::level_filters::LevelFilter; + + /// Extend a TDX rtmr with a hash digest for measured boot. + #[derive(Parser, Debug)] + #[command(author, version, about, long_about = None)] + struct Arguments { + /// digest in hex to extend the rtmr with + #[arg(long)] + digest: String, + /// the number or the rtmr + #[arg(long, default_value = "2")] + rtmr: u64, + /// Log level for the log output. + /// Valid values are: `off`, `error`, `warn`, `info`, `debug`, `trace` + #[clap(long, default_value_t = LevelFilter::WARN, value_parser = LogLevelParser)] + pub log_level: LevelFilter, + } + + pub fn main_with_error() -> Result<()> { + let args = Arguments::parse(); + tracing::subscriber::set_global_default(setup_logging( + env!("CARGO_CRATE_NAME"), + &args.log_level, + )?)?; + + // Parse the digest string as a hex array + let digest_bytes = hex::decode(&args.digest).context("Invalid digest format")?; + let extend_data: [u8; 48] = pad(&digest_bytes).context("Invalid digest length")?; + + // Extend the TDX measurement with the extend data + TdxRtmrEvent::default() + .with_extend_data(extend_data) + .with_rtmr_index(args.rtmr) + .extend()?; + + Ok(()) + } } -fn main_with_error() -> Result<()> { - let args = Arguments::parse(); - tracing::subscriber::set_global_default(setup_logging( - env!("CARGO_CRATE_NAME"), - &args.log_level, - )?)?; - - // Parse the digest string as a hex array - let digest_bytes = hex::decode(&args.digest).context("Invalid digest format")?; - let extend_data: [u8; 48] = pad(&digest_bytes).context("Invalid digest length")?; - - // Extend the TDX measurement with the extend data - TdxRtmrEvent::default() - .with_extend_data(extend_data) - .with_rtmr_index(args.rtmr) - .extend()?; - - Ok(()) +#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))] +mod os { + pub fn main_with_error() -> anyhow::Result<()> { + anyhow::bail!("OS or architecture not supported"); + } } - -fn main() -> Result<()> { - let ret = main_with_error(); +fn main() -> anyhow::Result<()> { + let ret = os::main_with_error(); if let Err(e) = &ret { error!(error = %e, "Execution failed"); } diff --git a/bin/tee-key-preexec/src/main.rs b/bin/tee-key-preexec/src/main.rs index 5d62361..14c10c3 100644 --- a/bin/tee-key-preexec/src/main.rs +++ b/bin/tee-key-preexec/src/main.rs @@ -6,21 +6,10 @@ #![deny(missing_docs)] #![deny(clippy::all)] -use anyhow::{Context, Result}; +use anyhow::Result; use clap::Parser; -use secp256k1::{rand, Secp256k1}; -use std::{ffi::OsString, os::unix::process::CommandExt, process::Command}; -use teepot::{ - ethereum::public_key_to_ethereum_address, - prover::reportdata::ReportDataV1, - quote::get_quote, - tdx::rtmr::{TdxRtmrEvent, UEFI_MARKER_DIGEST_BYTES}, -}; +use std::ffi::OsString; use tracing::error; -use tracing_log::LogTracer; -use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; - -const TEE_QUOTE_FILE: &str = "/tmp/tee_quote"; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -33,7 +22,21 @@ struct Args { cmd_args: Vec, } +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] fn main_with_error() -> Result<()> { + use anyhow::Context; + use secp256k1::{rand, Secp256k1}; + use std::{os::unix::process::CommandExt, process::Command}; + use teepot::tdx::rtmr::TdxRtmrEvent; + use teepot::{ + ethereum::public_key_to_ethereum_address, prover::reportdata::ReportDataV1, + quote::get_quote, + }; + use tracing_log::LogTracer; + use tracing_subscriber::{fmt, prelude::*, EnvFilter, Registry}; + + const TEE_QUOTE_FILE: &str = "/tmp/tee_quote"; + LogTracer::init().context("Failed to set logger")?; let subscriber = Registry::default() @@ -54,7 +57,7 @@ fn main_with_error() -> Result<()> { // so that any breach can't generate a new attestation with the expected RTMRs TdxRtmrEvent::default() .with_rtmr_index(3) - .with_extend_data(UEFI_MARKER_DIGEST_BYTES) + .with_extend_data(teepot::tdx::UEFI_MARKER_DIGEST_BYTES) .extend()?; // save quote to file @@ -94,6 +97,11 @@ fn main_with_error() -> Result<()> { }) } +#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))] +fn main_with_error() -> Result<()> { + anyhow::bail!("OS or architecture not supported"); +} + fn main() -> Result<()> { let ret = main_with_error(); if let Err(e) = &ret { diff --git a/bin/verify-attestation/src/main.rs b/bin/verify-attestation/src/main.rs index 3eee26f..4eb84f1 100644 --- a/bin/verify-attestation/src/main.rs +++ b/bin/verify-attestation/src/main.rs @@ -7,10 +7,7 @@ use anyhow::{bail, Context, Result}; use clap::Parser; use std::{fs, io::Read, path::PathBuf, str::FromStr, time::UNIX_EPOCH}; -use teepot::quote::{ - error, tcblevel::TcbLevel, tee_qv_get_collateral, verify_quote_with_collateral, - QuoteVerificationResult, -}; +use teepot::quote::{get_collateral, verify_quote_with_collateral, QuoteVerificationResult}; #[derive(Parser, Debug)] #[command(author = "Matter Labs", version, about = "SGX attestation and batch signature verifier", long_about = None)] @@ -62,10 +59,7 @@ fn verify_attestation_quote(attestation_quote_bytes: &[u8]) -> Result Result error::Result { // Get collateral for the quote - let collateral = QuoteContext::context( - tee_qv_get_collateral(attestation_quote_bytes), - "Failed to get collateral!", - )?; + let collateral = get_collateral(attestation_quote_bytes)?; // Get current time for verification let unix_time: i64 = std::time::SystemTime::now() diff --git a/bin/verify-era-proof-attestation/src/verification/policy.rs b/bin/verify-era-proof-attestation/src/verification/policy.rs index babff24..8130075 100644 --- a/bin/verify-era-proof-attestation/src/verification/policy.rs +++ b/bin/verify-era-proof-attestation/src/verification/policy.rs @@ -19,7 +19,7 @@ impl PolicyEnforcer { quote_verification_result: &QuoteVerificationResult, ) -> Result<()> { let quote = "e_verification_result.quote; - let tcblevel = TcbLevel::from(quote_verification_result.result); + let tcblevel = quote_verification_result.result; match "e.report { Report::SgxEnclave(report_body) => { diff --git a/bin/verify-era-proof-attestation/src/verification/reporting.rs b/bin/verify-era-proof-attestation/src/verification/reporting.rs index 6c1b7aa..638512d 100644 --- a/bin/verify-era-proof-attestation/src/verification/reporting.rs +++ b/bin/verify-era-proof-attestation/src/verification/reporting.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright (c) 2023-2025 Matter Labs -use teepot::quote::{tcblevel::TcbLevel, QuoteVerificationResult}; +use teepot::quote::QuoteVerificationResult; /// Handles reporting and logging of verification results pub struct VerificationReporter; @@ -11,7 +11,7 @@ impl VerificationReporter { pub fn log_quote_verification_summary(quote_verification_result: &QuoteVerificationResult) { let QuoteVerificationResult { collateral_expired, - result, + result: tcblevel, quote, advisories, .. @@ -21,7 +21,6 @@ impl VerificationReporter { tracing::warn!("Freshly fetched collateral expired!"); } - let tcblevel = TcbLevel::from(*result); let advisories = if advisories.is_empty() { "None".to_string() } else { diff --git a/crates/teepot-tee-quote-verification-rs/Cargo.toml b/crates/teepot-tee-quote-verification-rs/Cargo.toml index 1959c34..b267be8 100644 --- a/crates/teepot-tee-quote-verification-rs/Cargo.toml +++ b/crates/teepot-tee-quote-verification-rs/Cargo.toml @@ -5,10 +5,12 @@ name = "teepot-tee-quote-verification-rs" version = "0.3.0" edition = "2021" license = "BSD-3-Clause" -repository.workspace = true -homepage.workspace = true +repository = "https://github.com/matter-labs/teepot" +homepage = "https://github.com/matter-labs/teepot" description = "Fork of intel-tee-quote-verification-rs" [dependencies] -intel-tee-quote-verification-sys.workspace = true -serde.workspace = true +serde = { version = "1", features = ["derive", "rc"] } + +[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies] +intel-tee-quote-verification-sys = { version = "0.2.1" } diff --git a/crates/teepot-vault/Cargo.toml b/crates/teepot-vault/Cargo.toml index 4564c7d..9967d5d 100644 --- a/crates/teepot-vault/Cargo.toml +++ b/crates/teepot-vault/Cargo.toml @@ -17,14 +17,12 @@ 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 diff --git a/crates/teepot-vault/src/client/mod.rs b/crates/teepot-vault/src/client/mod.rs index 8235f8e..f254fd8 100644 --- a/crates/teepot-vault/src/client/mod.rs +++ b/crates/teepot-vault/src/client/mod.rs @@ -8,13 +8,15 @@ pub mod vault; -use crate::server::pki::{RaTlsCollateralExtension, RaTlsQuoteExtension}; +use crate::server::{ + attestation::Collateral, + pki::{RaTlsCollateralExtension, RaTlsQuoteExtension}, +}; use actix_web::http::header; use anyhow::Result; use awc::{Client, Connector}; use clap::Args; use const_oid::AssociatedOid; -use intel_tee_quote_verification_rs::Collateral; use rustls::{ client::{ danger::{HandshakeSignatureValid, ServerCertVerifier}, @@ -25,10 +27,9 @@ use rustls::{ }; use sha2::{Digest, Sha256}; use std::{sync::Arc, time, time::Duration}; -pub use teepot::{ - quote::tcblevel::{parse_tcb_levels, EnumSet, TcbLevel}, - quote::{verify_quote_with_collateral, QuoteVerificationResult}, - sgx::sgx_ql_qv_result_t, +pub use teepot::quote::{ + tcblevel::{parse_tcb_levels, EnumSet, TcbLevel}, + verify_quote_with_collateral, QuoteVerificationResult, }; use teepot::{quote::Report, sgx::Quote}; use tracing::{debug, error, info, trace, warn}; @@ -194,7 +195,7 @@ impl TeeConnection { let QuoteVerificationResult { collateral_expired, - result, + result: tcblevel, quote, advisories, earliest_expiration_date, @@ -206,7 +207,7 @@ impl TeeConnection { return Err(Error::General("TDX quote and not SGX quote".into())); }; - if collateral_expired || result != sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK { + if collateral_expired || tcblevel != TcbLevel::Ok { if collateral_expired { error!( "Collateral is out of date! Expired {}", @@ -218,7 +219,6 @@ impl TeeConnection { ))); } - let tcblevel = TcbLevel::from(result); if self .args .sgx_allowed_tcb_levels diff --git a/crates/teepot-vault/src/client/vault.rs b/crates/teepot-vault/src/client/vault.rs index 462d47d..42cfbae 100644 --- a/crates/teepot-vault/src/client/vault.rs +++ b/crates/teepot-vault/src/client/vault.rs @@ -20,7 +20,6 @@ use awc::{ }; use bytes::Bytes; use futures_core::Stream; -use intel_tee_quote_verification_rs::tee_qv_get_collateral; use rustls::ClientConfig; use serde_json::{json, Value}; use std::{ @@ -28,13 +27,13 @@ use std::{ sync::Arc, time, }; -use teepot::quote::error::QuoteContext; +use teepot::quote::get_collateral; pub use teepot::{ quote::{ tcblevel::{parse_tcb_levels, EnumSet, TcbLevel}, verify_quote_with_collateral, QuoteVerificationResult, }, - sgx::{sgx_gramine_get_quote, sgx_ql_qv_result_t, Collateral}, + sgx::{sgx_gramine_get_quote, Collateral}, }; use tracing::{debug, error, info, trace}; @@ -158,7 +157,7 @@ impl VaultConnection { info!("Getting attestation report"); let attestation_url = AuthRequest::URL; let quote = sgx_gramine_get_quote(&self.key_hash).context("Failed to get own quote")?; - let collateral = tee_qv_get_collateral("e).context("Failed to get own collateral")?; + let collateral = get_collateral("e).context("Failed to get own collateral")?; let auth_req = AuthRequest { name: self.name.clone(), diff --git a/crates/teepot/Cargo.toml b/crates/teepot/Cargo.toml index 8f960c4..c848a92 100644 --- a/crates/teepot/Cargo.toml +++ b/crates/teepot/Cargo.toml @@ -10,6 +10,15 @@ edition.workspace = true authors.workspace = true repository.workspace = true +[target.'cfg(all(target_os = "linux", target_arch = "x86_64"))'.dependencies] +tdx-attest-rs = { version = "0.1.2", git = "https://github.com/intel/SGXDataCenterAttestationPrimitives.git", rev = "aa239d25a437a28f3f4de92c38f5b6809faac842" } +teepot-tee-quote-verification-rs = { path = "../teepot-tee-quote-verification-rs" } + +[target.'cfg(not(all(target_os = "linux", target_arch = "x86_64")))'.dependencies] +dcap-qvl = "0.2.3" +chrono = "0.4.40" +bytes.workspace = true + [dependencies] anyhow.workspace = true async-trait.workspace = true @@ -18,9 +27,9 @@ clap.workspace = true config.workspace = true const-oid.workspace = true enumset.workspace = true +futures = "0.3.31" getrandom.workspace = true hex.workspace = true -intel-tee-quote-verification-rs.workspace = true num-integer.workspace = true num-traits.workspace = true opentelemetry.workspace = true @@ -39,8 +48,8 @@ serde_json.workspace = true sha2.workspace = true sha3.workspace = true signature.workspace = true -tdx-attest-rs.workspace = true thiserror.workspace = true +tokio.workspace = true tracing.workspace = true tracing-futures.workspace = true tracing-log.workspace = true diff --git a/crates/teepot/src/pki/mod.rs b/crates/teepot/src/pki/mod.rs index bed0cf6..b79f864 100644 --- a/crates/teepot/src/pki/mod.rs +++ b/crates/teepot/src/pki/mod.rs @@ -2,13 +2,12 @@ // Copyright (c) 2023-2025 Matter Labs //! Create a private key and a signed and self-signed certificates -use crate::quote::{error::QuoteContext, get_quote}; +use crate::quote::{get_collateral, get_quote}; use anyhow::{Context, Result}; use const_oid::{ db::rfc5280::{ID_KP_CLIENT_AUTH, ID_KP_SERVER_AUTH}, AssociatedOid, }; -use intel_tee_quote_verification_rs::tee_qv_get_collateral; use p256::{ecdsa::DerSignature, pkcs8::EncodePrivateKey}; use pkcs8::der; use rustls::pki_types::PrivatePkcs8KeyDer; @@ -148,7 +147,7 @@ pub fn make_self_signed_cert( debug!("quote.len: {:?}", quote.len()); // Create a relative distinguished name. let rdns = RdnSequence::from_str(dn)?; - let collateral = tee_qv_get_collateral("e).context("Failed to get own collateral")?; + let collateral = get_collateral("e).context("Failed to get own collateral")?; let mut serial = [0u8; 16]; getrandom::fill(&mut serial)?; diff --git a/crates/teepot/src/quote/attestation.rs b/crates/teepot/src/quote/attestation.rs index a41c8de..4f00065 100644 --- a/crates/teepot/src/quote/attestation.rs +++ b/crates/teepot/src/quote/attestation.rs @@ -4,13 +4,11 @@ //! Common attestation API for all TEEs use crate::quote::{ - error::QuoteContext, - get_quote, + get_collateral, get_quote, tcblevel::{EnumSet, TcbLevel}, verify_quote_with_collateral, Collateral, QuoteVerificationResult, }; use anyhow::{bail, Context, Result}; -use intel_tee_quote_verification_rs::tee_qv_get_collateral; use serde::{Deserialize, Serialize}; use std::{ sync::{Arc, RwLock}, @@ -46,8 +44,7 @@ pub fn get_quote_and_collateral( static ATTESTATION: RwLock> = RwLock::new(None); let unix_time: i64 = std::time::SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() + .duration_since(UNIX_EPOCH)? .as_secs() as _; if let Some(attestation) = ATTESTATION.read().unwrap().as_ref() { @@ -65,11 +62,11 @@ pub fn get_quote_and_collateral( } let (_tee_type, myquote) = get_quote(report_data).context("Failed to get own quote")?; - let collateral = tee_qv_get_collateral(&myquote).context("Failed to get own collateral")?; + let collateral = get_collateral(&myquote).context("Failed to get own collateral")?; let QuoteVerificationResult { collateral_expired, - result, + result: tcblevel, earliest_expiration_date, tcb_level_date_tag, quote, @@ -83,7 +80,6 @@ pub fn get_quote_and_collateral( bail!("Freshly fetched collateral expired"); } - let tcblevel = TcbLevel::from(result); if tcblevel != TcbLevel::Ok && allowed_tcb_levels.map_or(false, |levels| !levels.contains(tcblevel)) { diff --git a/crates/teepot/src/quote/error.rs b/crates/teepot/src/quote/error.rs index 508b5f3..b469161 100644 --- a/crates/teepot/src/quote/error.rs +++ b/crates/teepot/src/quote/error.rs @@ -1,10 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2024 Matter Labs +// Copyright (c) 2024-2025 Matter Labs //! Quote Error type -use intel_tee_quote_verification_rs::quote3_error_t; use std::io; +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] use tdx_attest_rs::tdx_attest_error_t; use thiserror::Error; @@ -22,8 +22,7 @@ pub enum QuoteError { InvalidTeeType, #[error("unsupported body type")] UnsupportedBodyType, - #[error("quote verification error {msg}: {inner:?}")] - Quote3Error { inner: quote3_error_t, msg: String }, + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] #[error("tdx_att_get_quote error {msg}: {inner:?}")] TdxAttGetQuote { inner: tdx_attest_error_t, @@ -35,8 +34,31 @@ pub enum QuoteError { ReportDataSize, #[error("can't get a quote: unknown TEE")] UnknownTee, + #[error("{0}: invalid parameter")] + InvalidParameter(String), + #[error("{0}: platform lib unavailable")] + PlatformLibUnavailable(String), + #[error("{0}: pck cert chain error")] + PckCertChainError(String), + #[error("{0}: pck cert unsupported format")] + PckCertUnsupportedFormat(String), + #[error("{0}: quote format unsupported")] + QuoteFormatUnsupported(String), + #[error("{0}: out of memory")] + OutOfMemory(String), + #[error("{0}: no quote collateral data")] + NoQuoteCollateralData(String), + #[error("{0}: unexpected error")] + Unexpected(String), + #[error("{0}: quote certification data unsupported")] + QuoteCertificationDataUnsupported(String), + #[error("{0}: unable to generate report")] + UnableToGenerateReport(String), + #[error("{0}: CRL unsupported format")] + CrlUnsupportedFormat(String), } +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] impl From for QuoteError { fn from(code: tdx_attest_error_t) -> Self { Self::TdxAttGetQuote { @@ -64,16 +86,29 @@ impl QuoteContext for Result { } } -impl QuoteContext for Result { +impl QuoteContext for Option { type Ok = T; fn context>(self, msg: I) -> Result { - self.map_err(|e| QuoteError::Quote3Error { - msg: msg.into(), - inner: e, - }) + self.ok_or(QuoteError::Unexpected(msg.into())) } } +/// Usability trait for easy QuoteError annotation +pub trait QuoteContextErr { + /// The Ok Type + type Ok; + /// The Context + fn str_context(self, msg: I) -> Result; +} + +impl QuoteContextErr for Result { + type Ok = T; + fn str_context(self, msg: I) -> Result { + self.map_err(|e| QuoteError::Unexpected(format!("{}: {}", msg, e))) + } +} + +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] impl QuoteContext for Result { type Ok = T; fn context>(self, msg: I) -> Result { diff --git a/crates/teepot/src/quote/intel.rs b/crates/teepot/src/quote/intel.rs new file mode 100644 index 0000000..fbbaf0b --- /dev/null +++ b/crates/teepot/src/quote/intel.rs @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2025 Matter Labs + +//! Drive Intel DCAP verification crate, which is using the C library + +use crate::{ + quote::{ + error::QuoteError, tcblevel::TcbLevel, Collateral, Quote, QuoteVerificationResult, TEEType, + }, + sgx::sgx_gramine_get_quote, +}; +use bytemuck::cast_slice; +use std::{ffi::CStr, mem, mem::MaybeUninit, pin::Pin}; +use tdx_attest_rs::{tdx_att_get_quote, tdx_attest_error_t, tdx_report_data_t}; +use teepot_tee_quote_verification_rs::{ + quote3_error_t as _quote3_error_t, sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t, + tee_get_supplemental_data_version_and_size, tee_qv_get_collateral, tee_supp_data_descriptor_t, + tee_verify_quote, Collateral as IntelCollateral, +}; +use tracing::{trace, warn}; + +/// Convert SGX QV result to our TcbLevel enum +fn convert_tcb_level(value: sgx_ql_qv_result_t) -> TcbLevel { + match value { + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK => TcbLevel::Ok, + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE => TcbLevel::OutOfDate, + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED => { + TcbLevel::OutOfDateConfigNeeded + } + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED => TcbLevel::SwHardeningNeeded, + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED => { + TcbLevel::ConfigAndSwHardeningNeeded + } + sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_NEEDED => TcbLevel::ConfigNeeded, + _ => TcbLevel::Invalid, + } +} + +/// Convert quote3_error_t to QuoteError with context +fn convert_quote_error(error: _quote3_error_t, context: impl Into) -> QuoteError { + let context = context.into(); + match error { + _quote3_error_t::SGX_QL_ERROR_INVALID_PARAMETER => QuoteError::InvalidParameter(context), + _quote3_error_t::SGX_QL_PCK_CERT_CHAIN_ERROR => QuoteError::PckCertChainError(context), + _quote3_error_t::SGX_QL_PCK_CERT_UNSUPPORTED_FORMAT => { + QuoteError::PckCertUnsupportedFormat(context) + } + _quote3_error_t::SGX_QL_QUOTE_FORMAT_UNSUPPORTED => { + QuoteError::QuoteFormatUnsupported(context) + } + _quote3_error_t::SGX_QL_ERROR_OUT_OF_MEMORY => QuoteError::OutOfMemory(context), + _quote3_error_t::SGX_QL_NO_QUOTE_COLLATERAL_DATA => { + QuoteError::NoQuoteCollateralData(context) + } + _quote3_error_t::SGX_QL_ERROR_UNEXPECTED => QuoteError::Unexpected(context), + _quote3_error_t::SGX_QL_QUOTE_CERTIFICATION_DATA_UNSUPPORTED => { + QuoteError::QuoteCertificationDataUnsupported(context) + } + _quote3_error_t::SGX_QL_UNABLE_TO_GENERATE_REPORT => { + QuoteError::UnableToGenerateReport(context) + } + _quote3_error_t::SGX_QL_CRL_UNSUPPORTED_FORMAT => QuoteError::CrlUnsupportedFormat(context), + _ => QuoteError::Unexpected(context), + } +} + +/// Convert internal Collateral type to Intel library Collateral type +fn convert_to_intel_collateral(collateral: &Collateral) -> IntelCollateral { + IntelCollateral { + major_version: collateral.major_version, + minor_version: collateral.minor_version, + tee_type: collateral.tee_type, + pck_crl_issuer_chain: collateral.pck_crl_issuer_chain.clone(), + root_ca_crl: collateral.root_ca_crl.clone(), + pck_crl: collateral.pck_crl.clone(), + tcb_info_issuer_chain: collateral.tcb_info_issuer_chain.clone(), + tcb_info: collateral.tcb_info.clone(), + qe_identity_issuer_chain: collateral.qe_identity_issuer_chain.clone(), + qe_identity: collateral.qe_identity.clone(), + } +} + +/// Get collateral data for a quote +pub fn get_collateral(quote: &[u8]) -> Result { + let collateral = tee_qv_get_collateral(quote) + .map_err(|e| convert_quote_error(e, "tee_qv_get_collateral"))?; + + Ok(Collateral { + major_version: collateral.major_version, + minor_version: collateral.minor_version, + tee_type: collateral.tee_type, + pck_crl_issuer_chain: collateral.pck_crl_issuer_chain, + root_ca_crl: collateral.root_ca_crl, + pck_crl: collateral.pck_crl, + tcb_info_issuer_chain: collateral.tcb_info_issuer_chain, + tcb_info: collateral.tcb_info, + qe_identity_issuer_chain: collateral.qe_identity_issuer_chain, + qe_identity: collateral.qe_identity, + }) +} + +/// Extract advisory information from supplemental data +fn extract_supplemental_data_info(supp_data: sgx_ql_qv_supplemental_t) -> (Vec, i64, i64) { + // Convert to valid UTF-8 string + let advisories = CStr::from_bytes_until_nul(cast_slice(&supp_data.sa_list[..])) + .ok() + .and_then(|s| CStr::to_str(s).ok()) + .into_iter() + .flat_map(|s| s.split(',').map(str::trim).map(String::from)) + .filter(|s| !s.is_empty()) + .collect(); + + ( + advisories, + supp_data.earliest_expiration_date, + supp_data.tcb_level_date_tag, + ) +} + +/// Verifies a quote with optional collateral material +pub(crate) fn verify_quote_with_collateral( + quote: &[u8], + collateral: Option<&crate::quote::Collateral>, + current_time: i64, +) -> Result { + // Convert collateral if provided + let intel_collateral = collateral.map(convert_to_intel_collateral); + + let TeeSuppDataDescriptor { + supp_data, + mut supp_data_descriptor, + } = initialize_supplemental_data(quote)?; + + let (collateral_expiration_status, result) = tee_verify_quote( + quote, + intel_collateral.as_ref(), + current_time, + None, + supp_data_descriptor.as_mut(), + ) + .map_err(|e| convert_quote_error(e, "tee_verify_quote"))?; + + // Extract supplemental data if available + let (advisories, earliest_expiration_date, tcb_level_date_tag) = + if supp_data_descriptor.is_some() { + let supp_data = unsafe { supp_data.assume_init() }; + extract_supplemental_data_info(supp_data) + } else { + (vec![], 0, 0) + }; + + let quote = Quote::parse(quote)?; + + Ok(QuoteVerificationResult { + collateral_expired: collateral_expiration_status != 0, + earliest_expiration_date, + tcb_level_date_tag, + result: convert_tcb_level(result), + quote, + advisories, + }) +} + +struct TeeSuppDataDescriptor { + supp_data: Pin>>, + supp_data_descriptor: Option, +} + +fn initialize_supplemental_data(quote: &[u8]) -> Result { + let mut supp_data = Box::pin(mem::MaybeUninit::zeroed()); + let mut supp_data_desc = tee_supp_data_descriptor_t { + major_version: 0, + data_size: 0, + p_data: supp_data.as_mut_ptr() as *mut u8, + }; + trace!("tee_get_supplemental_data_version_and_size"); + let (_, supp_size) = tee_get_supplemental_data_version_and_size(quote) + .map_err(|e| convert_quote_error(e, "tee_get_supplemental_data_version_and_size"))?; + + trace!( + "tee_get_supplemental_data_version_and_size supp_size: {}", + supp_size + ); + + let p_supplemental_data = if supp_size == mem::size_of::() as u32 { + supp_data_desc.data_size = supp_size; + Some(supp_data_desc) + } else { + supp_data_desc.data_size = 0; + trace!( + "tee_get_supplemental_data_version_and_size supp_size: {}", + supp_size + ); + trace!( + "mem::size_of::(): {}", + mem::size_of::() + ); + warn!("Quote supplemental data size is different between DCAP QVL and QvE, please make sure you install DCAP QVL and QvE from the same release."); + None + }; + + Ok(TeeSuppDataDescriptor { + supp_data, + supp_data_descriptor: p_supplemental_data, + }) +} + +/// Prepare report data for quote generation +fn prepare_report_data(report_data: &[u8]) -> Result<[u8; 64], QuoteError> { + if report_data.len() > 64 { + return Err(QuoteError::ReportDataSize); + } + + let mut report_data_fixed = [0u8; 64]; + report_data_fixed[..report_data.len()].copy_from_slice(report_data); + Ok(report_data_fixed) +} + +/// Get a TDX quote +fn tdx_get_quote(report_data_bytes: &[u8; 64]) -> Result, 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()) + } +} + +/// Detect the TEE environment +fn detect_tee_environment() -> Result { + if std::fs::metadata("/dev/attestation").is_ok() { + Ok(TEEType::SGX) + } else if std::fs::metadata("/dev/tdx_guest").is_ok() { + Ok(TEEType::TDX) + } else { + Err(QuoteError::UnknownTee) + } +} + +/// Get the attestation quote from a TEE +pub(crate) fn get_quote(report_data: &[u8]) -> Result<(TEEType, Box<[u8]>), QuoteError> { + let report_data_fixed = prepare_report_data(report_data)?; + + match detect_tee_environment()? { + TEEType::SGX => Ok((TEEType::SGX, sgx_gramine_get_quote(&report_data_fixed)?)), + TEEType::TDX => Ok((TEEType::TDX, tdx_get_quote(&report_data_fixed)?)), + _ => Err(QuoteError::UnknownTee), // For future TEE types + } +} diff --git a/crates/teepot/src/quote/mod.rs b/crates/teepot/src/quote/mod.rs index 321aa08..8a373cf 100644 --- a/crates/teepot/src/quote/mod.rs +++ b/crates/teepot/src/quote/mod.rs @@ -10,27 +10,25 @@ pub mod attestation; pub mod error; pub mod tcblevel; -use crate::{ - quote::error::{QuoteContext as _, QuoteError}, - sgx::sgx_gramine_get_quote, - tdx::tgx_get_quote, -}; -use bytemuck::{cast_slice, AnyBitPattern}; -use intel_tee_quote_verification_rs::{ - sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t, tee_get_supplemental_data_version_and_size, - tee_supp_data_descriptor_t, tee_verify_quote, Collateral, +#[cfg_attr(all(target_os = "linux", target_arch = "x86_64"), path = "intel.rs")] +#[cfg_attr( + not(all(target_os = "linux", target_arch = "x86_64")), + path = "phala.rs" +)] +mod os; + +use crate::quote::{ + error::{QuoteContext as _, QuoteError}, + tcblevel::TcbLevel, }; +use bytemuck::AnyBitPattern; use serde::{Deserialize, Serialize}; use std::{ - ffi::CStr, fmt::{Display, Formatter}, io::Read, - mem, str::FromStr, }; -use tracing::{trace, warn}; - -pub use intel_tee_quote_verification_rs::tee_qv_get_collateral; +use tracing::trace; #[allow(missing_docs)] pub const TEE_TYPE_SGX: u32 = 0x00000000; @@ -603,35 +601,13 @@ impl FromStr for TEEType { /// Get the attestation quote from a TEE pub fn get_quote(report_data: &[u8]) -> Result<(TEEType, Box<[u8]>), QuoteError> { - // check, if we are running in a TEE - if std::fs::metadata("/dev/attestation").is_ok() { - if report_data.len() > 64 { - return Err(QuoteError::ReportDataSize); - } - - let mut report_data_fixed = [0u8; 64]; - report_data_fixed[..report_data.len()].copy_from_slice(report_data); - - Ok((TEEType::SGX, sgx_gramine_get_quote(&report_data_fixed)?)) - } else if std::fs::metadata("/dev/tdx_guest").is_ok() { - if report_data.len() > 64 { - return Err(QuoteError::ReportDataSize); - } - - let mut report_data_fixed = [0u8; 64]; - report_data_fixed[..report_data.len()].copy_from_slice(report_data); - - Ok((TEEType::TDX, tgx_get_quote(&report_data_fixed)?)) - } else { - // if not, return an error - Err(QuoteError::UnknownTee) - } + os::get_quote(report_data) } /// The result of the quote verification pub struct QuoteVerificationResult { /// the raw result - pub result: sgx_ql_qv_result_t, + pub result: TcbLevel, /// indicates if the collateral is expired pub collateral_expired: bool, /// the earliest expiration date of the collateral @@ -644,93 +620,41 @@ pub struct QuoteVerificationResult { pub quote: Quote, } +/// The collateral data needed to do remote attestation for SGX and TDX +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Collateral { + /// Major version of the collateral data + pub major_version: u16, + /// Minor version of the collateral data + pub minor_version: u16, + /// Type of TEE (SGX=0, TDX=0x81) + pub tee_type: u32, + /// The PCK CRL issuer chain used for validating the PCK CRL + pub pck_crl_issuer_chain: Box<[u8]>, + /// The root CA CRL used for validating the PCK CRL issuer chain + pub root_ca_crl: Box<[u8]>, + /// The PCK CRL used for validating the PCK certificate + pub pck_crl: Box<[u8]>, + /// The TCB info issuer chain used for validating the TCB info + pub tcb_info_issuer_chain: Box<[u8]>, + /// The TCB info used for determining the TCB level + pub tcb_info: Box<[u8]>, + /// The QE identity issuer chain used for validating the QE identity + pub qe_identity_issuer_chain: Box<[u8]>, + /// The QE identity used for validating the QE + pub qe_identity: Box<[u8]>, +} + +/// Get the collateral data from an SGX or TDX quote +pub fn get_collateral(quote: &[u8]) -> Result { + os::get_collateral(quote) +} + /// Verifies a quote with optional collateral material pub fn verify_quote_with_collateral( quote: &[u8], collateral: Option<&Collateral>, current_time: i64, ) -> Result { - let mut supp_data: mem::MaybeUninit = mem::MaybeUninit::zeroed(); - let mut supp_data_desc = tee_supp_data_descriptor_t { - major_version: 0, - data_size: 0, - p_data: supp_data.as_mut_ptr() as *mut u8, - }; - trace!("tee_get_supplemental_data_version_and_size"); - let (_, supp_size) = - tee_get_supplemental_data_version_and_size(quote).map_err(|e| QuoteError::Quote3Error { - msg: "tee_get_supplemental_data_version_and_size".into(), - inner: e, - })?; - - trace!( - "tee_get_supplemental_data_version_and_size supp_size: {}", - supp_size - ); - - if supp_size == mem::size_of::() as u32 { - supp_data_desc.data_size = supp_size; - } else { - supp_data_desc.data_size = 0; - trace!( - "tee_get_supplemental_data_version_and_size supp_size: {}", - supp_size - ); - trace!( - "mem::size_of::(): {}", - mem::size_of::() - ); - warn!("Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release.") - } - - let p_supplemental_data = match supp_data_desc.data_size { - 0 => None, - _ => Some(&mut supp_data_desc), - }; - - let has_sup = p_supplemental_data.is_some(); - - trace!("tee_verify_quote"); - - let (collateral_expiration_status, result) = - tee_verify_quote(quote, collateral, current_time, None, p_supplemental_data) - .context("tee_verify_quote")?; - - trace!("tee_verify_quote end"); - - // check supplemental data if necessary - let (advisories, earliest_expiration_date, tcb_level_date_tag) = if has_sup { - unsafe { - let supp_data = supp_data.assume_init(); - // convert to valid UTF-8 string - let ads = CStr::from_bytes_until_nul(cast_slice(&supp_data.sa_list[..])) - .ok() - .and_then(|s| CStr::to_str(s).ok()) - .into_iter() - .flat_map(|s| s.split(',').map(str::trim).map(String::from)) - .filter(|s| !s.is_empty()) - .collect(); - ( - ads, - supp_data.earliest_expiration_date, - supp_data.tcb_level_date_tag, - ) - } - } else { - (vec![], 0, 0) - }; - - trace!("Quote::parse"); - let quote = Quote::parse(quote)?; - - let res = QuoteVerificationResult { - collateral_expired: collateral_expiration_status != 0, - earliest_expiration_date, - tcb_level_date_tag, - result, - quote, - advisories, - }; - - Ok(res) + os::verify_quote_with_collateral(quote, collateral, current_time) } diff --git a/crates/teepot/src/quote/phala.rs b/crates/teepot/src/quote/phala.rs new file mode 100644 index 0000000..e416110 --- /dev/null +++ b/crates/teepot/src/quote/phala.rs @@ -0,0 +1,259 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright (c) 2023-2025 Matter Labs + +//! Emulate Intel DCAP library collateral and verification + +use crate::quote::{ + error::{QuoteContext, QuoteContextErr, QuoteError}, + tcblevel::TcbLevel, + Collateral, Quote, QuoteVerificationResult, TEEType, +}; +use bytes::Bytes; +use dcap_qvl::{verify::VerifiedReport, QuoteCollateralV3}; +use std::ffi::{CStr, CString}; +use std::str::FromStr; + +/// Helper function to extract a required header value from a response +fn extract_header_value( + response: &reqwest::Response, + header_name: &str, +) -> Result { + response + .headers() + .get(header_name) + .ok_or_else(|| QuoteError::Unexpected(format!("Missing required header: {header_name}")))? + .to_str() + .map_err(|e| QuoteError::Unexpected(format!("Invalid header value: {e}"))) + .map(|val| val.to_string()) +} + +/// Fetch collateral data from Intel's Provisioning Certification Service +async fn fetch_pcs_collateral( + quote: &[u8], +) -> Result<(QuoteCollateralV3, String, Bytes), QuoteError> { + let client = reqwest::Client::new(); + let response = client + .get("https://api.trustedservices.intel.com/sgx/certification/v4/pckcrl?ca=platform") + .send() + .await + .map_err(|e| QuoteError::Unexpected(format!("Failed to fetch collateral: {e}")))?; + + // Extract required fields + let issuer_chain = extract_header_value(&response, "SGX-PCK-CRL-Issuer-Chain")?; + let pck_crl_data = response + .bytes() + .await + .map_err(|e| QuoteError::Unexpected(format!("Failed to fetch collateral data: {e}")))?; + + // Fetch the full collateral + dcap_qvl::collateral::get_collateral_from_pcs(quote, std::time::Duration::from_secs(1000)) + .await + .map(|collateral| (collateral, issuer_chain, pck_crl_data)) + .str_context("Fetching PCS collateral with `get_collateral_from_pcs`") +} + +/// Get collateral for a quote, handling the async operations +pub(crate) fn get_collateral(quote: &[u8]) -> Result { + // Execute the async operation in a separate thread + let result = std::thread::scope(|s| { + s.spawn(|| { + // Create a minimal runtime for this thread only + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .context("Failed to build tokio runtime")?; + + // Run the async function + rt.block_on(fetch_pcs_collateral(quote)) + }) + .join() + .map_err(|_| QuoteError::Unexpected("Thread panic in get_collateral".into())) + })??; + + // Destructure the result + let (collateral, pck_crl, pck_issuer_chain) = result; + + // Convert QuoteCollateralV3 to Collateral + convert_to_collateral(collateral, pck_crl, pck_issuer_chain) +} + +// Helper function to convert QuoteCollateralV3 to Collateral +fn convert_to_collateral( + collateral: QuoteCollateralV3, + pck_crl: String, + pck_issuer_chain: Bytes, +) -> Result { + let QuoteCollateralV3 { + tcb_info_issuer_chain, + tcb_info, + tcb_info_signature, + qe_identity_issuer_chain, + qe_identity, + qe_identity_signature, + } = collateral; + + let tcb_info_signature = hex::encode(tcb_info_signature); + let qe_identity_signature = hex::encode(qe_identity_signature); + + // Create strings with proper formatting + let tcb_info_json = + format!("{{ \"tcbInfo\": {tcb_info}, \"signature\": \"{tcb_info_signature}\" }}"); + + let qe_identity_json = format!( + "{{ \"enclaveIdentity\": {qe_identity}, \"signature\": \"{qe_identity_signature}\" }}" + ); + + // Helper to create CString and convert to Box<[u8]> + let to_bytes_with_nul = |s: String, context: &str| -> Result, QuoteError> { + Ok(CString::new(s) + .str_context(context)? + .as_bytes_with_nul() + .into()) + }; + + Ok(Collateral { + // Default/unhandled values + major_version: 0, + minor_version: 0, + tee_type: 0, + root_ca_crl: Box::new([]), + + // Converted values + pck_crl_issuer_chain: pck_issuer_chain.as_ref().into(), + pck_crl: pck_crl.as_bytes().into(), + tcb_info_issuer_chain: to_bytes_with_nul(tcb_info_issuer_chain, "tcb_info_issuer_chain")?, + tcb_info: to_bytes_with_nul(tcb_info_json, "tcb_info")?, + qe_identity_issuer_chain: to_bytes_with_nul( + qe_identity_issuer_chain, + "qe_identity_issuer_chain", + )?, + qe_identity: to_bytes_with_nul(qe_identity_json, "qe_identity")?, + }) +} + +/// Split the last zero byte +fn get_str_from_bytes(bytes: &[u8], context: &str) -> Result { + let c_str = CStr::from_bytes_until_nul(bytes) + .str_context(format!("Failed to extract CString: {}", context))?; + Ok(c_str.to_string_lossy().into_owned()) +} + +/// Parse JSON field from collateral data +fn parse_json_field(data: &[u8], context: &str) -> Result { + serde_json::from_str(&get_str_from_bytes(data, context)?) + .str_context(format!("Failed to parse JSON: {}", context)) +} + +/// Convert Collateral to QuoteCollateralV3 +fn convert_collateral(collateral: &Collateral) -> Result { + // Parse TCB info + let tcb_info_json = parse_json_field(collateral.tcb_info.as_ref(), "tcb_info_json")?; + + let tcb_info = tcb_info_json["tcbInfo"].to_string(); + let tcb_info_signature = tcb_info_json + .get("signature") + .context("TCB Info missing 'signature' field")? + .as_str() + .context("TCB Info signature must be a string")?; + + let tcb_info_signature = hex::decode(tcb_info_signature) + .ok() + .context("TCB Info signature must be valid hex")?; + + // Parse QE identity + let qe_identity_json = parse_json_field(collateral.qe_identity.as_ref(), "qe_identity_json")?; + + let qe_identity = qe_identity_json + .get("enclaveIdentity") + .context("QE Identity missing 'enclaveIdentity' field")? + .to_string(); + + let qe_identity_signature = qe_identity_json + .get("signature") + .context("QE Identity missing 'signature' field")? + .as_str() + .context("QE Identity signature must be a string")?; + + let qe_identity_signature = hex::decode(qe_identity_signature) + .ok() + .context("QE Identity signature must be valid hex")?; + + Ok(QuoteCollateralV3 { + tcb_info_issuer_chain: get_str_from_bytes( + collateral.tcb_info_issuer_chain.as_ref(), + "convert_collateral: tcb_info_issuer_chain", + )?, + tcb_info, + tcb_info_signature, + qe_identity_issuer_chain: get_str_from_bytes( + collateral.qe_identity_issuer_chain.as_ref(), + "convert_collateral: qe_identity_issuer_chain", + )?, + qe_identity, + qe_identity_signature, + }) +} + +/// Verify a quote with the provided collateral +pub(crate) fn verify_quote_with_collateral( + quote: &[u8], + collateral: Option<&Collateral>, + current_time: i64, +) -> Result { + // Convert collateral or return error if not provided + let collateral = collateral + .ok_or_else(|| QuoteError::Unexpected("No collateral provided".into())) + .and_then(convert_collateral)?; + + // Convert current time to u64 + let current_time_u64 = current_time + .try_into() + .str_context("Failed to convert current_time to u64")?; + + // Verify the quote + let verified_report = dcap_qvl::verify::verify(quote, &collateral, current_time_u64) + .expect("Failed to verify quote"); + + let VerifiedReport { + status, + advisory_ids, + report: _, + } = verified_report; + + // Parse TCB level from status + let result = + TcbLevel::from_str(&status).str_context("Failed to parse TCB level from status")?; + + // Parse quote + let quote = Quote::parse(quote)?; + + let tcb_info_json: serde_json::Value = + serde_json::from_str(&String::from_utf8_lossy(collateral.tcb_info.as_ref())) + .str_context("verify_quote_with_collateral tcb_info_json")?; + + let next_update = tcb_info_json + .get("nextUpdate") + .context("verify_quote_with_collateral: TCB Info missing 'nextUpdate' field")? + .as_str() + .context("verify_quote_with_collateral: TCB Info nextUpdate must be a string")?; + + let next_update = chrono::DateTime::parse_from_rfc3339(next_update) + .ok() + .context("verify_quote_with_collateral: Failed to parse next update")?; + + Ok(QuoteVerificationResult { + result, + collateral_expired: result == TcbLevel::OutOfDate, + earliest_expiration_date: next_update + .signed_duration_since(chrono::DateTime::UNIX_EPOCH) + .num_seconds(), + tcb_level_date_tag: 0, + advisories: advisory_ids, + quote, + }) +} + +/// Get the attestation quote from a TEE +pub fn get_quote(_report_data: &[u8]) -> Result<(TEEType, Box<[u8]>), QuoteError> { + Err(QuoteError::UnknownTee) +} diff --git a/crates/teepot/src/quote/tcblevel.rs b/crates/teepot/src/quote/tcblevel.rs index 25669f0..f2baee5 100644 --- a/crates/teepot/src/quote/tcblevel.rs +++ b/crates/teepot/src/quote/tcblevel.rs @@ -4,7 +4,6 @@ //! Intel SGX Enclave TCB level wrapper use enumset::EnumSetType; -use intel_tee_quote_verification_rs::sgx_ql_qv_result_t; use serde::{Deserialize, Serialize}; use std::{ fmt::{Display, Formatter}, @@ -34,37 +33,20 @@ pub enum TcbLevel { Invalid, } -impl From for TcbLevel { - fn from(value: sgx_ql_qv_result_t) -> Self { - match value { - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK => TcbLevel::Ok, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE => TcbLevel::OutOfDate, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED => { - TcbLevel::OutOfDateConfigNeeded - } - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED => TcbLevel::SwHardeningNeeded, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED => { - TcbLevel::ConfigAndSwHardeningNeeded - } - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_NEEDED => TcbLevel::ConfigNeeded, - _ => TcbLevel::Invalid, - } - } -} - impl FromStr for TcbLevel { - type Err = (); + type Err = String; fn from_str(s: &str) -> Result { - match s { - "Ok" => Ok(TcbLevel::Ok), - "ConfigNeeded" => Ok(TcbLevel::ConfigNeeded), - "ConfigAndSwHardeningNeeded" => Ok(TcbLevel::ConfigAndSwHardeningNeeded), - "SwHardeningNeeded" => Ok(TcbLevel::SwHardeningNeeded), - "OutOfDate" => Ok(TcbLevel::OutOfDate), - "OutOfDateConfigNeeded" => Ok(TcbLevel::OutOfDateConfigNeeded), - "Invalid" => Ok(TcbLevel::Invalid), - _ => Err(()), + match s.to_ascii_lowercase().as_str() { + "ok" => Ok(TcbLevel::Ok), + "uptodate" => Ok(TcbLevel::Ok), + "configneeded" => Ok(TcbLevel::ConfigNeeded), + "configandswhardeningneeded" => Ok(TcbLevel::ConfigAndSwHardeningNeeded), + "swhardeningneeded" => Ok(TcbLevel::SwHardeningNeeded), + "outofdate" => Ok(TcbLevel::OutOfDate), + "outofdateconfigneeded" => Ok(TcbLevel::OutOfDateConfigNeeded), + "invalid" => Ok(TcbLevel::Invalid), + _ => Err(format!("Invalid TCB level: {}", s)), } } } diff --git a/crates/teepot/src/sgx/mod.rs b/crates/teepot/src/sgx/mod.rs index d5dba44..8a9f85d 100644 --- a/crates/teepot/src/sgx/mod.rs +++ b/crates/teepot/src/sgx/mod.rs @@ -8,9 +8,8 @@ pub mod sign; use crate::quote::error::QuoteContext; -pub use crate::quote::error::QuoteError; +pub use crate::quote::{error::QuoteError, Collateral}; use bytemuck::{try_from_bytes, AnyBitPattern, PodCastError}; -pub use intel_tee_quote_verification_rs::{sgx_ql_qv_result_t, Collateral}; use std::{ fs::OpenOptions, io::{Read, Write}, diff --git a/crates/teepot/src/tdx/mod.rs b/crates/teepot/src/tdx/mod.rs index 321c2d7..878cd17 100644 --- a/crates/teepot/src/tdx/mod.rs +++ b/crates/teepot/src/tdx/mod.rs @@ -3,29 +3,17 @@ //! Intel TDX helper functions. +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] pub mod rtmr; -use crate::sgx::QuoteError; -pub use intel_tee_quote_verification_rs::Collateral; -use tdx_attest_rs::{tdx_att_get_quote, tdx_attest_error_t, tdx_report_data_t}; - -/// Get a TDX quote -pub fn tgx_get_quote(report_data_bytes: &[u8; 64]) -> Result, 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()) - } -} +/// The sha384 digest of 0u32, which is used in the UEFI TPM protocol +/// as a marker. Used to advance the PCR. +/// ```shell +/// $ echo -n -e "\000\000\000\000" | sha384sum -b +/// 394341b7182cd227c5c6b07ef8000cdfd86136c4292b8e576573ad7ed9ae41019f5818b4b971c9effc60e1ad9f1289f0 *- +/// ``` +pub const UEFI_MARKER_DIGEST_BYTES: [u8; 48] = [ + 0x39, 0x43, 0x41, 0xb7, 0x18, 0x2c, 0xd2, 0x27, 0xc5, 0xc6, 0xb0, 0x7e, 0xf8, 0x00, 0x0c, 0xdf, + 0xd8, 0x61, 0x36, 0xc4, 0x29, 0x2b, 0x8e, 0x57, 0x65, 0x73, 0xad, 0x7e, 0xd9, 0xae, 0x41, 0x01, + 0x9f, 0x58, 0x18, 0xb4, 0xb9, 0x71, 0xc9, 0xef, 0xfc, 0x60, 0xe1, 0xad, 0x9f, 0x12, 0x89, 0xf0, +]; diff --git a/crates/teepot/src/tdx/rtmr.rs b/crates/teepot/src/tdx/rtmr.rs index dbb8d67..58725f3 100644 --- a/crates/teepot/src/tdx/rtmr.rs +++ b/crates/teepot/src/tdx/rtmr.rs @@ -5,18 +5,6 @@ use crate::sgx::QuoteError; -/// The sha384 digest of 0u32, which is used in the UEFI TPM protocol -/// as a marker. Used to advance the PCR. -/// ```shell -/// $ echo -n -e "\000\000\000\000" | sha384sum -b -/// 394341b7182cd227c5c6b07ef8000cdfd86136c4292b8e576573ad7ed9ae41019f5818b4b971c9effc60e1ad9f1289f0 *- -/// ``` -pub const UEFI_MARKER_DIGEST_BYTES: [u8; 48] = [ - 0x39, 0x43, 0x41, 0xb7, 0x18, 0x2c, 0xd2, 0x27, 0xc5, 0xc6, 0xb0, 0x7e, 0xf8, 0x00, 0x0c, 0xdf, - 0xd8, 0x61, 0x36, 0xc4, 0x29, 0x2b, 0x8e, 0x57, 0x65, 0x73, 0xad, 0x7e, 0xd9, 0xae, 0x41, 0x01, - 0x9f, 0x58, 0x18, 0xb4, 0xb9, 0x71, 0xc9, 0xef, 0xfc, 0x60, 0xe1, 0xad, 0x9f, 0x12, 0x89, 0xf0, -]; - /// The actual rtmr event data handled in DCAP #[repr(C, packed)] pub struct TdxRtmrEvent { @@ -103,7 +91,7 @@ impl From for Vec { #[cfg(test)] mod test { - use super::UEFI_MARKER_DIGEST_BYTES; + use crate::tdx::UEFI_MARKER_DIGEST_BYTES; #[test] fn test_uefi_marker_digest() { diff --git a/crates/teepot/tests/sgx_quote_verification.rs b/crates/teepot/tests/sgx_quote_verification.rs index 08c8198..28a33e9 100644 --- a/crates/teepot/tests/sgx_quote_verification.rs +++ b/crates/teepot/tests/sgx_quote_verification.rs @@ -1,13 +1,15 @@ // SPDX-License-Identifier: Apache-2.0 -// Copyright (c) 2024 Matter Labs +// Copyright (c) 2024-2025 Matter Labs mod sgx { use anyhow::{Context, Result}; - use intel_tee_quote_verification_rs::{sgx_ql_qv_result_t, Collateral}; use std::time::{Duration, UNIX_EPOCH}; use teepot::{ prover::reportdata::{ReportData, ReportDataV1}, - quote::{verify_quote_with_collateral, Quote, QuoteVerificationResult, Report}, + quote::{ + tcblevel::TcbLevel, verify_quote_with_collateral, Collateral, Quote, + QuoteVerificationResult, Report, + }, }; use tracing_test::traced_test; @@ -17,7 +19,7 @@ mod sgx { current_time: i64, expected_mrsigner: &[u8], expected_reportdata: &[u8], - expected_result: sgx_ql_qv_result_t, + expected_result: TcbLevel, ) -> Result<()> { let QuoteVerificationResult { collateral_expired, @@ -28,7 +30,7 @@ mod sgx { tcb_level_date_tag, } = verify_quote_with_collateral(quote, collateral, current_time)?; - if collateral_expired || result != sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK { + if collateral_expired || result != TcbLevel::Ok { print!("Attestation failed: "); if collateral_expired { @@ -40,28 +42,7 @@ mod sgx { earliest_expiration_date ); } - - match result { - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK => (), - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_NEEDED => println!("Config needed"), - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED => { - println!("Config and Software hardening needed") - } - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE => println!("Out of date"), - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED => { - println!("Out of Date and Config needed") - } - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED => { - println!("Software hardening needed") - } - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_INVALID_SIGNATURE => { - println!("Invalid signature") - } - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_REVOKED => println!("Revoked"), - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED => println!("Unspecified"), - - _ => println!("Unknown state!"), - } + println!("{result:?}"); } for advisory in advisories { @@ -85,6 +66,8 @@ mod sgx { } #[test] + // alternative quote verification cannot cope with old collateral data format + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] fn sw_hardening() { let quote = [ 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x93, 0x9a, @@ -1144,12 +1127,14 @@ mod sgx { current_time, &mrsigner, &report_data, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED, + TcbLevel::SwHardeningNeeded, ) .unwrap(); } #[test] + // alternative quote verification cannot cope with old collateral data format + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] fn out_of_date() { let quote = [ 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0e, 0x00, 0x93, 0x9a, @@ -2215,7 +2200,7 @@ mod sgx { current_time, &mrsigner, &report_data, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE, + TcbLevel::OutOfDate, ) .unwrap(); } @@ -2598,12 +2583,14 @@ mod sgx { current_time, &mrsigner, &report_data, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED, + TcbLevel::SwHardeningNeeded, ) .unwrap(); } #[test] + #[cfg(all(target_os = "linux", target_arch = "x86_64"))] + // alternative quote verification errors on debug flag fn vault_proxy() { let quote = [ 3, 0, 2, 0, 0, 0, 0, 0, 9, 0, 14, 0, 147, 154, 114, 51, 247, 156, 76, 169, 148, 10, 13, @@ -3681,7 +3668,7 @@ mod sgx { current_time, &mrsigner, &report_data, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED, + TcbLevel::SwHardeningNeeded, ) .unwrap(); } @@ -4809,7 +4796,7 @@ mod sgx { current_time as i64, &mrsigner, &report_data, - sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK, + TcbLevel::Ok, ) .context("check_quote")?; Ok(()) diff --git a/deny.toml b/deny.toml index 2fc391c..1c4ee4e 100644 --- a/deny.toml +++ b/deny.toml @@ -32,6 +32,7 @@ allow = [ "BSD-3-Clause", "OpenSSL", "CC0-1.0", + "Zlib", ] confidence-threshold = 0.8 exceptions = [] diff --git a/packages/container-self-attestation-test-sgx-azure/default.nix b/packages/container-self-attestation-test-sgx-azure/default.nix index d6f6bcb..6f25ff8 100644 --- a/packages/container-self-attestation-test-sgx-azure/default.nix +++ b/packages/container-self-attestation-test-sgx-azure/default.nix @@ -2,10 +2,12 @@ # Copyright (c) 2024 Matter Labs { teepot , pkgs +, stdenv , container-name ? "teepot-self-attestation-test-sgx-azure" , tag ? null , isAzure ? true }: +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else pkgs.lib.tee.sgxGramineContainer { name = container-name; inherit tag; diff --git a/packages/container-tdx-test/default.nix b/packages/container-tdx-test/default.nix index e12c646..9563fff 100644 --- a/packages/container-tdx-test/default.nix +++ b/packages/container-tdx-test/default.nix @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Matter Labs { lib +, stdenv , openssl , curl , dockerTools @@ -8,28 +9,31 @@ , teepot , nixsgx }: -dockerTools.buildLayeredImage { - name = "tdx-test"; +if (stdenv.hostPlatform.isDarwin) then { + # FIXME: dockerTools.buildLayeredImage seems to be broken on Darwin +} else + dockerTools.buildLayeredImage { + name = "tdx-test"; - config.Entrypoint = [ "${teepot.teepot.tdx_test}/bin/tdx-test-dcap" ]; - config.Env = [ - "SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt" - ]; - - contents = buildEnv { - name = "image-root"; - - paths = with dockerTools;[ - teepot.teepot.tdx_test - openssl.out - curl.out - nixsgx.sgx-dcap.quote_verify - nixsgx.sgx-dcap.default_qpl - usrBinEnv - binSh - caCertificates - fakeNss + config.Entrypoint = [ "${teepot.teepot.tdx_test}/bin/tdx-test" ]; + config.Env = [ + "SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt" ]; - pathsToLink = [ "/bin" "/lib" "/etc" "/share" ]; - }; -} + + contents = buildEnv { + name = "image-root"; + + paths = with dockerTools; [ + teepot.teepot.tdx_test + openssl.out + curl.out + # nixsgx.sgx-dcap.quote_verify + # nixsgx.sgx-dcap.default_qpl + usrBinEnv + binSh + caCertificates + fakeNss + ]; + pathsToLink = [ "/bin" "/lib" "/etc" "/share" ]; + }; + } diff --git a/packages/container-tee-key-preexec-dcap/default.nix b/packages/container-tee-key-preexec-dcap/default.nix index b49ff69..c2ebf94 100644 --- a/packages/container-tee-key-preexec-dcap/default.nix +++ b/packages/container-tee-key-preexec-dcap/default.nix @@ -2,6 +2,7 @@ # Copyright (c) 2024 Matter Labs { teepot , pkgs +, stdenv , bash , coreutils , container-name ? "teepot-key-preexec-dcap" @@ -9,6 +10,7 @@ }: let entrypoint = "${bash}/bin/bash"; in +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else pkgs.lib.tee.sgxGramineContainer { name = container-name; inherit tag entrypoint; diff --git a/packages/container-vault-admin-sgx-azure/default.nix b/packages/container-vault-admin-sgx-azure/default.nix index cb50463..dc661ef 100644 --- a/packages/container-vault-admin-sgx-azure/default.nix +++ b/packages/container-vault-admin-sgx-azure/default.nix @@ -2,10 +2,12 @@ # Copyright (c) 2024 Matter Labs { teepot , pkgs +, stdenv , container-name ? "teepot-vault-admin-sgx-azure" , tag ? null , isAzure ? null }: +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else pkgs.lib.tee.sgxGramineContainer { name = container-name; inherit tag; diff --git a/packages/container-vault-admin/default.nix b/packages/container-vault-admin/default.nix index ec70476..ee1549e 100644 --- a/packages/container-vault-admin/default.nix +++ b/packages/container-vault-admin/default.nix @@ -2,11 +2,13 @@ # Copyright (c) 2024 Matter Labs { dockerTools , buildEnv +, stdenv , teepot , openssl , curl , nixsgx }: +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else dockerTools.buildLayeredImage { name = "vault-admin"; diff --git a/packages/container-vault-sgx-azure/default.nix b/packages/container-vault-sgx-azure/default.nix index 9d94e9e..52d88a4 100644 --- a/packages/container-vault-sgx-azure/default.nix +++ b/packages/container-vault-sgx-azure/default.nix @@ -2,6 +2,7 @@ # Copyright (c) 2024 Matter Labs { teepot , pkgs +, stdenv , vat , vault , container-name ? "teepot-vault-sgx-azure" @@ -12,6 +13,7 @@ let entrypoint = "${teepot.teepot.tee_ratls_preexec}/bin/tee-ratls-preexec"; appDir = "/opt/vault"; in +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else pkgs.lib.tee.sgxGramineContainer { name = container-name; inherit tag; @@ -86,5 +88,3 @@ pkgs.lib.tee.sgxGramineContainer { sys.experimental__enable_flock = true; }; } - - diff --git a/packages/container-vault-unseal-sgx-azure/default.nix b/packages/container-vault-unseal-sgx-azure/default.nix index c1f0774..cd2ca12 100644 --- a/packages/container-vault-unseal-sgx-azure/default.nix +++ b/packages/container-vault-unseal-sgx-azure/default.nix @@ -2,11 +2,13 @@ # Copyright (c) 2024 Matter Labs { teepot , pkgs +, stdenv , vat , container-name ? "teepot-vault-unseal-sgx-azure" , tag ? null , isAzure ? true }: +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else pkgs.lib.tee.sgxGramineContainer { name = container-name; inherit tag isAzure; diff --git a/packages/container-vault-unseal/default.nix b/packages/container-vault-unseal/default.nix index 1345d09..22979b9 100644 --- a/packages/container-vault-unseal/default.nix +++ b/packages/container-vault-unseal/default.nix @@ -1,30 +1,43 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Matter Labs { dockerTools +, lib +, stdenv , buildEnv , teepot , openssl , curl , nixsgx }: -dockerTools.buildLayeredImage { - name = "vault-unseal"; +if (stdenv.hostPlatform.isDarwin) then { + # FIXME: dockerTools.buildLayeredImage seems to be broken on Darwin +} else + dockerTools.buildLayeredImage { + name = "vault-unseal"; - config.Entrypoint = [ "${teepot.teepot.vault_unseal}/bin/vault-unseal" ]; + config.Entrypoint = [ "${teepot.teepot.vault_unseal}/bin/vault-unseal" ]; - contents = buildEnv { - name = "image-root"; - paths = with dockerTools; with nixsgx;[ - openssl.out - curl.out - sgx-dcap.quote_verify - sgx-dcap.default_qpl - usrBinEnv - binSh - caCertificates - fakeNss - teepot.teepot.vault_unseal - ]; - pathsToLink = [ "/bin" "/lib" "/etc" ]; - }; -} + contents = buildEnv { + name = "image-root"; + paths = + with dockerTools; + with nixsgx; + [ + openssl.out + curl.out + usrBinEnv + binSh + caCertificates + fakeNss + teepot.teepot.vault_unseal + ] ++ lib.optionals (stdenv.hostPlatform.system == "x86_64-linux") [ + sgx-dcap.quote_verify + sgx-dcap.default_qpl + ]; + pathsToLink = [ + "/bin" + "/lib" + "/etc" + ]; + }; + } diff --git a/packages/container-verify-attestation-sgx/default.nix b/packages/container-verify-attestation-sgx/default.nix index d01e540..e871549 100644 --- a/packages/container-verify-attestation-sgx/default.nix +++ b/packages/container-verify-attestation-sgx/default.nix @@ -2,30 +2,44 @@ # Copyright (c) 2024 Matter Labs { dockerTools , buildEnv +, lib +, stdenv , teepot , openssl , curl , nixsgx }: -dockerTools.buildLayeredImage { - name = "verify-attestation-sgx"; +if (stdenv.hostPlatform.isDarwin) then { + # FIXME: dockerTools.buildLayeredImage seems to be broken on Darwin +} else + dockerTools.buildLayeredImage { + name = "verify-attestation-sgx"; - config.Entrypoint = [ "${teepot.teepot.verify_attestation}/bin/verify-attestation" ]; - config.Env = [ "LD_LIBRARY_PATH=/lib" ]; - contents = buildEnv { - name = "image-root"; + config.Entrypoint = [ "${teepot.teepot.verify_attestation}/bin/verify-attestation" ]; + config.Env = [ "LD_LIBRARY_PATH=/lib" ]; + contents = buildEnv { + name = "image-root"; - paths = with dockerTools; with nixsgx;[ - openssl.out - curl.out - sgx-dcap.quote_verify - sgx-dcap.default_qpl - teepot.teepot.verify_attestation - usrBinEnv - binSh - caCertificates - fakeNss - ]; - pathsToLink = [ "/bin" "/lib" "/etc" "/share" ]; - }; -} + paths = + with dockerTools; + with nixsgx; + [ + openssl.out + curl.out + teepot.teepot.verify_attestation + usrBinEnv + binSh + caCertificates + fakeNss + ] ++ lib.optionals (stdenv.hostPlatform.system == "x86_64-linux") [ + sgx-dcap.quote_verify + sgx-dcap.default_qpl + ]; + pathsToLink = [ + "/bin" + "/lib" + "/etc" + "/share" + ]; + }; + } diff --git a/packages/container-verify-era-proof-attestation-sgx/default.nix b/packages/container-verify-era-proof-attestation-sgx/default.nix index f0918d1..d8be90c 100644 --- a/packages/container-verify-era-proof-attestation-sgx/default.nix +++ b/packages/container-verify-era-proof-attestation-sgx/default.nix @@ -3,31 +3,45 @@ { dockerTools , buildEnv , teepot +, stdenv , openssl , curl , nixsgx , pkg-config }: -dockerTools.buildLayeredImage { - name = "verify-era-proof-attestation"; +if (stdenv.hostPlatform.isDarwin) then { + # FIXME: dockerTools.buildLayeredImage seems to be broken on Darwin +} else + dockerTools.buildLayeredImage { + name = "verify-era-proof-attestation"; - config.Entrypoint = [ "${teepot.teepot.verify_era_proof_attestation}/bin/verify-era-proof-attestation" ]; - config.Env = [ "LD_LIBRARY_PATH=/lib" ]; - contents = buildEnv { - name = "image-root"; - - paths = with dockerTools; with nixsgx;[ - pkg-config - openssl.out - curl.out - sgx-dcap.quote_verify - sgx-dcap.default_qpl - teepot.teepot.verify_era_proof_attestation - usrBinEnv - binSh - caCertificates - fakeNss + config.Entrypoint = [ + "${teepot.teepot.verify_era_proof_attestation}/bin/verify-era-proof-attestation" ]; - pathsToLink = [ "/bin" "/lib" "/etc" "/share" ]; - }; -} + config.Env = [ "LD_LIBRARY_PATH=/lib" ]; + contents = buildEnv { + name = "image-root"; + + paths = + with dockerTools; + with nixsgx; + [ + pkg-config + openssl.out + curl.out + sgx-dcap.quote_verify + sgx-dcap.default_qpl + teepot.teepot.verify_era_proof_attestation + usrBinEnv + binSh + caCertificates + fakeNss + ]; + pathsToLink = [ + "/bin" + "/lib" + "/etc" + "/share" + ]; + }; + } diff --git a/packages/tdx_google/default.nix b/packages/tdx_google/default.nix index 5044fd7..98f16a6 100644 --- a/packages/tdx_google/default.nix +++ b/packages/tdx_google/default.nix @@ -2,9 +2,12 @@ # Copyright (c) 2024 Matter Labs { lib , pkgs +, stdenv , system , ... -}: lib.teepot.nixosGenerate { +}: +if (stdenv.hostPlatform.system != "x86_64-linux") then { } else +lib.teepot.nixosGenerate { inherit (lib) nixosSystem; inherit system pkgs; modules = [ diff --git a/packages/teepot/default.nix b/packages/teepot/default.nix index 9aee174..340bbae 100644 --- a/packages/teepot/default.nix +++ b/packages/teepot/default.nix @@ -1,20 +1,30 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2024 Matter Labs -{ lib, pkgs, makeWrapper, teepot }: -let teepotCrate = teepot.teepotCrate; in +{ lib +, pkgs +, makeWrapper +, teepot +, stdenv +}: +let + teepotCrate = teepot.teepotCrate; +in teepotCrate.craneLib.buildPackage ( - teepotCrate.commonArgs // { + teepotCrate.commonArgs + // { pname = "teepot"; inherit (teepotCrate) cargoArtifacts; nativeBuildInputs = teepotCrate.commonArgs.nativeBuildInputs ++ [ makeWrapper ]; passthru = { - inherit (teepotCrate) rustPlatform + inherit (teepotCrate) + rustPlatform rustVersion commonArgs craneLib - cargoArtifacts; + cargoArtifacts + ; }; outputs = [ @@ -37,9 +47,10 @@ teepotCrate.craneLib.buildPackage ( "verify_era_proof_attestation" ]; - postInstall = '' + postInstall = lib.optionalString (stdenv.hostPlatform.system == "x86_64-linux") '' removeReferencesToVendoredSources "$out" "$cargoVendorDir" removeReferencesToVendoredSources "$out" "${teepotCrate.rustVersion}/lib/rustlib/" + '' + '' mkdir -p $out/nix-support for i in $outputs; do [[ $i == "out" ]] && continue @@ -47,14 +58,19 @@ teepotCrate.craneLib.buildPackage ( echo -n "''${!i} " >> $out/nix-support/propagated-user-env-packages binname=''${i//_/-} mv "$out/bin/$binname" "''${!i}/bin/" - - makeWrapper "''${!i}/bin/$binname" "''${!i}/bin/$binname-dcap" \ - --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ pkgs.nixsgx.sgx-dcap.quote_verify pkgs.nixsgx.sgx-dcap.default_qpl pkgs.curl ]}" \ - --set-default QCNL_CONF_PATH "${pkgs.nixsgx.sgx-dcap.default_qpl}/etc/sgx_default_qcnl.conf" - + '' + lib.optionalString (stdenv.hostPlatform.system == "x86_64-linux") '' + makeWrapper "''${!i}/bin/$binname" "''${!i}/bin/$binname-dcap" \ + --prefix LD_LIBRARY_PATH : "${ + lib.makeLibraryPath [ + pkgs.nixsgx.sgx-dcap.quote_verify + pkgs.nixsgx.sgx-dcap.default_qpl + pkgs.curl + ] + }" \ + --set-default QCNL_CONF_PATH "${pkgs.nixsgx.sgx-dcap.default_qpl}/etc/sgx_default_qcnl.conf" + '' + '' done rmdir "$out/bin" ''; } ) - diff --git a/packages/teepotCrate/default.nix b/packages/teepotCrate/default.nix index 9c3be39..41263c3 100644 --- a/packages/teepotCrate/default.nix +++ b/packages/teepotCrate/default.nix @@ -2,12 +2,14 @@ # Copyright (c) 2024 Matter Labs { lib , inputs +, stdenv , makeRustPlatform -, nixsgx +, nixsgx ? null , pkg-config , rust-bin , pkgs , openssl +, darwin }: let rustVersion = rust-bin.fromRustupToolchainFile (inputs.src + "/rust-toolchain.toml"); @@ -23,11 +25,15 @@ let ]; buildInputs = [ - openssl + openssl.dev + ] + ++ lib.optionals (stdenv.hostPlatform.system == "x86_64-linux") [ nixsgx.sgx-sdk nixsgx.sgx-dcap nixsgx.sgx-dcap.quote_verify nixsgx.sgx-dcap.libtdx_attest + ] ++ lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security ]; strictDeps = true; diff --git a/shells/teepot/default.nix b/shells/teepot/default.nix index a8e3195..7fed35a 100644 --- a/shells/teepot/default.nix +++ b/shells/teepot/default.nix @@ -6,11 +6,18 @@ , teepot , nixsgx , stdenv +, }: let - toolchain_with_src = (teepot.teepot.passthru.rustVersion.override { - extensions = [ "rustfmt" "clippy" "rust-src" ]; - }); + toolchain_with_src = ( + teepot.teepot.passthru.rustVersion.override { + extensions = [ + "rustfmt" + "clippy" + "rust-src" + ]; + } + ); in mkShell { inputsFrom = [ teepot.teepot ]; @@ -21,26 +28,34 @@ mkShell { teepot.teepot.passthru.rustPlatform.bindgenHook ]; - packages = with pkgs; [ - dive - taplo - vault - cargo-release - google-cloud-sdk-gce - azure-cli - kubectl - kubectx - k9s - ]; + packages = + with pkgs; + [ + dive + taplo + vault + cargo-release + azure-cli + kubectl + kubectx + k9s + google-cloud-sdk + ]; - TEE_LD_LIBRARY_PATH = lib.makeLibraryPath [ - pkgs.curl - nixsgx.sgx-dcap - nixsgx.sgx-dcap.quote_verify - nixsgx.sgx-dcap.default_qpl - ]; + TEE_LD_LIBRARY_PATH = lib.makeLibraryPath ( + lib.optionals (stdenv.hostPlatform.system == "x86_64-linux") [ + pkgs.curl + nixsgx.sgx-dcap + nixsgx.sgx-dcap.quote_verify + nixsgx.sgx-dcap.default_qpl + ] + ); - QCNL_CONF_PATH = "${nixsgx.sgx-dcap.default_qpl}/etc/sgx_default_qcnl.conf"; + QCNL_CONF_PATH = + if (stdenv.hostPlatform.system != "x86_64-linux") then + "" + else + "${nixsgx.sgx-dcap.default_qpl}/etc/sgx_default_qcnl.conf"; OPENSSL_NO_VENDOR = "1"; RUST_SRC_PATH = "${toolchain_with_src}/lib/rustlib/src/rust/library"; From 0b8f1d54c78c452a58d1e8b7a8ab00f81f3c4bbf Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Mon, 7 Apr 2025 13:41:53 +0200 Subject: [PATCH 2/2] feat: bump rust version to 1.86 fixes the hardcoded `/usr/bin/strip` issue on macos see https://github.com/rust-lang/rust/issues/131206 Signed-off-by: Harald Hoyer --- bin/verify-era-proof-attestation/src/proof/types.rs | 4 ++-- crates/teepot-vault/src/client/mod.rs | 2 +- crates/teepot-vault/src/client/vault.rs | 8 ++++---- crates/teepot/src/quote/attestation.rs | 2 +- flake.lock | 6 +++--- rust-toolchain.toml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bin/verify-era-proof-attestation/src/proof/types.rs b/bin/verify-era-proof-attestation/src/proof/types.rs index af3e905..e2362e6 100644 --- a/bin/verify-era-proof-attestation/src/proof/types.rs +++ b/bin/verify-era-proof-attestation/src/proof/types.rs @@ -61,12 +61,12 @@ impl Proof { pub fn is_permanently_ignored(&self) -> bool { self.status .as_ref() - .map_or(false, |s| s.eq_ignore_ascii_case("permanently_ignored")) + .is_some_and(|s| s.eq_ignore_ascii_case("permanently_ignored")) } /// Check if the proof is failed or picked by a prover pub fn is_failed_or_picked(&self) -> bool { - self.status.as_ref().map_or(false, |s| { + self.status.as_ref().is_some_and(|s| { s.eq_ignore_ascii_case("failed") || s.eq_ignore_ascii_case("picked_by_prover") }) } diff --git a/crates/teepot-vault/src/client/mod.rs b/crates/teepot-vault/src/client/mod.rs index f254fd8..97625d7 100644 --- a/crates/teepot-vault/src/client/mod.rs +++ b/crates/teepot-vault/src/client/mod.rs @@ -222,7 +222,7 @@ impl TeeConnection { if self .args .sgx_allowed_tcb_levels - .map_or(true, |levels| !levels.contains(tcblevel)) + .is_none_or(|levels| !levels.contains(tcblevel)) { error!("Quote verification result: {}", tcblevel); return Err(Error::General(format!( diff --git a/crates/teepot-vault/src/client/vault.rs b/crates/teepot-vault/src/client/vault.rs index 42cfbae..c3cf4ad 100644 --- a/crates/teepot-vault/src/client/vault.rs +++ b/crates/teepot-vault/src/client/vault.rs @@ -297,7 +297,7 @@ impl VaultConnection { } /// set a secret in the vault - pub async fn store_secret<'de, T: serde::Serialize>( + pub async fn store_secret( &self, val: T, rel_path: &str, @@ -306,7 +306,7 @@ impl VaultConnection { } /// set a secret in the vault for a different TEE - pub async fn store_secret_for_tee<'de, T: serde::Serialize>( + pub async fn store_secret_for_tee( &self, tee_name: &str, val: T, @@ -330,7 +330,7 @@ impl VaultConnection { } /// get a secret from the vault - pub async fn load_secret<'de, T: serde::de::DeserializeOwned>( + pub async fn load_secret( &self, rel_path: &str, ) -> Result, HttpResponseError> { @@ -338,7 +338,7 @@ impl VaultConnection { } /// get a secret from the vault for a specific TEE - pub async fn load_secret_for_tee<'de, T: serde::de::DeserializeOwned>( + pub async fn load_secret_for_tee( &self, tee_name: &str, rel_path: &str, diff --git a/crates/teepot/src/quote/attestation.rs b/crates/teepot/src/quote/attestation.rs index 4f00065..371545c 100644 --- a/crates/teepot/src/quote/attestation.rs +++ b/crates/teepot/src/quote/attestation.rs @@ -81,7 +81,7 @@ pub fn get_quote_and_collateral( } if tcblevel != TcbLevel::Ok - && allowed_tcb_levels.map_or(false, |levels| !levels.contains(tcblevel)) + && allowed_tcb_levels.is_some_and(|levels| !levels.contains(tcblevel)) { error!("Quote verification result: {}", tcblevel); bail!("Quote verification result: {}", tcblevel); diff --git a/flake.lock b/flake.lock index 643b08f..62f2b11 100644 --- a/flake.lock +++ b/flake.lock @@ -234,11 +234,11 @@ ] }, "locked": { - "lastModified": 1734661750, - "narHash": "sha256-BI58NBdimxu1lnpOrG9XxBz7Cwqy+qIf99zunWofX5w=", + "lastModified": 1743993291, + "narHash": "sha256-u8GHvduU1gCtoFXvTS/wGjH1ouv5S/GRGq6MAT+sG/k=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "7d3d910d5fd575e6e8c5600d83d54e5c47273bfe", + "rev": "0cb3c8979c65dc6a5812dfe67499a8c7b8b4325b", "type": "github" }, "original": { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index dbe555f..a237e46 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.83" +channel = "1.86" components = ["rustfmt", "clippy", "rust-src"]