diff --git a/Cargo.lock b/Cargo.lock index edc67dac..b9e8e9a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,12 +145,12 @@ checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", - "heck", - "indexmap 2.1.0", + "heck 0.4.1", + "indexmap 2.6.0", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.79", "syn-solidity", "tiny-keccak 2.0.2", ] @@ -211,6 +211,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" +[[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.3" @@ -266,15 +272,14 @@ dependencies = [ "base64 0.22.1", "chrono", "crypto", + "dcap-qvl", "flex-error", "hex", "lcp-types", - "pem", - "rustls 0.19.1", "serde", "serde_json", "sgx_types", - "webpki 0.21.4", + "tokio", ] [[package]] @@ -417,7 +422,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.32", + "syn 2.0.79", ] [[package]] @@ -600,9 +605,9 @@ checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -756,7 +761,7 @@ version = "3.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", @@ -853,9 +858,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "context" @@ -1152,6 +1157,36 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "dcap-qvl" +version = "0.1.3" +dependencies = [ + "anyhow", + "asn1_der", + "chrono", + "const-oid", + "der 0.7.9", + "hex", + "insta", + "parity-scale-codec", + "pem 3.0.4", + "reqwest", + "ring 0.16.20", + "rustls-webpki 0.102.8", + "scale-info", + "serde", + "serde_json", + "tokio", + "urlencoding", + "x509-cert", +] + [[package]] name = "deflate" version = "1.0.0" @@ -1173,15 +1208,28 @@ dependencies = [ [[package]] name = "der" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", + "der_derive", + "flagset", "pem-rfc7468", "zeroize", ] +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "derivation-path" version = "0.2.0" @@ -1433,6 +1481,18 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "env_logger" version = "0.9.0" @@ -1576,6 +1636,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flagset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" + [[package]] name = "flex-error" version = "0.4.4" @@ -1595,11 +1661,10 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "matches", "percent-encoding", ] @@ -1807,9 +1872,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1817,7 +1882,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.1", + "indexmap 2.6.0", "slab", "tokio", "tokio-util", @@ -1849,6 +1914,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hashlink" version = "0.8.3" @@ -1898,6 +1969,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1925,6 +2002,51 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" +[[package]] +name = "hickory-proto" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +dependencies = [ + "async-trait", + "cfg-if 1.0.0", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand 0.8.5", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +dependencies = [ + "cfg-if 1.0.0", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "hmac" version = "0.8.1" @@ -1975,6 +2097,17 @@ dependencies = [ "store", ] +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + [[package]] name = "http" version = "0.2.8" @@ -2005,9 +2138,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" [[package]] name = "httparse" -version = "1.7.1" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -2033,9 +2166,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2048,7 +2181,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.7", "tokio", "tower-service", "tracing", @@ -2094,15 +2227,16 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.2" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ + "futures-util", "http", "hyper", - "rustls 0.20.6", + "rustls 0.21.12", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", ] [[package]] @@ -2448,11 +2582,20 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.3" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -2504,12 +2647,24 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.0", +] + +[[package]] +name = "insta" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6593a41c7a73841868772495db7dc1e8ecab43bb5c0b6da2059246c4b506ab60" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "similar", ] [[package]] @@ -2566,6 +2721,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.7", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + [[package]] name = "ipnet" version = "2.7.1" @@ -2892,6 +3059,12 @@ dependencies = [ "cc", ] +[[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.3.8" @@ -2910,11 +3083,17 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" dependencies = [ - "cfg-if 1.0.0", + "linked-hash-map", ] [[package]] @@ -2936,6 +3115,12 @@ dependencies = [ "libc", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.1.0" @@ -2945,12 +3130,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "matchit" version = "0.5.0" @@ -3011,14 +3190,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.4" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.48.0", ] [[package]] @@ -3359,11 +3537,11 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a56f651b4dd45ae3ac3d260ced32eaf0620cddaae5f26c69b554a9016594726" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.79", ] [[package]] @@ -3380,9 +3558,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parity-scale-codec" -version = "3.4.0" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637935964ff85a605d114591d4d2c13c5d1ba2806dae97cea6bf180238a749ac" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -3394,11 +3572,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 1.3.0", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 1.0.108", @@ -3484,6 +3662,16 @@ dependencies = [ "base64 0.21.0", ] +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -3495,9 +3683,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" @@ -3537,7 +3725,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.6", + "der 0.7.9", "pkcs8", "spki", ] @@ -3548,7 +3736,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.6", + "der 0.7.9", "spki", ] @@ -3571,7 +3759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c64d9ba0963cdcea2e1b2230fbae2bab30eb25a174be395c41e764bfb65dd62" dependencies = [ "proc-macro2", - "syn 2.0.32", + "syn 2.0.79", ] [[package]] @@ -3602,7 +3790,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.18.1", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", ] [[package]] @@ -3631,9 +3828,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -3747,9 +3944,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.28" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3918,28 +4115,27 @@ dependencies = [ "base64 0.22.1", "chrono", "crypto", - "enclave-api", "flex-error", "hex", "httparse", "keymanager", "lcp-types", "log", + "pem 2.0.1", "rand 0.8.5", "rsa", "rustls 0.19.1", "sgx_types", "sha2 0.10.6", - "store", "webpki 0.21.4", "webpki-roots 0.17.0", ] [[package]] name = "reqwest" -version = "0.11.14" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.0", "bytes", @@ -3947,10 +4143,11 @@ dependencies = [ "futures-core", "futures-util", "h2", + "hickory-resolver", "http", "http-body", "hyper", - "hyper-rustls 0.23.2", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", @@ -3958,22 +4155,34 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.20.6", + "rustls 0.21.12", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", + "system-configuration", "tokio", - "tokio-rustls 0.23.4", + "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.22.6", + "webpki-roots 0.25.4", "winreg", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "retry" version = "2.0.0" @@ -4198,6 +4407,18 @@ dependencies = [ "webpki 0.22.4", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring 0.17.8", + "rustls-webpki 0.101.7", + "sct 0.7.0", +] + [[package]] name = "rustls-native-certs" version = "0.5.0" @@ -4231,6 +4452,33 @@ dependencies = [ "base64 0.13.0", ] +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "rustversion" version = "1.0.11" @@ -4323,6 +4571,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "001cf62ece89779fd16105b5f515ad0e5cedcd5440d3dd806bb067978e7c3608" dependencies = [ + "bitvec", "cfg-if 1.0.0", "derive_more", "parity-scale-codec", @@ -4494,9 +4743,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.185" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4531,13 +4780,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.185" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.79", ] [[package]] @@ -4553,12 +4802,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ - "indexmap 1.9.1", + "indexmap 2.6.0", "itoa", + "memchr", "ryu", "serde", ] @@ -4644,7 +4894,7 @@ dependencies = [ [[package]] name = "sgx_libc" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_types", ] @@ -4652,7 +4902,7 @@ dependencies = [ [[package]] name = "sgx_tcrypto" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_types", ] @@ -4660,7 +4910,7 @@ dependencies = [ [[package]] name = "sgx_trts" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_libc", "sgx_types", @@ -4669,7 +4919,7 @@ dependencies = [ [[package]] name = "sgx_tse" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_types", ] @@ -4677,7 +4927,7 @@ dependencies = [ [[package]] name = "sgx_tseal" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_tcrypto", "sgx_trts", @@ -4688,12 +4938,12 @@ dependencies = [ [[package]] name = "sgx_types" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" [[package]] name = "sgx_urts" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "libc", "sgx_types", @@ -4815,6 +5065,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "similar" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" + [[package]] name = "simple-error" version = "0.2.3" @@ -4850,14 +5106,24 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", ] +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -4872,12 +5138,12 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.6", + "der 0.7.9", ] [[package]] @@ -4920,7 +5186,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", @@ -4961,9 +5227,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.32" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -4979,14 +5245,14 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.79", ] [[package]] name = "sync_wrapper" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "synstructure" @@ -5000,6 +5266,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -5395,22 +5682,22 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.25.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78819ab9e79e14aefb149593f15c07239d0cea924cb44e1259e1bec643619e6" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.4.10", "tokio-macros", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -5425,13 +5712,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.108", + "syn 2.0.79", ] [[package]] @@ -5456,6 +5743,16 @@ dependencies = [ "webpki 0.22.4", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.9" @@ -5496,6 +5793,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + [[package]] name = "toml_edit" version = "0.18.1" @@ -5504,7 +5807,18 @@ checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ "indexmap 1.9.1", "nom8", - "toml_datetime", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime 0.6.8", + "winnow", ] [[package]] @@ -5780,9 +6094,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -5792,9 +6106,9 @@ checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] @@ -5831,16 +6145,21 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.2.2" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna", - "matches", + "idna 0.5.0", "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" @@ -6044,12 +6363,15 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.6" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki 0.22.4", -] +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -6321,13 +6643,23 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] [[package]] @@ -6339,6 +6671,17 @@ dependencies = [ "tap", ] +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid", + "der 0.7.9", + "spki", +] + [[package]] name = "zerocopy" version = "0.7.32" @@ -6356,7 +6699,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.79", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index e1676c2d..14c3cde2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ members = [ "modules/tendermint-lc", "modules/mock-lc", "modules/service", + "modules/dcap-qvl", "proto", "tests/integration", "tools/nodes-runner", diff --git a/Makefile b/Makefile index 1241c5e8..a6278a9e 100644 --- a/Makefile +++ b/Makefile @@ -216,7 +216,7 @@ TEST_ENCLAVE_CARGO_TEST=$(TEST_ENCLAVE_CARGO) test $(CARGO_TARGET) .PHONY: test test: - @cargo test $(CARGO_TARGET) --lib --workspace --exclude integration-test + @cargo test $(CARGO_TARGET) --workspace --exclude integration-test @$(TEST_ENCLAVE_CARGO_TEST) -p ecall-handler @$(TEST_ENCLAVE_CARGO_TEST) -p enclave-environment @$(TEST_ENCLAVE_CARGO_TEST) -p host-api diff --git a/app/src/commands/attestation.rs b/app/src/commands/attestation.rs index 12a4a9da..36984328 100644 --- a/app/src/commands/attestation.rs +++ b/app/src/commands/attestation.rs @@ -2,13 +2,12 @@ use crate::{ enclave::EnclaveLoader, opts::{EnclaveOpts, Opts}, }; -use anyhow::{bail, Result}; +use anyhow::{anyhow, bail, Result}; use clap::Parser; use crypto::Address; use enclave_api::{Enclave, EnclaveCommandAPI, EnclaveProtoAPI}; use host::store::transaction::CommitStore; -use log::info; -use remote_attestation::{ias, IASMode}; +use remote_attestation::{dcap, ias, IASMode}; /// `attestation` subcommand #[allow(clippy::upper_case_acronyms)] @@ -16,8 +15,10 @@ use remote_attestation::{ias, IASMode}; pub enum AttestationCmd { #[clap(display_order = 1, about = "Remote Attestation with IAS")] IAS(IASRemoteAttestation), + #[clap(display_order = 2, about = "Remote Attestation with DCAP")] + DCAP(DCAPRemoteAttestation), #[cfg(feature = "sgx-sw")] - #[clap(display_order = 2, about = "Simulate Remote Attestation")] + #[clap(display_order = 3, about = "Simulate Remote Attestation")] Simulate(SimulateRemoteAttestation), } @@ -29,26 +30,23 @@ impl AttestationCmd { L: EnclaveLoader, { let home = opts.get_home(); + if !home.exists() { + bail!("home directory doesn't exist at {:?}", home); + } match self { - AttestationCmd::IAS(cmd) => { - if !home.exists() { - bail!("home directory doesn't exist at {:?}", home); - } - run_ias_remote_attestation( - enclave_loader.load(opts, cmd.enclave.path.as_ref(), cmd.enclave.is_debug())?, - cmd, - ) - } + AttestationCmd::IAS(cmd) => run_ias_remote_attestation( + enclave_loader.load(opts, cmd.enclave.path.as_ref(), cmd.enclave.is_debug())?, + cmd, + ), + AttestationCmd::DCAP(cmd) => run_dcap_remote_attestation( + enclave_loader.load(opts, cmd.enclave.path.as_ref(), cmd.enclave.is_debug())?, + cmd, + ), #[cfg(feature = "sgx-sw")] - AttestationCmd::Simulate(cmd) => { - if !home.exists() { - bail!("home directory doesn't exist at {:?}", home); - } - run_simulate_remote_attestation( - enclave_loader.load(opts, cmd.enclave.path.as_ref(), cmd.enclave.is_debug())?, - cmd, - ) - } + AttestationCmd::Simulate(cmd) => run_simulate_remote_attestation( + enclave_loader.load(opts, cmd.enclave.path.as_ref(), cmd.enclave.is_debug())?, + cmd, + ), } } } @@ -76,8 +74,8 @@ fn run_ias_remote_attestation, S: CommitStore>( let spid = std::env::var("SPID")?; let ias_key = std::env::var("IAS_KEY")?; let target_enclave_key = Address::from_hex_string(&cmd.enclave_key)?; - match ias::run_ias_ra( - &enclave, + ias::run_ias_ra( + enclave.get_key_manager(), target_enclave_key, if cmd.is_dev { IASMode::Development @@ -86,20 +84,9 @@ fn run_ias_remote_attestation, S: CommitStore>( }, spid, ias_key, - ) { - Ok(res) => { - info!("AVR: {:?}", res.avr); - info!( - "report_data: {}", - res.get_avr()?.parse_quote()?.report_data() - ); - enclave - .get_key_manager() - .save_avr(target_enclave_key, res)?; - Ok(()) - } - Err(e) => bail!("failed to perform IAS Remote Attestation: {}", e), - } + ) + .map_err(|e| anyhow!("failed to perform IAS Remote Attestation: {}", e))?; + Ok(()) } #[cfg(feature = "sgx-sw")] @@ -211,25 +198,38 @@ fn run_simulate_remote_attestation, S: CommitStore>( } let target_enclave_key = Address::from_hex_string(&cmd.enclave_key)?; - match remote_attestation::ias_simulation::run_ias_ra_simulation( - &enclave, + remote_attestation::ias_simulation::run_ias_ra_simulation( + enclave.get_key_manager(), target_enclave_key, cmd.advisory_ids.clone(), cmd.isv_enclave_quote_status.clone(), signing_key, signing_cert, - ) { - Ok(res) => { - info!("AVR: {:?}", res.avr); - info!( - "report_data: {}", - res.get_avr()?.parse_quote()?.report_data() - ); - enclave - .get_key_manager() - .save_avr(target_enclave_key, res)?; - Ok(()) - } - Err(e) => bail!("failed to simulate Remote Attestation: {}", e), - } + ) + .map_err(|e| anyhow!("failed to simulate Remote Attestation: {}", e))?; + Ok(()) +} + +#[derive(Clone, Debug, Parser, PartialEq)] +pub struct DCAPRemoteAttestation { + /// Options for enclave + #[clap(flatten)] + pub enclave: EnclaveOpts, + /// An enclave key attested by Remote Attestation + #[clap( + long = "enclave_key", + help = "An enclave key attested by Remote Attestation" + )] + pub enclave_key: String, +} + +fn run_dcap_remote_attestation, S: CommitStore>( + enclave: E, + cmd: &DCAPRemoteAttestation, +) -> Result<()> { + dcap::run_dcap_ra( + enclave.get_key_manager(), + Address::from_hex_string(&cmd.enclave_key)?, + )?; + Ok(()) } diff --git a/app/src/commands/enclave.rs b/app/src/commands/enclave.rs index 90990555..63245aa3 100644 --- a/app/src/commands/enclave.rs +++ b/app/src/commands/enclave.rs @@ -67,7 +67,8 @@ pub struct GenerateKey { hain" )] pub operator: Option, - // TODO add target qe option + #[clap(long = "target_qe3", help = "Create a report for QE3 instead of QE")] + pub target_qe3: bool, } impl GenerateKey { @@ -84,7 +85,7 @@ fn run_generate_key, S: CommitStore>( enclave: E, input: &GenerateKey, ) -> Result<()> { - let (target_info, _) = remote_attestation::init_quote()?; + let (target_info, _) = remote_attestation::init_quote(input.target_qe3)?; let res = enclave .generate_enclave_key(GenerateEnclaveKeyInput { target_info, @@ -120,9 +121,9 @@ fn run_list_keys, S: CommitStore>( }; let mut list_json = Vec::new(); for eki in list { - match eki.signed_avr { - Some(signed_avr) => { - let avr = signed_avr.get_avr()?; + match eki.ias_report { + Some(ias_report) => { + let avr = ias_report.get_avr()?; let report_data = avr.parse_quote()?.report_data(); list_json.push(json! {{ "address": eki.address.to_hex_string(), diff --git a/enclave/Cargo.lock b/enclave/Cargo.lock index 6f9a9223..687a2e66 100644 --- a/enclave/Cargo.lock +++ b/enclave/Cargo.lock @@ -39,7 +39,7 @@ dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.1.0", + "indexmap 2.6.0", "proc-macro-error", "proc-macro2", "quote", @@ -77,6 +77,12 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "asn1_der" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" + [[package]] name = "attestation-report" version = "0.1.0" @@ -84,10 +90,10 @@ dependencies = [ "base64 0.22.1", "chrono", "crypto", + "dcap-qvl", "flex-error", "hex", "lcp-types", - "pem", "serde", "serde_json", "sgx_types", @@ -107,15 +113,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "base64" -version = "0.22.1" +name = "base64ct" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bincode" @@ -195,6 +201,12 @@ dependencies = [ "syn 1.0.103", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -203,9 +215,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -216,6 +228,15 @@ dependencies = [ "serde", ] +[[package]] +name = "cc" +version = "1.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +dependencies = [ + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -259,6 +280,12 @@ dependencies = [ "serde", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "context" version = "0.1.0" @@ -373,6 +400,49 @@ dependencies = [ "syn 2.0.32", ] +[[package]] +name = "dcap-qvl" +version = "0.1.3" +dependencies = [ + "anyhow", + "asn1_der", + "chrono", + "const-oid", + "der", + "hex", + "parity-scale-codec", + "pem", + "ring 0.16.20", + "rustls-webpki", + "scale-info", + "serde", + "serde_json", + "x509-cert", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "der_derive", + "flagset", + "zeroize", +] + +[[package]] +name = "der_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -555,6 +625,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "flagset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" + [[package]] name = "flex-error" version = "0.4.4" @@ -641,6 +717,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -658,9 +745,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -813,12 +900,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.15.0", ] [[package]] @@ -836,6 +923,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "keccak" version = "0.1.3" @@ -872,9 +968,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -946,12 +1042,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" @@ -1011,9 +1104,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "parity-scale-codec" -version = "3.4.0" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637935964ff85a605d114591d4d2c13c5d1ba2806dae97cea6bf180238a749ac" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "byte-slice-cast", @@ -1023,11 +1116,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 1.3.0", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", "syn 1.0.103", @@ -1041,11 +1134,11 @@ checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "pem" -version = "2.0.1" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", ] [[package]] @@ -1093,7 +1186,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.18.1", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.22", ] [[package]] @@ -1122,9 +1224,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -1219,6 +1321,36 @@ dependencies = [ "rand_core", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys", +] + [[package]] name = "ripemd" version = "0.1.3" @@ -1257,6 +1389,23 @@ dependencies = [ "semver", ] +[[package]] +name = "rustls-pki-types" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring 0.17.8", + "rustls-pki-types", + "untrusted 0.9.0", +] + [[package]] name = "ryu" version = "1.0.11" @@ -1380,9 +1529,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" dependencies = [ "itoa", "ryu", @@ -1430,12 +1579,12 @@ dependencies = [ [[package]] name = "sgx_alloc" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" [[package]] name = "sgx_libc" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_types", ] @@ -1443,7 +1592,7 @@ dependencies = [ [[package]] name = "sgx_tcrypto" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_types", ] @@ -1451,7 +1600,7 @@ dependencies = [ [[package]] name = "sgx_trts" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_libc", "sgx_types", @@ -1460,7 +1609,7 @@ dependencies = [ [[package]] name = "sgx_tse" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_types", ] @@ -1468,7 +1617,7 @@ dependencies = [ [[package]] name = "sgx_tseal" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" dependencies = [ "sgx_tcrypto", "sgx_trts", @@ -1479,7 +1628,7 @@ dependencies = [ [[package]] name = "sgx_types" version = "1.1.6" -source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#c3d82372dff81e5bafb07f71bc8ad532d06b504e" +source = "git+https://github.com/apache/incubator-teaclave-sgx-sdk?rev=v1.1.6#v1.1.6" [[package]] name = "sha2" @@ -1513,12 +1662,40 @@ dependencies = [ "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -1740,6 +1917,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + [[package]] name = "toml_edit" version = "0.18.1" @@ -1748,7 +1931,18 @@ checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" dependencies = [ "indexmap 1.9.2", "nom8", - "toml_datetime", + "toml_datetime 0.5.1", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.6.0", + "toml_datetime 0.6.8", + "winnow", ] [[package]] @@ -1804,6 +1998,18 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "valuable" version = "0.1.0" @@ -1816,6 +2022,192 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "x509-cert" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94" +dependencies = [ + "const-oid", + "der", + "spki", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/modules/attestation-report/Cargo.toml b/modules/attestation-report/Cargo.toml index 9d02997d..324f8422 100644 --- a/modules/attestation-report/Cargo.toml +++ b/modules/attestation-report/Cargo.toml @@ -13,16 +13,16 @@ lcp-types = { path = "../types", default-features = false } flex-error = { version = "0.4.4", default-features = false } hex = { version = "0.4", default-features = false, features = ["alloc"] } base64 = { version = "0.22.1", default-features = false, features = ["alloc"] } +dcap-qvl = { path = "../dcap-qvl", default-features = false } -pem = { version = "2.0", default-features = false } -rustls = { version = "0.19", optional = true } -webpki = { version = "0.21", optional = true } +[dev-dependencies] +tokio = { version = "1.0", default-features = false, features = ["macros"] } [features] default = ["std"] std = [ - "rustls", - "webpki", "flex-error/std", - "serde_json/preserve_order" + "lcp-types/std", + "serde_json/preserve_order", + "dcap-qvl/report", ] diff --git a/modules/attestation-report/src/dcap.rs b/modules/attestation-report/src/dcap.rs new file mode 100644 index 00000000..32076769 --- /dev/null +++ b/modules/attestation-report/src/dcap.rs @@ -0,0 +1,211 @@ +use crate::prelude::*; +use crate::Error; +use dcap_qvl::quote::Quote; +use lcp_types::Time; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct DCAPQuote { + pub quote: Vec, + pub attested_at: Time, +} + +impl DCAPQuote { + pub fn new(quote: Vec, attested_at: Time) -> Self { + let this = DCAPQuote { quote, attested_at }; + let _ = this.get_quote(); // Ensure the quote is valid + this + } + + pub fn to_json(&self) -> Result { + serde_json::to_string(self).map_err(Error::serde_json) + } + + pub fn get_quote(&self) -> Quote { + Quote::parse(&self.quote).expect("Failed to parse DCAP quote") + } +} + +#[cfg(test)] +mod tests { + use super::*; + use core::time::Duration; + use dcap_qvl::{collateral::get_collateral, verify::verify, QuoteCollateralV3}; + + #[test] + fn test_dcap_quote() { + let quote = get_test_quote(); + let q = DCAPQuote::new(quote, Time::now()); + let quote = q.get_quote(); + assert_eq!(quote.header.version, 3); + } + + #[tokio::test] + async fn test_get_collateral() { + let quote = get_test_quote(); + let res = get_collateral( + "https://api.trustedservices.intel.com/sgx/certification/v4/", + "e, + Duration::from_secs(30), + ) + .await; + assert!(res.is_ok()); + } + + #[tokio::test] + async fn test_verify_quote() { + let quote = get_test_quote(); + let collateral = get_test_collateral(); + let res = verify("e, &collateral, 1728282833).expect("Failed to verify quote"); + assert_eq!(res.status, "SWHardeningNeeded"); + } + + fn get_test_quote() -> Vec { + hex::decode("03000200000000000a000f00939a7233f79c4ca9940a0db3957f0607b5fe5d7f613d2d40b066b320879bd14d0000000015150b07ff800e000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000700000000000000ea4047329d65711f63993b9397245d44bafaee5e7d56a4906e7738f7cf697d7d000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000130fd34a0e3139da00ce0a9b845cb3ccf039b1bf700000000000000000000000000000000000000000000000000000000000000000000000000000000000000441000004bc221614d15399401379d302d1b8eae3a287957eac2497360c07d2fb3b237b9a2372e52dcdbe26560b1060274ebe0fefba61f1694b780b9c6e5dedc68e0e3624b1526520dd11db5efc9504fa42d048e37ba38c90c8873e7c62f72e86794797bcf8586b9e5c10d0866a95331548da898ae0adf78e428128324151ee558cfc71215150b07ff800e00000000000000000000000000000000000000000000000000000000000000000000000000000000001500000000000000070000000000000096b347a64e5a045e27369c26e6dcda51fd7c850e9b3a3a79e718f43261dee1e400000000000000000000000000000000000000000000000000000000000000008c4f5775d796503e96137f77c68a829a0056ac8ded70140b081b094490c57bff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017b0dc79c3dc5ff39b3f67346eef41f1ecd63e0a5259a9102eaace1f0aca06ec0000000000000000000000000000000000000000000000000000000000000000e6516d69dd50710c9d1eed1281bd9bb9bac590c23712a15d5cd648032d0524bc467ca02deb6a1bfb638e0df697a388419b18ac2d96b0cfca7dc9a5e6491e4eac2000000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f0500dc0d00002d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949456a6a4343424453674177494241674956414a34674a3835554b6b7a613873504a4847676e4f4b6d5451426e754d416f4743437147534d343942414d430a4d484578497a416842674e5642414d4d476b6c756447567349464e48574342515130736755484a765932567a6332397949454e424d526f77474159445651514b0a4442464a626e526c6243424462334a7762334a6864476c76626a45554d424947413155454277774c553246756447456751327868636d4578437a414a42674e560a4241674d416b4e424d517377435159445651514745774a56557a4165467730794e4441354d5467784d4451354d6a56614677307a4d5441354d5467784d4451350a4d6a56614d484178496a416742674e5642414d4d47556c756447567349464e4857434251513073675132567964476c6d61574e6864475578476a415942674e560a42416f4d45556c756447567349454e76636e4276636d4630615739754d5251774567594456515148444174545957353059534244624746795954454c4d416b470a413155454341774351304578437a414a42674e5642415954416c56544d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741450a516a537877644d662b2b3578645553717478343769335952633970504a475434304642774e306e5335557a43314233524b63544875514c3135796b357a4c766c0a5535707a7563552f2b6d674a4e6f55774b6e784942364f434171677767674b6b4d42384741315564497751594d426141464e446f71747031312f6b75535265590a504873555a644456386c6c4e4d477747413155644877526c4d474d77596142666f463247573268306448427a4f693876595842704c6e527964584e305a57527a0a5a584a3261574e6c63793570626e526c6243356a62323076633264344c324e6c636e52705a6d6c6a5958527062323476646a517663474e7259334a7350324e680a5058427962324e6c63334e7663695a6c626d4e765a476c755a7a316b5a584977485159445652304f42425945464f7632356e4f67634c754f693644424b3037470a4d4f5161315a53494d41344741315564447745422f775145417749477744414d42674e5648524d4241663845416a41414d4949423141594a4b6f5a496876684e0a415130424249494278544343416345774867594b4b6f5a496876684e41513042415151514459697469663748386e4277566732482b38504f476a4343415751470a43697147534962345451454e41514977676746554d42414743797147534962345451454e41514942416745564d42414743797147534962345451454e415149430a416745564d42414743797147534962345451454e41514944416745434d42414743797147534962345451454e41514945416745454d42414743797147534962340a5451454e41514946416745424d42454743797147534962345451454e41514947416749416744415142677371686b69472b4530424451454342774942446a41510a42677371686b69472b45304244514543434149424144415142677371686b69472b45304244514543435149424144415142677371686b69472b453042445145430a436749424144415142677371686b69472b45304244514543437749424144415142677371686b69472b45304244514543444149424144415142677371686b69470a2b45304244514543445149424144415142677371686b69472b45304244514543446749424144415142677371686b69472b4530424451454344774942414441510a42677371686b69472b45304244514543454149424144415142677371686b69472b45304244514543455149424454416642677371686b69472b453042445145430a4567515146525543424147414467414141414141414141414144415142676f71686b69472b45304244514544424149414144415542676f71686b69472b4530420a44514545424159416b473756414141774477594b4b6f5a496876684e4151304242516f424144414b42676771686b6a4f5051514441674e4941444246416941450a4d50754f5455774e32794a7a6e30635362614a5654314e576d6e786d374a334d366a67626a424c523341496841496e354d5442363133744c6a33386a4b7432330a6d7a545743764b6735324d7941594c5578696632396a506a0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949436d444343416a36674177494241674956414e446f71747031312f6b7553526559504873555a644456386c6c4e4d416f4743437147534d343942414d430a4d476778476a415942674e5642414d4d45556c756447567349464e48574342536232393049454e424d526f77474159445651514b4442464a626e526c624342440a62334a7762334a6864476c76626a45554d424947413155454277774c553246756447456751327868636d4578437a414a42674e564241674d416b4e424d5173770a435159445651514745774a56557a4165467730784f4441314d6a45784d4455774d5442614677307a4d7a41314d6a45784d4455774d5442614d484578497a41680a42674e5642414d4d476b6c756447567349464e48574342515130736755484a765932567a6332397949454e424d526f77474159445651514b4442464a626e526c0a6243424462334a7762334a6864476c76626a45554d424947413155454277774c553246756447456751327868636d4578437a414a42674e564241674d416b4e420a4d517377435159445651514745774a56557a425a4d424d4742797147534d34394167454743437147534d34394177454841304941424c39712b4e4d7032494f670a74646c31626b2f75575a352b5447516d38614369387a373866732b664b435133642b75447a586e56544154325a68444369667949754a77764e33774e427039690a484253534d4a4d4a72424f6a6762737767626777487759445652306a42426777466f4155496d554d316c71644e496e7a6737535655723951477a6b6e427177770a556759445652306642457377535442486f45576751345a426148523063484d364c79396a5a584a3061575a70593246305a584d7564484a316333526c5a484e6c0a636e5a705932567a4c6d6c75644756734c6d4e766253394a626e526c62464e4857464a76623352445153356b5a584977485159445652304f42425945464e446f0a71747031312f6b7553526559504873555a644456386c6c4e4d41344741315564447745422f77514541774942426a415342674e5648524d4241663845434441470a4151482f416745414d416f4743437147534d343942414d43413067414d4555434951434a6754627456714f795a316d336a716941584d365159613672357357530a34792f4737793875494a4778647749675271507642534b7a7a516167424c517135733541373070646f6961524a387a2f3075447a344e675639316b3d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949436a7a4343416a53674177494241674955496d554d316c71644e496e7a6737535655723951477a6b6e42717777436759494b6f5a497a6a3045417749770a614445614d4267474131554541777752535735305a5777675530645949464a766233516751304578476a415942674e5642416f4d45556c756447567349454e760a636e4276636d4630615739754d5251774567594456515148444174545957353059534244624746795954454c4d416b47413155454341774351304578437a414a0a42674e5642415954416c56544d423458445445344d4455794d5445774e4455784d466f58445451354d54497a4d54497a4e546b314f566f77614445614d4267470a4131554541777752535735305a5777675530645949464a766233516751304578476a415942674e5642416f4d45556c756447567349454e76636e4276636d46300a615739754d5251774567594456515148444174545957353059534244624746795954454c4d416b47413155454341774351304578437a414a42674e56424159540a416c56544d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a3044415163445167414543366e45774d4449595a4f6a2f69505773437a61454b69370a314f694f534c52466857476a626e42564a66566e6b59347533496a6b4459594c304d784f346d717379596a6c42616c54565978465032734a424b357a6c4b4f420a757a43427544416642674e5648534d4547444157674251695a517a575770303069664f44744a5653763141624f5363477244425342674e5648523845537a424a0a4d45656752614244686b466f64485277637a6f764c324e6c636e52705a6d6c6a5958526c63793530636e567a6447566b63325679646d6c6a5a584d75615735300a5a577775593239744c306c756447567355306459556d397664454e424c6d526c636a416442674e564851344546675155496d554d316c71644e496e7a673753560a55723951477a6b6e4271777744675944565230504151482f42415144416745474d42494741315564457745422f7751494d4159424166384341514577436759490a4b6f5a497a6a3045417749445351417752674968414f572f35516b522b533943695344634e6f6f774c7550524c735747662f59693747535839344267775477670a41694541344a306c72486f4d732b586f356f2f7358364f39515778485241765a55474f6452513763767152586171493d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a00").unwrap() + } + + fn get_test_collateral() -> QuoteCollateralV3 { + serde_json::from_value(serde_json::json!( + { + "pck_crl_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICmDCCAj6gAwIBAgIVANDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHExIzAh\nBgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQKDBFJbnRl\nbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNB\nMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL9q+NMp2IOg\ntdl1bk/uWZ5+TGQm8aCi8z78fs+fKCQ3d+uDzXnVTAT2ZhDCifyIuJwvN3wNBp9i\nHBSSMJMJrBOjgbswgbgwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqww\nUgYDVR0fBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNl\ncnZpY2VzLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFNDo\nqtp11/kuSReYPHsUZdDV8llNMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEAMAoGCCqGSM49BAMCA0gAMEUCIQCJgTbtVqOyZ1m3jqiAXM6QYa6r5sWS\n4y/G7y8uIJGxdwIgRqPvBSKzzQagBLQq5s5A70pdoiaRJ8z/0uDz4NgV91k=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", + "pck_crl": "-----BEGIN X509 CRL-----\nMIIBKjCB0QIBATAKBggqhkjOPQQDAjBxMSMwIQYDVQQDDBpJbnRlbCBTR1ggUENL\nIFByb2Nlc3NvciBDQTEaMBgGA1UECgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNV\nBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMXDTI0MTAw\nNzA2MzIwM1oXDTI0MTEwNjA2MzIwM1qgLzAtMAoGA1UdFAQDAgEBMB8GA1UdIwQY\nMBaAFNDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMCA0gAMEUCIQCWbrP8\npfz+VQuy3jAh2xmlGXf2ge0fCZ52brj3yutKKwIgUvkWacySv202hND5/dj4ndO6\ndu33EqMZ6GZ2Zubc0fg=\n-----END X509 CRL-----\n", + "tcb_info_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj\nftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", + "tcb_info": "{\"id\":\"SGX\",\"version\":3,\"issueDate\":\"2024-10-07T06:24:15Z\",\"nextUpdate\":\"2024-11-06T06:24:15Z\",\"fmspc\":\"00906ED50000\",\"pceId\":\"0000\",\"tcbType\":0,\"tcbEvaluationDataNumber\":17,\"tcbLevels\":[{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":21},{\"svn\":21},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":14},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"SWHardeningNeeded\",\"advisoryIDs\":[\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":21},{\"svn\":21},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"ConfigurationAndSWHardeningNeeded\",\"advisoryIDs\":[\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":20},{\"svn\":20},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":14},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00828\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":20},{\"svn\":20},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2023-02-15T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":19},{\"svn\":19},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":6},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":19},{\"svn\":19},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":13},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00161\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":17},{\"svn\":17},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":6},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00161\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":17},{\"svn\":17},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":6},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00161\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":17},{\"svn\":17},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":11},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00161\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":17},{\"svn\":17},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00477\",\"INTEL-SA-00161\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":15},{\"svn\":15},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":6},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2020-06-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00161\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":15},{\"svn\":15},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2020-06-10T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00161\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":14},{\"svn\":14},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":6},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2019-12-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00161\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":14},{\"svn\":14},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":10},\"tcbDate\":\"2019-12-11T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00161\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":13},{\"svn\":13},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":2},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":9},\"tcbDate\":\"2019-11-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00161\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00219\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":13},{\"svn\":13},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":9},\"tcbDate\":\"2019-11-13T00:00:00Z\",\"tcbStatus\":\"OutOfDateConfigurationNeeded\",\"advisoryIDs\":[\"INTEL-SA-00219\",\"INTEL-SA-00161\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":2},{\"svn\":2},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":7},\"tcbDate\":\"2019-05-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00220\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00219\",\"INTEL-SA-00161\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":1},{\"svn\":1},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":7},\"tcbDate\":\"2019-01-09T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00233\",\"INTEL-SA-00220\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00219\",\"INTEL-SA-00161\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]},{\"tcb\":{\"sgxtcbcomponents\":[{\"svn\":1},{\"svn\":1},{\"svn\":2},{\"svn\":4},{\"svn\":1},{\"svn\":128},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0},{\"svn\":0}],\"pcesvn\":6},\"tcbDate\":\"2018-08-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00203\",\"INTEL-SA-00233\",\"INTEL-SA-00220\",\"INTEL-SA-00270\",\"INTEL-SA-00293\",\"INTEL-SA-00219\",\"INTEL-SA-00161\",\"INTEL-SA-00320\",\"INTEL-SA-00329\",\"INTEL-SA-00381\",\"INTEL-SA-00389\",\"INTEL-SA-00477\",\"INTEL-SA-00614\",\"INTEL-SA-00617\",\"INTEL-SA-00289\",\"INTEL-SA-00828\",\"INTEL-SA-00334\",\"INTEL-SA-00615\"]}]}", + "tcb_info_signature": [ + 109, + 184, + 134, + 155, + 159, + 73, + 222, + 149, + 48, + 216, + 221, + 236, + 127, + 122, + 219, + 95, + 32, + 99, + 191, + 191, + 6, + 100, + 233, + 239, + 188, + 233, + 248, + 235, + 111, + 42, + 12, + 72, + 7, + 104, + 254, + 46, + 74, + 145, + 79, + 136, + 71, + 207, + 251, + 199, + 126, + 139, + 37, + 30, + 50, + 171, + 27, + 57, + 9, + 246, + 179, + 178, + 65, + 91, + 15, + 235, + 181, + 63, + 137, + 138 + ], + "qe_identity_issuer_chain": "-----BEGIN CERTIFICATE-----\nMIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG\nA1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw\nb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD\nVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv\nP+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju\nypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f\nBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz\nLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK\nQEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG\nSM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj\nftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n", + "qe_identity": "{\"id\":\"QE\",\"version\":2,\"issueDate\":\"2024-10-07T06:33:17Z\",\"nextUpdate\":\"2024-11-06T06:33:17Z\",\"tcbEvaluationDataNumber\":17,\"miscselect\":\"00000000\",\"miscselectMask\":\"FFFFFFFF\",\"attributes\":\"11000000000000000000000000000000\",\"attributesMask\":\"FBFFFFFFFFFFFFFF0000000000000000\",\"mrsigner\":\"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF\",\"isvprodid\":1,\"tcbLevels\":[{\"tcb\":{\"isvsvn\":8},\"tcbDate\":\"2024-03-13T00:00:00Z\",\"tcbStatus\":\"UpToDate\"},{\"tcb\":{\"isvsvn\":6},\"tcbDate\":\"2021-11-10T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":5},\"tcbDate\":\"2020-11-11T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":4},\"tcbDate\":\"2019-11-13T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":2},\"tcbDate\":\"2019-05-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00219\",\"INTEL-SA-00293\",\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]},{\"tcb\":{\"isvsvn\":1},\"tcbDate\":\"2018-08-15T00:00:00Z\",\"tcbStatus\":\"OutOfDate\",\"advisoryIDs\":[\"INTEL-SA-00202\",\"INTEL-SA-00219\",\"INTEL-SA-00293\",\"INTEL-SA-00334\",\"INTEL-SA-00477\",\"INTEL-SA-00615\"]}]}", + "qe_identity_signature": [ + 35, + 231, + 176, + 146, + 25, + 226, + 90, + 206, + 89, + 56, + 40, + 208, + 103, + 239, + 21, + 212, + 108, + 8, + 223, + 150, + 157, + 23, + 49, + 36, + 153, + 94, + 193, + 11, + 11, + 190, + 0, + 56, + 167, + 111, + 10, + 95, + 58, + 45, + 106, + 35, + 153, + 104, + 210, + 242, + 76, + 46, + 166, + 50, + 105, + 114, + 106, + 242, + 131, + 227, + 131, + 28, + 164, + 52, + 103, + 239, + 197, + 109, + 49, + 9 + ] + } + )).unwrap() + } +} diff --git a/modules/attestation-report/src/errors.rs b/modules/attestation-report/src/errors.rs index 3c58c98b..090c5fb1 100644 --- a/modules/attestation-report/src/errors.rs +++ b/modules/attestation-report/src/errors.rs @@ -40,14 +40,6 @@ define_error! { format_args!("Mrenclave mismatch error: expected={} actual={}", e.expected, e.actual) }, - WebPki - { - descr: String - } - |e| { - format_args!("WebPKI error: descr={}", e.descr) - }, - SerdeJson [TraceError] |_| { "serde_json error" }, diff --git a/modules/attestation-report/src/ias.rs b/modules/attestation-report/src/ias.rs new file mode 100644 index 00000000..5fac63e1 --- /dev/null +++ b/modules/attestation-report/src/ias.rs @@ -0,0 +1,133 @@ +use crate::prelude::*; +use crate::{errors::Error, Quote}; +use base64::{engine::general_purpose::STANDARD as Base64Std, Engine}; +use chrono::prelude::DateTime; +use core::fmt::Debug; +use lcp_types::Time; +use serde::{Deserialize, Serialize}; +use sgx_types::sgx_quote_t; + +/// IASSignedReport represents the signed attestation verification report from Intel +#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct IASSignedReport { + /// A report generated by the Intel Attestation Service + pub avr: String, + /// Signature of the report + #[serde(with = "serde_base64")] + pub signature: Vec, + /// Certificate matching the signing key of the signature + #[serde(with = "serde_base64")] + pub signing_cert: Vec, +} + +impl IASSignedReport { + pub fn get_avr(&self) -> Result { + serde_json::from_slice(self.avr.as_ref()).map_err(Error::serde_json) + } + + pub fn to_json(&self) -> Result { + serde_json::to_string(self).map_err(Error::serde_json) + } + + pub fn from_json(json: &str) -> Result { + serde_json::from_str(json).map_err(Error::serde_json) + } +} + +// IASAttestationVerificationReport represents Intel's Attestation Verification Report +// https://api.trustedservices.intel.com/documents/sgx-attestation-api-spec.pdf +#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)] +pub struct IASAttestationVerificationReport { + pub id: String, + pub timestamp: String, + pub version: i64, + #[serde(alias = "isvEnclaveQuoteStatus")] + pub isv_enclave_quote_status: String, + #[serde(alias = "isvEnclaveQuoteBody")] + pub isv_enclave_quote_body: String, + #[serde(alias = "revocationReason")] + pub revocation_reason: Option, + #[serde(alias = "pseManifestStatus")] + pub pse_manifest_status: Option, + #[serde(alias = "pseManifestHash")] + pub pse_manifest_hash: Option, + #[serde(alias = "platformInfoBlob")] + pub platform_info_blob: Option, + pub nonce: Option, + #[serde(alias = "epidPseudonym")] + pub epid_pseudonym: Option>, + #[serde(alias = "advisoryURL")] + pub advisory_url: String, + #[serde(alias = "advisoryIDs")] + pub advisory_ids: Vec, +} + +impl IASAttestationVerificationReport { + pub fn attestation_time(&self) -> Result { + let time_fixed = self.timestamp.clone() + "+0000"; + let dt = DateTime::parse_from_str(&time_fixed, "%Y-%m-%dT%H:%M:%S%.f%z")?; + Ok(Time::from_unix_timestamp( + dt.timestamp(), + dt.timestamp_subsec_nanos(), + )?) + } + + pub fn parse_quote(&self) -> Result { + if self.version != 4 { + return Err(Error::unexpected_attestation_report_version( + 4, + self.version, + )); + } + + let quote = Base64Std + .decode(&self.isv_enclave_quote_body) + .map_err(Error::base64)?; + let sgx_quote: sgx_quote_t = unsafe { core::ptr::read(quote.as_ptr() as *const _) }; + Ok(Quote { + raw: sgx_quote, + status: self.isv_enclave_quote_status.clone(), + attestation_time: self.attestation_time()?, + }) + } + + #[cfg(feature = "std")] + pub fn to_canonical_json(&self) -> Result { + if self.version != 4 { + return Err(Error::unexpected_attestation_report_version( + 4, + self.version, + )); + } + Ok(format!( + "{}", + serde_json::json!({ + "id": self.id, + "timestamp": self.timestamp, + "version": self.version, + "advisoryURL": self.advisory_url, + "advisoryIDs": self.advisory_ids, + "isvEnclaveQuoteStatus": self.isv_enclave_quote_status, + "platformInfoBlob": self.platform_info_blob, + "isvEnclaveQuoteBody": self.isv_enclave_quote_body + }) + )) + } +} + +mod serde_base64 { + use super::*; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + pub fn serialize(v: &Vec, s: S) -> Result { + let base64 = Base64Std.encode(v); + String::serialize(&base64, s) + } + + pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> { + let base64 = String::deserialize(d)?; + Base64Std + .decode(base64.as_bytes()) + .map_err(serde::de::Error::custom) + } +} diff --git a/modules/attestation-report/src/lib.rs b/modules/attestation-report/src/lib.rs index 89217b26..382f4c55 100644 --- a/modules/attestation-report/src/lib.rs +++ b/modules/attestation-report/src/lib.rs @@ -20,15 +20,12 @@ mod prelude { pub use core::iter::FromIterator; } +pub use dcap::DCAPQuote; pub use errors::Error; -mod errors; +pub use ias::{IASAttestationVerificationReport, IASSignedReport}; +pub use report::{Quote, ReportData, VerifiableQuote}; -pub use report::{ - AttestationVerificationReport, Quote, ReportData, SignedAttestationVerificationReport, -}; +mod dcap; +mod errors; +mod ias; mod report; - -#[cfg(feature = "std")] -pub use verification::verify_report; -#[cfg(feature = "std")] -mod verification; diff --git a/modules/attestation-report/src/report.rs b/modules/attestation-report/src/report.rs index 472a5172..1b11a732 100644 --- a/modules/attestation-report/src/report.rs +++ b/modules/attestation-report/src/report.rs @@ -1,15 +1,39 @@ -use crate::errors::Error; -use crate::prelude::*; -use base64::{engine::general_purpose::STANDARD as Base64Std, Engine}; -use chrono::prelude::DateTime; +use crate::{dcap::DCAPQuote, errors::Error}; +use crate::{prelude::*, IASSignedReport}; use core::fmt::{Debug, Display, Error as FmtError}; use crypto::Address; use lcp_types::Time; -use serde::{Deserialize, Serialize}; use sgx_types::{metadata::metadata_t, sgx_measurement_t, sgx_quote_t, sgx_report_data_t}; pub const REPORT_DATA_V1: u8 = 1; +#[derive(Debug)] +pub enum VerifiableQuote { + IAS(IASSignedReport), + DCAP(DCAPQuote), +} + +impl VerifiableQuote { + pub fn attested_at(&self) -> Result { + match self { + VerifiableQuote::IAS(report) => report.get_avr()?.attestation_time(), + VerifiableQuote::DCAP(quote) => Ok(quote.attested_at), + } + } +} + +impl From for VerifiableQuote { + fn from(report: IASSignedReport) -> Self { + VerifiableQuote::IAS(report) + } +} + +impl From for VerifiableQuote { + fn from(quote: DCAPQuote) -> Self { + VerifiableQuote::DCAP(quote) + } +} + /// ReportData is a 64-byte value that is embedded in the Quote /// | version: 1 byte | enclave key: 20 bytes | operator: 20 bytes | nonce: 22 bytes | #[derive(Debug, Clone, PartialEq)] @@ -79,114 +103,6 @@ impl From for ReportData { } } -/// SignedAttestationVerificationReport represents the signed attestation verification report from Intel -#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct SignedAttestationVerificationReport { - /// A report generated by the Intel Attestation Service - pub avr: String, - /// Signature of the report - #[serde(with = "serde_base64")] - pub signature: Vec, - /// Certificate matching the signing key of the signature - #[serde(with = "serde_base64")] - pub signing_cert: Vec, -} - -impl SignedAttestationVerificationReport { - pub fn get_avr(&self) -> Result { - serde_json::from_slice(self.avr.as_ref()).map_err(Error::serde_json) - } - - pub fn to_json(&self) -> Result { - serde_json::to_string(self).map_err(Error::serde_json) - } - - pub fn from_json(json: &str) -> Result { - serde_json::from_str(json).map_err(Error::serde_json) - } -} - -// AttestationVerificationReport represents Intel's Attestation Verification Report -// https://api.trustedservices.intel.com/documents/sgx-attestation-api-spec.pdf -#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)] -pub struct AttestationVerificationReport { - pub id: String, - pub timestamp: String, - pub version: i64, - #[serde(alias = "isvEnclaveQuoteStatus")] - pub isv_enclave_quote_status: String, - #[serde(alias = "isvEnclaveQuoteBody")] - pub isv_enclave_quote_body: String, - #[serde(alias = "revocationReason")] - pub revocation_reason: Option, - #[serde(alias = "pseManifestStatus")] - pub pse_manifest_status: Option, - #[serde(alias = "pseManifestHash")] - pub pse_manifest_hash: Option, - #[serde(alias = "platformInfoBlob")] - pub platform_info_blob: Option, - pub nonce: Option, - #[serde(alias = "epidPseudonym")] - pub epid_pseudonym: Option>, - #[serde(alias = "advisoryURL")] - pub advisory_url: String, - #[serde(alias = "advisoryIDs")] - pub advisory_ids: Vec, -} - -impl AttestationVerificationReport { - pub fn attestation_time(&self) -> Result { - let time_fixed = self.timestamp.clone() + "+0000"; - let dt = DateTime::parse_from_str(&time_fixed, "%Y-%m-%dT%H:%M:%S%.f%z")?; - Ok(Time::from_unix_timestamp( - dt.timestamp(), - dt.timestamp_subsec_nanos(), - )?) - } - - pub fn parse_quote(&self) -> Result { - if self.version != 4 { - return Err(Error::unexpected_attestation_report_version( - 4, - self.version, - )); - } - - let quote = Base64Std - .decode(&self.isv_enclave_quote_body) - .map_err(Error::base64)?; - let sgx_quote: sgx_quote_t = unsafe { core::ptr::read(quote.as_ptr() as *const _) }; - Ok(Quote { - raw: sgx_quote, - status: self.isv_enclave_quote_status.clone(), - attestation_time: self.attestation_time()?, - }) - } - - #[cfg(feature = "std")] - pub fn to_canonical_json(&self) -> Result { - if self.version != 4 { - return Err(Error::unexpected_attestation_report_version( - 4, - self.version, - )); - } - Ok(format!( - "{}", - serde_json::json!({ - "id": self.id, - "timestamp": self.timestamp, - "version": self.version, - "advisoryURL": self.advisory_url, - "advisoryIDs": self.advisory_ids, - "isvEnclaveQuoteStatus": self.isv_enclave_quote_status, - "platformInfoBlob": self.platform_info_blob, - "isvEnclaveQuoteBody": self.isv_enclave_quote_body - }) - )) - } -} - #[derive(Clone, Debug, PartialEq)] pub struct Quote { pub raw: sgx_quote_t, @@ -214,20 +130,3 @@ impl Quote { } } } - -mod serde_base64 { - use super::*; - use serde::{Deserialize, Deserializer, Serialize, Serializer}; - - pub fn serialize(v: &Vec, s: S) -> Result { - let base64 = Base64Std.encode(v); - String::serialize(&base64, s) - } - - pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> { - let base64 = String::deserialize(d)?; - Base64Std - .decode(base64.as_bytes()) - .map_err(serde::de::Error::custom) - } -} diff --git a/modules/attestation-report/src/verification.rs b/modules/attestation-report/src/verification.rs deleted file mode 100644 index 4a79c23f..00000000 --- a/modules/attestation-report/src/verification.rs +++ /dev/null @@ -1,73 +0,0 @@ -use crate::prelude::*; -use crate::{errors::Error, SignedAttestationVerificationReport}; -use lcp_types::{nanos_to_duration, Time}; - -pub const IAS_REPORT_CA: &[u8] = - include_bytes!("../../../enclave/Intel_SGX_Attestation_RootCA.pem"); - -type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm]; -static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[ - &webpki::ECDSA_P256_SHA256, - &webpki::ECDSA_P256_SHA384, - &webpki::ECDSA_P384_SHA256, - &webpki::ECDSA_P384_SHA384, - &webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY, - &webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY, - &webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY, - &webpki::RSA_PKCS1_2048_8192_SHA256, - &webpki::RSA_PKCS1_2048_8192_SHA384, - &webpki::RSA_PKCS1_2048_8192_SHA512, - &webpki::RSA_PKCS1_3072_8192_SHA384, -]; - -pub fn verify_report( - current_timestamp: Time, - report: &SignedAttestationVerificationReport, -) -> Result<(), Error> { - // NOTE: Currently, webpki::Time's constructor only accepts seconds as unix timestamp. - // Therefore, the current time are rounded up conservatively. - let duration = nanos_to_duration(current_timestamp.as_unix_timestamp_nanos())?; - let secs = if duration.subsec_nanos() > 0 { - duration.as_secs() + 1 - } else { - duration.as_secs() - }; - let now = webpki::Time::from_seconds_since_unix_epoch(secs); - let root_ca_pem = pem::parse(IAS_REPORT_CA).expect("failed to parse pem bytes"); - let root_ca = root_ca_pem.contents(); - - let mut root_store = rustls::RootCertStore::empty(); - root_store - .add(&rustls::Certificate(root_ca.to_vec())) - .map_err(|e| Error::web_pki(e.to_string()))?; - - let trust_anchors: Vec = root_store - .roots - .iter() - .map(|cert| cert.to_trust_anchor()) - .collect(); - - let chain = vec![root_ca]; - - let report_cert = webpki::EndEntityCert::from(&report.signing_cert) - .map_err(|e| Error::web_pki(e.to_string()))?; - - report_cert - .verify_is_valid_tls_server_cert( - SUPPORTED_SIG_ALGS, - &webpki::TLSServerTrustAnchors(&trust_anchors), - &chain, - now, - ) - .map_err(|e| Error::web_pki(e.to_string()))?; - - report_cert - .verify_signature( - &webpki::RSA_PKCS1_2048_8192_SHA256, - report.avr.as_ref(), - &report.signature, - ) - .map_err(|e| Error::web_pki(e.to_string()))?; - - Ok(()) -} diff --git a/modules/dcap-qvl/.gitignore b/modules/dcap-qvl/.gitignore new file mode 100644 index 00000000..06aba01b --- /dev/null +++ b/modules/dcap-qvl/.gitignore @@ -0,0 +1,2 @@ +Cargo.lock +/target diff --git a/modules/dcap-qvl/Cargo.toml b/modules/dcap-qvl/Cargo.toml new file mode 100644 index 00000000..f12c89db --- /dev/null +++ b/modules/dcap-qvl/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = "dcap-qvl" +version = "0.1.3" +edition = "2021" +license = "MIT" +description = "This crate implements the quote verification logic for DCAP (Data Center Attestation Primitives) in pure Rust." +authors = ["Kevin Wang ", "Jun Kimura "] + +[dependencies] +hex = { version = "0.4", default-features = false, features = ["alloc"] } +serde = { version = "1", default-features = false, features = ["derive"] } +scale = { package = "parity-scale-codec", version = "3.6.5", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2", default-features = false, features = ["derive"] } +chrono = { version = "0.4.31", default-features = false, features = [ + "alloc", + "serde", +] } +const-oid = { version = "0.9.5", default-features = false } +x509-cert = { version = "0.2.4", default-features = false } +pem = { version = "3", default-features = false } +asn1_der = { version = "0.7", default-features = false, features = [ + "native_types", +] } +der = { version = "0.7.8", default-features = false, features = ["alloc"] } +anyhow = { version = "1", default-features = false } +ring = { version = "0.16.20", default-features = false, features = [ + "alloc", +] } +reqwest = { version = "0.11.27", optional = true, default-features = false, features = [ + "rustls-tls", + "blocking", + "hickory-dns", +] } +urlencoding = { version = "2", optional = true } +serde_json = { version = "1.0.108", default-features = false, features = [ + "alloc", +] } + +[dependencies.webpki] +version = "0.102.7" +package = "rustls-webpki" +default-features = false +features = ["alloc", "ring"] + +[dev-dependencies] +insta = "1" +tokio = { version = "1", features = ["full"] } + +[features] +default = ["std", "report"] +std = [ + "serde/std", + "scale/std", + "scale-info/std", + "anyhow/std", + "ring/std", + "webpki/std", + "const-oid/std", + "pem/std", + "asn1_der/std", + "der/std", + "reqwest", + "urlencoding", +] +report = ["std"] diff --git a/modules/dcap-qvl/LICENSE b/modules/dcap-qvl/LICENSE new file mode 100644 index 00000000..7eb78102 --- /dev/null +++ b/modules/dcap-qvl/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Phala Network + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/dcap-qvl/README.md b/modules/dcap-qvl/README.md new file mode 100644 index 00000000..2d1e01bd --- /dev/null +++ b/modules/dcap-qvl/README.md @@ -0,0 +1,43 @@ + + + +# dcap-qvl + +This crate implements the quote verification logic for DCAP (Data Center Attestation Primitives) in pure Rust. It supports both SGX (Software Guard Extensions) and TDX (Trust Domain Extensions) quotes. + +# Features +- Verify SGX and TDX quotes +- Get collateral from PCCS +- Extract information from quotes + +# Usage +Add the following dependency to your `Cargo.toml` file to use this crate: +```toml +[dependencies] +dcap-qvl = "0.1.0" +``` + +# Example: Get Collateral from PCCS_URL and Verify Quote + +To get collateral from a PCCS_URL and verify a quote, you can use the following example code: +```rust +use dcap_qvl::collateral::get_collateral; +use dcap_qvl::verify::verify; + +#[tokio::main] +async fn main() { + // Get PCCS_URL from environment variable. The URL is like "https://localhost:8081/sgx/certification/v4/". + let pccs_url = std::env::var("PCCS_URL").expect("PCCS_URL is not set"); + let quote = std::fs::read("tdx_quote").expect("tdx_quote is not found"); + let collateral = get_collateral(&pccs_url, "e, std::time::Duration::from_secs(10)).await.expect("failed to get collateral"); + let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(); + let tcb = verify("e, &collateral, now).expect("failed to verify quote"); + println!("{:?}", tcb); +} +``` + + + +# License + +This crate is licensed under the MIT license. See the LICENSE file for details. diff --git a/modules/dcap-qvl/sample/sgx_quote b/modules/dcap-qvl/sample/sgx_quote new file mode 100644 index 00000000..9ad774da Binary files /dev/null and b/modules/dcap-qvl/sample/sgx_quote differ diff --git a/modules/dcap-qvl/sample/sgx_quote_collateral b/modules/dcap-qvl/sample/sgx_quote_collateral new file mode 100644 index 00000000..8049c96f --- /dev/null +++ b/modules/dcap-qvl/sample/sgx_quote_collateral @@ -0,0 +1,98 @@ +-----BEGIN CERTIFICATE----- +MIICmDCCAj6gAwIBAgIVANDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMC +MGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD +b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw +CQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHExIzAh +BgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQKDBFJbnRl +bCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNB +MQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL9q+NMp2IOg +tdl1bk/uWZ5+TGQm8aCi8z78fs+fKCQ3d+uDzXnVTAT2ZhDCifyIuJwvN3wNBp9i +HBSSMJMJrBOjgbswgbgwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqww +UgYDVR0fBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNl +cnZpY2VzLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFNDo +qtp11/kuSReYPHsUZdDV8llNMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG +AQH/AgEAMAoGCCqGSM49BAMCA0gAMEUCIQCJgTbtVqOyZ1m3jqiAXM6QYa6r5sWS +4y/G7y8uIJGxdwIgRqPvBSKzzQagBLQq5s5A70pdoiaRJ8z/0uDz4NgV91k= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- +) 308201213081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3233303430333130323235315a170d3234303430323130323235315aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020348003045022051577d47d9fba157b65f1eb5f4657bbc5e56ccaf735a03f1b963d704805ab118022100939015ec1636e7eafa5f426c1e402647c673132b6850cabd68cef6bad7682a03q 3082012a3081d1020101300a06082a8648ce3d04030230713123302106035504030c1a496e74656c205347582050434b2050726f636573736f72204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3233313132313030333530305a170d3233313232313030333530305aa02f302d300a0603551d140403020101301f0603551d23041830168014d0e8aada75d7f92e4917983c7b1465d0d5f2594d300a06082a8648ce3d0403020348003045022100e6c77526dd47d8046ddbf4400ec682bc9ebb2b3c29ec70ce14894bb7b7e7cba4022079aa0f91245352971b014adf68db7b4ed72c053bd4863196ae812adeb77eb74d-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- +F{"id":"SGX","version":3,"issueDate":"2023-11-21T00:06:09Z","nextUpdate":"2023-12-21T00:06:09Z","fmspc":"00A067110000","pceId":"0000","tcbType":0,"tcbEvaluationDataNumber":16,"tcbLevels":[{"tcb":{"sgxtcbcomponents":[{"svn":11},{"svn":11},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":12},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":13},"tcbDate":"2023-08-09T00:00:00Z","tcbStatus":"SWHardeningNeeded","advisoryIDs":["INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":11},{"svn":11},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":13},"tcbDate":"2023-08-09T00:00:00Z","tcbStatus":"ConfigurationAndSWHardeningNeeded","advisoryIDs":["INTEL-SA-00289","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":10},{"svn":10},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":12},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":13},"tcbDate":"2023-02-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00828","INTEL-SA-00289","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":10},{"svn":10},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":13},"tcbDate":"2023-02-15T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00289","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":9},{"svn":9},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":12},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":13},"tcbDate":"2022-11-09T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00289","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":9},{"svn":9},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":13},"tcbDate":"2022-11-09T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00289","INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":4},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00614","INTEL-SA-00617","INTEL-SA-00289","INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":4},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00289","INTEL-SA-00614","INTEL-SA-00617","INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00289","INTEL-SA-00614","INTEL-SA-00617","INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":10},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDateConfigurationNeeded","advisoryIDs":["INTEL-SA-00477","INTEL-SA-00289","INTEL-SA-00614","INTEL-SA-00617","INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00828","INTEL-SA-00615"]},{"tcb":{"sgxtcbcomponents":[{"svn":5},{"svn":5},{"svn":2},{"svn":2},{"svn":255},{"svn":1},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":5},"tcbDate":"2018-01-04T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00106","INTEL-SA-00115","INTEL-SA-00135","INTEL-SA-00203","INTEL-SA-00220","INTEL-SA-00233","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00289","INTEL-SA-00614","INTEL-SA-00617","INTEL-SA-00657","INTEL-SA-00767","INTEL-SA-00828","INTEL-SA-00615"]}]}%y=w#݋J"(%KS=gfT#9t&})+E@ bٰ:#.H-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- +{"id":"QE","version":2,"issueDate":"2023-11-21T00:39:26Z","nextUpdate":"2023-12-21T00:39:26Z","tcbEvaluationDataNumber":16,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":8},"tcbDate":"2023-08-09T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00615"]},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]}]}QUkץ^Be;7]uTǁ +٭  +z9?>"bs \ No newline at end of file diff --git a/modules/dcap-qvl/sample/tdx_quote b/modules/dcap-qvl/sample/tdx_quote new file mode 100644 index 00000000..facdebb0 Binary files /dev/null and b/modules/dcap-qvl/sample/tdx_quote differ diff --git a/modules/dcap-qvl/sample/tdx_quote_collateral b/modules/dcap-qvl/sample/tdx_quote_collateral new file mode 100644 index 00000000..92f444e8 --- /dev/null +++ b/modules/dcap-qvl/sample/tdx_quote_collateral @@ -0,0 +1,98 @@ +-----BEGIN CERTIFICATE----- +MIICmDCCAj6gAwIBAgIVANDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMC +MGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD +b3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw +CQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHExIzAh +BgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQKDBFJbnRl +bCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNB +MQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL9q+NMp2IOg +tdl1bk/uWZ5+TGQm8aCi8z78fs+fKCQ3d+uDzXnVTAT2ZhDCifyIuJwvN3wNBp9i +HBSSMJMJrBOjgbswgbgwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqww +UgYDVR0fBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNl +cnZpY2VzLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFNDo +qtp11/kuSReYPHsUZdDV8llNMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG +AQH/AgEAMAoGCCqGSM49BAMCA0gAMEUCIQCJgTbtVqOyZ1m3jqiAXM6QYa6r5sWS +4y/G7y8uIJGxdwIgRqPvBSKzzQagBLQq5s5A70pdoiaRJ8z/0uDz4NgV91k= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- +1 308201223081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3234303332303139313933305a170d3235303430333139313933305aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020349003046022100e7606fef2da68785a0c39bc34ac344c9e2d6ed4b0223e79a6c6297d421b73784022100fc1587aece4296d5e9370fd6a444a72d03c598cb21dc8104c55b127b766ea82bi 308201293081d1020101300a06082a8648ce3d04030230713123302106035504030c1a496e74656c205347582050434b2050726f636573736f72204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3234303930323034343432325a170d3234313030323034343432325aa02f302d300a0603551d140403020101301f0603551d23041830168014d0e8aada75d7f92e4917983c7b1465d0d5f2594d300a06082a8648ce3d04030203470030440220595960d75b439d47f024a96b42a759465e6b2069a239f976bdafbe1c4034bc19022008a98744e0a8b34ac03c31221090500d2b0b66b953627dd39a0e7b45e38fd4d6-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- +y{"id":"SGX","version":3,"issueDate":"2024-09-02T00:42:10Z","nextUpdate":"2024-10-02T00:42:10Z","fmspc":"B0C06F000000","pceId":"0000","tcbType":0,"tcbEvaluationDataNumber":16,"tcbLevels":[{"tcb":{"sgxtcbcomponents":[{"svn":2,"category":"BIOS","type":"Early Microcode Update"},{"svn":2,"category":"OS/VMM","type":"SGX Late Microcode Update"},{"svn":2,"category":"OS/VMM","type":"TXT SINIT"},{"svn":2,"category":"BIOS"},{"svn":3,"category":"BIOS"},{"svn":1,"category":"BIOS"},{"svn":0},{"svn":3,"category":"OS/VMM","type":"SEAMLDR ACM"},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":11},"tcbDate":"2023-08-09T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"sgxtcbcomponents":[{"svn":2,"category":"BIOS","type":"Early Microcode Update"},{"svn":2,"category":"OS/VMM","type":"SGX Late Microcode Update"},{"svn":2,"category":"OS/VMM","type":"TXT SINIT"},{"svn":2,"category":"BIOS"},{"svn":3,"category":"BIOS"},{"svn":1,"category":"BIOS"},{"svn":0},{"svn":3,"category":"OS/VMM","type":"SEAMLDR ACM"},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0},{"svn":0}],"pcesvn":5},"tcbDate":"2018-01-04T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00106","INTEL-SA-00115","INTEL-SA-00135","INTEL-SA-00203","INTEL-SA-00220","INTEL-SA-00233","INTEL-SA-00270","INTEL-SA-00293","INTEL-SA-00320","INTEL-SA-00329","INTEL-SA-00381","INTEL-SA-00389","INTEL-SA-00477","INTEL-SA-00837"]}]}H((ɈGU2$:Y_? C&*]V> sWLu2wuLV-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE----- +{"id":"QE","version":2,"issueDate":"2024-09-02T00:35:42Z","nextUpdate":"2024-10-02T00:35:42Z","tcbEvaluationDataNumber":16,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":8},"tcbDate":"2023-08-09T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00615"]},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477","INTEL-SA-00615"]}]} `c-Zh% bmTE/<۶Nؽ:@E8F~:95# +B \ No newline at end of file diff --git a/modules/dcap-qvl/src/collateral.rs b/modules/dcap-qvl/src/collateral.rs new file mode 100644 index 00000000..a985346d --- /dev/null +++ b/modules/dcap-qvl/src/collateral.rs @@ -0,0 +1,110 @@ +use core::time::Duration; + +use alloc::string::{String, ToString}; +use anyhow::{anyhow, Result}; +use scale::Decode; + +use crate::quote::Quote; +use crate::QuoteCollateralV3; + +fn get_header(resposne: &reqwest::Response, name: &str) -> Result { + let value = resposne + .headers() + .get(name) + .ok_or(anyhow!("Missing {name}"))? + .to_str()?; + let value = urlencoding::decode(value)?; + Ok(value.into_owned()) +} + +/// Get collateral given DCAP quote and base URL of PCCS server URL. +/// +/// # Arguments +/// +/// * `pccs_url` - The base URL of PCCS server. (e.g. `https://pccs.example.com/sgx/certification/v4`) +/// * `quote` - The raw quote to verify. Supported SGX and TDX quotes. +/// * `timeout` - The timeout for the request. (e.g. `Duration::from_secs(10)`) +/// +/// # Returns +/// +/// * `Ok(QuoteCollateralV3)` - The quote collateral +/// * `Err(Error)` - The error +pub async fn get_collateral( + pccs_url: &str, + mut quote: &[u8], + timeout: Duration, +) -> Result { + let quote = Quote::decode(&mut quote)?; + let fmspc = hex::encode_upper(quote.fmspc().map_err(|_| anyhow!("get fmspc error"))?); + let client = reqwest::Client::builder() + .danger_accept_invalid_certs(true) + .timeout(timeout) + .build()?; + let base_url = pccs_url.trim_end_matches('/'); + + let pck_crl_issuer_chain; + let pck_crl; + { + let response = client + .get(format!("{base_url}/pckcrl?ca=processor")) + .send() + .await?; + println!("{:#?}", response); + pck_crl_issuer_chain = get_header(&response, "SGX-PCK-CRL-Issuer-Chain")?; + pck_crl = response.text().await?; + }; + let tcb_info_issuer_chain; + let raw_tcb_info; + { + let resposne = client + .get(format!("{base_url}/tcb?fmspc={fmspc}")) + .send() + .await?; + tcb_info_issuer_chain = get_header(&resposne, "SGX-TCB-Info-Issuer-Chain") + .or(get_header(&resposne, "TCB-Info-Issuer-Chain"))?; + raw_tcb_info = resposne.text().await?; + }; + let qe_identity_issuer_chain; + let raw_qe_identity; + { + let response = client.get(format!("{base_url}/qe/identity")).send().await?; + qe_identity_issuer_chain = get_header(&response, "SGX-Enclave-Identity-Issuer-Chain")?; + raw_qe_identity = response.text().await?; + }; + + let tcb_info_json: serde_json::Value = + serde_json::from_str(&raw_tcb_info).map_err(|_| anyhow!("TCB Info should a JSON"))?; + let tcb_info = tcb_info_json["tcbInfo"].to_string(); + let tcb_info_signature = tcb_info_json + .get("signature") + .ok_or(anyhow!("TCB Info should has `signature` field"))? + .as_str() + .ok_or(anyhow!("TCB Info signature should a hex string"))?; + let tcb_info_signature = hex::decode(tcb_info_signature) + .map_err(|_| anyhow!("TCB Info signature should a hex string"))?; + + let qe_identity_json: serde_json::Value = serde_json::from_str(raw_qe_identity.as_str()) + .map_err(|_| anyhow!("QE Identity should a JSON"))?; + let qe_identity = qe_identity_json + .get("enclaveIdentity") + .ok_or(anyhow!("QE Identity should has `enclaveIdentity` field"))? + .to_string(); + let qe_identity_signature = qe_identity_json + .get("signature") + .ok_or(anyhow!("QE Identity should has `signature` field"))? + .as_str() + .ok_or(anyhow!("QE Identity signature should a hex string"))?; + let qe_identity_signature = hex::decode(qe_identity_signature) + .map_err(|_| anyhow!("QE Identity signature should a hex string"))?; + + Ok(QuoteCollateralV3 { + pck_crl_issuer_chain, + pck_crl, + tcb_info_issuer_chain, + tcb_info, + tcb_info_signature, + qe_identity_issuer_chain, + qe_identity, + qe_identity_signature, + }) +} diff --git a/modules/dcap-qvl/src/constants.rs b/modules/dcap-qvl/src/constants.rs new file mode 100644 index 00000000..c0afcb06 --- /dev/null +++ b/modules/dcap-qvl/src/constants.rs @@ -0,0 +1,132 @@ +#![allow(dead_code)] + +pub type MrSigner = [u8; 32]; +pub type MrEnclave = [u8; 32]; +pub type Fmspc = [u8; 6]; +pub type CpuSvn = [u8; 16]; +pub type Svn = u16; + +pub const ATTESTATION_KEY_TYPE_ECDSA256_WITH_P256_CURVE: u16 = 2; +pub const ATTESTATION_KEY_TYPE_ECDSA484_WITH_P384_CURVE: u16 = 3; + +pub const TEE_TYPE_SGX: u32 = 0x00000000; +pub const TEE_TYPE_TDX: u32 = 0x00000081; + +pub const ECDSA_256_WITH_P256_CURVE: u16 = 2; +pub const ECDSA_384_WITH_P384_CURVE: u16 = 3; +pub const ECDSA_P256_SIGNATURE_BYTE_LEN: usize = 64; +pub const BODY_BYTE_SIZE: usize = 6; +pub const BODY_SGX_ENCLAVE_REPORT_TYPE: u16 = 1; +pub const BODY_TD_REPORT10_TYPE: u16 = 2; +pub const BODY_TD_REPORT15_TYPE: u16 = 3; +pub const ENCLAVE_REPORT_BYTE_LEN: usize = 384; +pub const TD_REPORT10_BYTE_LEN: usize = 584; +pub const TD_REPORT15_BYTE_LEN: usize = 648; + +pub const PCK_ID_PLAIN_PPID: u16 = 1; +pub const PCK_ID_ENCRYPTED_PPID_2048: u16 = 2; +pub const PCK_ID_ENCRYPTED_PPID_3072: u16 = 3; +pub const PCK_ID_PCK_CERTIFICATE: u16 = 4; +pub const PCK_ID_PCK_CERT_CHAIN: u16 = 5; +pub const PCK_ID_QE_REPORT_CERTIFICATION_DATA: u16 = 6; + +pub const ALLOWED_QUOTE_VERSIONS: [u16; 3] = [3, 4, 5]; +pub const ALLOWED_BODY_TYPES: [u16; 3] = [ + BODY_SGX_ENCLAVE_REPORT_TYPE, + BODY_TD_REPORT10_TYPE, + BODY_TD_REPORT15_TYPE, +]; +pub const ALLOWED_TEE_TYPES: [u32; 2] = [TEE_TYPE_SGX, TEE_TYPE_TDX]; +pub const ALLOWED_ATTESTATION_KEY_TYPES: [u16; 1] = [ECDSA_256_WITH_P256_CURVE]; +pub const INTEL_QE_VENDOR_ID: [u8; 16] = [ + 0x93, 0x9A, 0x72, 0x33, 0xF7, 0x9C, 0x4C, 0xA9, 0x94, 0x0A, 0x0D, 0xB3, 0x95, 0x7F, 0x06, 0x07, +]; +pub const HEADER_BYTE_LEN: usize = 48; +pub const AUTH_DATA_SIZE_BYTE_LEN: usize = 4; + +pub const ECDSA_SIGNATURE_BYTE_LEN: usize = 64; +pub const ECDSA_PUBKEY_BYTE_LEN: usize = 64; +pub const QE_REPORT_BYTE_LEN: usize = ENCLAVE_REPORT_BYTE_LEN; +pub const QE_REPORT_SIG_BYTE_LEN: usize = ECDSA_SIGNATURE_BYTE_LEN; +pub const CERTIFICATION_DATA_TYPE_BYTE_LEN: usize = 2; +pub const CERTIFICATION_DATA_SIZE_BYTE_LEN: usize = 4; +pub const QE_AUTH_DATA_SIZE_BYTE_LEN: usize = 2; +pub const QE_CERT_DATA_TYPE_BYTE_LEN: usize = 2; +pub const QE_CERT_DATA_SIZE_BYTE_LEN: usize = 4; + +pub const AUTH_DATA_MIN_BYTE_LEN: usize = ECDSA_SIGNATURE_BYTE_LEN + + ECDSA_PUBKEY_BYTE_LEN + + QE_REPORT_BYTE_LEN + + QE_REPORT_SIG_BYTE_LEN + + QE_AUTH_DATA_SIZE_BYTE_LEN + + QE_CERT_DATA_TYPE_BYTE_LEN + + QE_CERT_DATA_SIZE_BYTE_LEN; + +pub const QUOTE_MIN_BYTE_LEN: usize = + // Actual minimal size is a Quote V3 with Enclave report + HEADER_BYTE_LEN + + ENCLAVE_REPORT_BYTE_LEN + + AUTH_DATA_SIZE_BYTE_LEN + + AUTH_DATA_MIN_BYTE_LEN; + +pub const ATTESTATION_KEY_LEN: usize = 64; +pub const AUTHENTICATION_DATA_LEN: usize = 32; +pub const QE_HASH_DATA_BYTE_LEN: usize = ATTESTATION_KEY_LEN + AUTHENTICATION_DATA_LEN; + +pub const PCK_ID_PLAIN: u16 = 1; +pub const PCK_ID_RSA_2048_OAEP: u16 = 2; +pub const PCK_ID_RSA_3072_OAEP: u16 = 3; +pub const PCK_LEAF_CERT_PLAIN: u16 = 4; +pub const PCK_CERT_CHAIN: u16 = 5; +pub const QE_REPORT_CERT: u16 = 6; +pub const PLATFORM_MANIFEST: u16 = 7; + +/// The needed code for a trust anchor can be extracted using `webpki` with something like this: +/// println!("{:?}", webpki::TrustAnchor::try_from_cert_der(&root_cert)); +#[allow(clippy::zero_prefixed_literal)] +pub static DCAP_SERVER_ROOTS: &[webpki::types::TrustAnchor<'static>; 1] = + &[webpki::types::TrustAnchor { + subject: webpki::types::Der::from_slice(&[ + 49, 26, 48, 24, 06, 03, 85, 04, 03, 12, 17, 73, 110, 116, 101, 108, 32, 83, 71, 88, 32, + 82, 111, 111, 116, 32, 67, 65, 49, 26, 48, 24, 06, 03, 85, 04, 10, 12, 17, 73, 110, + 116, 101, 108, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 49, 20, 48, 18, + 06, 03, 85, 04, 07, 12, 11, 83, 97, 110, 116, 97, 32, 67, 108, 97, 114, 97, 49, 11, 48, + 09, 06, 03, 85, 04, 08, 12, 02, 67, 65, 49, 11, 48, 09, 06, 03, 85, 04, 06, 19, 02, 85, + 83, + ]), + subject_public_key_info: webpki::types::Der::from_slice(&[ + 48, 19, 06, 07, 42, 134, 72, 206, 61, 02, 01, 06, 08, 42, 134, 72, 206, 61, 03, 01, 07, + 03, 66, 00, 04, 11, 169, 196, 192, 192, 200, 97, 147, 163, 254, 35, 214, 176, 44, 218, + 16, 168, 187, 212, 232, 142, 72, 180, 69, 133, 97, 163, 110, 112, 85, 37, 245, 103, + 145, 142, 46, 220, 136, 228, 13, 134, 11, 208, 204, 78, 226, 106, 172, 201, 136, 229, + 05, 169, 83, 85, 140, 69, 63, 107, 09, 04, 174, 115, 148, + ]), + name_constraints: None, + }]; + +pub mod oids { + use const_oid::ObjectIdentifier as OID; + + const fn oid(s: &str) -> OID { + OID::new_unwrap(s) + } + + pub const SGX_EXTENSION: OID = oid("1.2.840.113741.1.13.1"); + pub const PPID: OID = oid("1.2.840.113741.1.13.1.1"); + pub const TCB: OID = oid("1.2.840.113741.1.13.1.2"); + pub const PCEID: OID = oid("1.2.840.113741.1.13.1.3"); + pub const FMSPC: OID = oid("1.2.840.113741.1.13.1.4"); + pub const SGX_TYPE: OID = oid("1.2.840.113741.1.13.1.5"); // ASN1 Enumerated + pub const PLATFORM_INSTANCE_ID: OID = oid("1.2.840.113741.1.13.1.6"); + pub const CONFIGURATION: OID = oid("1.2.840.113741.1.13.1.7"); + pub const PCESVN: OID = oid("1.2.840.113741.1.13.1.2.17"); + pub const CPUSVN: OID = oid("1.2.840.113741.1.13.1.2.18"); + + #[test] + fn const_oid_works() { + assert_eq!( + SGX_EXTENSION.as_bytes(), + oid("1.2.840.113741.1.13.1").as_bytes() + ); + } +} diff --git a/modules/dcap-qvl/src/lib.rs b/modules/dcap-qvl/src/lib.rs new file mode 100644 index 00000000..87ac358c --- /dev/null +++ b/modules/dcap-qvl/src/lib.rs @@ -0,0 +1,118 @@ +//! # dcap-qvl +//! +//! This crate implements the quote verification logic for DCAP (Data Center Attestation Primitives) in pure Rust. It supports both SGX (Software Guard Extensions) and TDX (Trust Domain Extensions) quotes. +//! +//! # Features +//! - Verify SGX and TDX quotes +//! - Get collateral from PCCS +//! - Extract information from quotes +//! +//! # Usage +//! Add the following dependency to your `Cargo.toml` file to use this crate: +//! ```toml +//! [dependencies] +//! dcap-qvl = "0.1.0" +//! ``` +//! +//! # Example: Get Collateral from PCCS_URL and Verify Quote +//! +//! To get collateral from a PCCS_URL and verify a quote, you can use the following example code: +//! ```no_run +//! use dcap_qvl::collateral::get_collateral; +//! use dcap_qvl::verify::verify; +//! +//! #[tokio::main] +//! async fn main() { +//! // Get PCCS_URL from environment variable. The URL is like "https://localhost:8081/sgx/certification/v4/". +//! let pccs_url = std::env::var("PCCS_URL").expect("PCCS_URL is not set"); +//! let quote = std::fs::read("tdx_quote").expect("tdx_quote is not found"); +//! let collateral = get_collateral(&pccs_url, "e, std::time::Duration::from_secs(10)).await.expect("failed to get collateral"); +//! let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(); +//! let tcb = verify("e, &collateral, now).expect("failed to verify quote"); +//! println!("{:?}", tcb); +//! } +//! ``` + +#![cfg_attr(all(not(test), not(feature = "std")), no_std)] + +#[macro_use] +extern crate alloc; + +use scale::{Decode, Encode}; +use scale_info::TypeInfo; + +#[allow(unused_imports)] +mod prelude { + pub use core::prelude::v1::*; + + // Re-export according to alloc::prelude::v1 because it is not yet stabilized + // https://doc.rust-lang.org/src/alloc/prelude/v1.rs.html + pub use alloc::borrow::ToOwned; + pub use alloc::boxed::Box; + pub use alloc::string::{String, ToString}; + pub use alloc::vec::Vec; + + pub use alloc::format; + pub use alloc::vec; + + // Those are exported by default in the std prelude in Rust 2021 + pub use core::convert::{TryFrom, TryInto}; + pub use core::iter::FromIterator; +} +use prelude::*; + +#[derive(Encode, Decode, TypeInfo, Debug, Clone, PartialEq, Eq)] +pub enum Error { + InvalidCertificate, + InvalidSignature, + CodecError, + + // DCAP + TCBInfoExpired, + KeyLengthIsInvalid, + PublicKeyIsInvalid, + RsaSignatureIsInvalid, + DerEncodingError, + UnsupportedDCAPQuoteVersion, + UnsupportedDCAPAttestationKeyType, + UnsupportedQuoteAuthData, + UnsupportedDCAPPckCertFormat, + LeafCertificateParsingError, + CertificateChainIsInvalid, + CertificateChainIsTooShort, + IntelExtensionCertificateDecodingError, + IntelExtensionAmbiguity, + CpuSvnLengthMismatch, + CpuSvnDecodingError, + PceSvnDecodingError, + PceSvnLengthMismatch, + FmspcLengthMismatch, + FmspcDecodingError, + FmspcMismatch, + QEReportHashMismatch, + IsvEnclaveReportSignatureIsInvalid, + DerDecodingError, + OidIsMissing, +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, serde::Serialize, serde::Deserialize)] +pub struct QuoteCollateralV3 { + pub pck_crl_issuer_chain: String, + pub pck_crl: String, + pub tcb_info_issuer_chain: String, + pub tcb_info: String, + pub tcb_info_signature: Vec, + pub qe_identity_issuer_chain: String, + pub qe_identity: String, + pub qe_identity_signature: Vec, +} + +#[cfg(feature = "report")] +pub mod collateral; + +mod constants; +mod tcb_info; +mod utils; + +pub mod quote; +pub mod verify; diff --git a/modules/dcap-qvl/src/quote.rs b/modules/dcap-qvl/src/quote.rs new file mode 100644 index 00000000..afa93adb --- /dev/null +++ b/modules/dcap-qvl/src/quote.rs @@ -0,0 +1,284 @@ +use alloc::string::String; +use alloc::vec::Vec; + +use anyhow::{anyhow, Result}; +use scale::{Decode, Input}; + +use crate::{constants::*, utils, Error}; + +#[derive(Debug, Clone)] +pub struct Data { + pub data: Vec, + _marker: core::marker::PhantomData, +} + +impl> Decode for Data { + fn decode(input: &mut I) -> Result { + let len = T::decode(input)?; + let mut data = vec![0u8; len.into() as usize]; + input.read(&mut data)?; + Ok(Data { + data, + _marker: core::marker::PhantomData, + }) + } +} + +#[derive(Decode, Debug)] +pub struct Header { + pub version: u16, + pub attestation_key_type: u16, + pub tee_type: u32, + pub qe_svn: u16, + pub pce_svn: u16, + pub qe_vendor_id: [u8; 16], + pub user_data: [u8; 20], +} + +#[derive(Decode, Debug)] +pub struct Body { + pub body_type: u16, + pub size: u32, +} + +#[derive(Decode, Debug, Clone)] +pub struct EnclaveReport { + pub cpu_svn: [u8; 16], + pub misc_select: u32, + pub reserved1: [u8; 28], + pub attributes: [u8; 16], + pub mr_enclave: [u8; 32], + pub reserved2: [u8; 32], + pub mr_signer: [u8; 32], + pub reserved3: [u8; 96], + pub isv_prod_id: u16, + pub isv_svn: u16, + pub reserved4: [u8; 60], + pub report_data: [u8; 64], +} + +#[derive(Decode, Debug, Clone)] +pub struct TDReport10 { + pub tee_tcb_svn: [u8; 16], + pub mr_seam: [u8; 48], + pub mr_signer_seam: [u8; 48], + pub seam_attributes: [u8; 8], + pub td_attributes: [u8; 8], + pub xfam: [u8; 8], + pub mr_td: [u8; 48], + pub mr_config_id: [u8; 48], + pub mr_owner: [u8; 48], + pub mr_owner_config: [u8; 48], + pub rt_mr0: [u8; 48], + pub rt_mr1: [u8; 48], + pub rt_mr2: [u8; 48], + pub rt_mr3: [u8; 48], + pub report_data: [u8; 64], +} + +#[derive(Decode, Debug, Clone)] +pub struct TDReport15 { + pub base: TDReport10, + pub tee_tcb_svn2: [u8; 16], + pub mr_service_td: [u8; 48], +} + +#[derive(Decode)] +pub struct CertificationData { + pub cert_type: u16, + pub body: Data, +} + +impl core::fmt::Debug for CertificationData { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let body_str = String::from_utf8_lossy(&self.body.data); + f.debug_struct("CertificationData") + .field("cert_type", &self.cert_type) + .field("body", &body_str) + .finish() + } +} + +#[derive(Decode, Debug)] +pub struct QEReportCertificationData { + pub qe_report: [u8; ENCLAVE_REPORT_BYTE_LEN], + pub qe_report_signature: [u8; QE_REPORT_SIG_BYTE_LEN], + pub qe_auth_data: Data, + pub certification_data: CertificationData, +} + +#[derive(Decode, Debug)] +pub struct AuthDataV3 { + pub ecdsa_signature: [u8; ECDSA_SIGNATURE_BYTE_LEN], + pub ecdsa_attestation_key: [u8; ECDSA_PUBKEY_BYTE_LEN], + pub qe_report: [u8; ENCLAVE_REPORT_BYTE_LEN], + pub qe_report_signature: [u8; QE_REPORT_SIG_BYTE_LEN], + pub qe_auth_data: Data, + pub certification_data: CertificationData, +} + +#[derive(Debug)] +pub struct AuthDataV4 { + pub ecdsa_signature: [u8; ECDSA_SIGNATURE_BYTE_LEN], + pub ecdsa_attestation_key: [u8; ECDSA_PUBKEY_BYTE_LEN], + pub certification_data: CertificationData, + pub qe_report_data: QEReportCertificationData, +} + +impl AuthDataV4 { + pub fn into_v3(self) -> AuthDataV3 { + AuthDataV3 { + ecdsa_signature: self.ecdsa_signature, + ecdsa_attestation_key: self.ecdsa_attestation_key, + qe_report: self.qe_report_data.qe_report, + qe_report_signature: self.qe_report_data.qe_report_signature, + qe_auth_data: self.qe_report_data.qe_auth_data, + certification_data: self.qe_report_data.certification_data, + } + } +} + +impl Decode for AuthDataV4 { + fn decode(input: &mut I) -> Result { + let ecdsa_signature = Decode::decode(input)?; + let ecdsa_attestation_key = Decode::decode(input)?; + let certification_data: CertificationData = Decode::decode(input)?; + let qe_report_data = + QEReportCertificationData::decode(&mut &certification_data.body.data[..])?; + Ok(AuthDataV4 { + ecdsa_signature, + ecdsa_attestation_key, + certification_data, + qe_report_data, + }) + } +} + +#[derive(Debug)] +pub enum AuthData { + V3(AuthDataV3), + V4(AuthDataV4), +} + +impl AuthData { + pub fn into_v3(self) -> AuthDataV3 { + match self { + AuthData::V3(data) => data, + AuthData::V4(data) => data.into_v3(), + } + } +} + +fn decode_auth_data(ver: u16, input: &mut &[u8]) -> Result { + match ver { + 3 => { + let auth_data = AuthDataV3::decode(input)?; + Ok(AuthData::V3(auth_data)) + } + 4 => { + let auth_data = AuthDataV4::decode(input)?; + Ok(AuthData::V4(auth_data)) + } + _ => Err(scale::Error::from("unsupported quote version")), + } +} + +#[derive(Debug, Clone)] +pub enum Report { + SgxEnclave(EnclaveReport), + TD10(TDReport10), + TD15(TDReport15), +} + +#[derive(Debug)] +pub struct Quote { + pub header: Header, + pub report: Report, + pub auth_data: AuthData, +} + +impl Decode for Quote { + fn decode(input: &mut I) -> Result { + let header = Header::decode(input)?; + let report; + match header.version { + 3 => { + if header.tee_type != TEE_TYPE_SGX { + return Err(scale::Error::from("invalid tee type")); + } + report = Report::SgxEnclave(EnclaveReport::decode(input)?); + } + 4 => match header.tee_type { + TEE_TYPE_SGX => { + report = Report::SgxEnclave(EnclaveReport::decode(input)?); + } + TEE_TYPE_TDX => { + report = Report::TD10(TDReport10::decode(input)?); + } + _ => return Err(scale::Error::from("invalid tee type")), + }, + 5 => { + let body = Body::decode(input)?; + match body.body_type { + BODY_SGX_ENCLAVE_REPORT_TYPE => { + report = Report::SgxEnclave(EnclaveReport::decode(input)?); + } + BODY_TD_REPORT10_TYPE => { + report = Report::TD10(TDReport10::decode(input)?); + } + BODY_TD_REPORT15_TYPE => { + report = Report::TD15(TDReport15::decode(input)?); + } + _ => return Err(scale::Error::from("unsupported body type")), + } + } + _ => return Err(scale::Error::from("unsupported quote version")), + } + let data = Data::::decode(input)?; + let auth_data = decode_auth_data(header.version, &mut &data.data[..])?; + Ok(Quote { + header, + report, + auth_data, + }) + } +} + +impl Quote { + /// Parse a TEE quote from a byte slice. + pub fn parse(quote: &[u8]) -> Result { + let mut input = quote; + let quote = + Quote::decode(&mut input).map_err(|e| anyhow!("Failed to parse TEE quote: {:?}", e))?; + Ok(quote) + } + + /// Get the raw certificate chain from the quote. + pub fn raw_cert_chain(&self) -> &[u8] { + match &self.auth_data { + AuthData::V3(data) => &data.certification_data.body.data, + AuthData::V4(data) => &data.qe_report_data.certification_data.body.data, + } + } + + /// Get the FMSPC from the quote. + pub fn fmspc(&self) -> Result { + let raw_cert_chain = self.raw_cert_chain(); + let certs = utils::extract_certs(raw_cert_chain)?; + let extension_section = utils::get_intel_extension(&certs[0])?; + utils::get_fmspc(&extension_section) + } + + /// Get the the length of signed data in the quote. + pub fn signed_length(&self) -> usize { + let mut len = match self.report { + Report::SgxEnclave(_) => HEADER_BYTE_LEN + ENCLAVE_REPORT_BYTE_LEN, + Report::TD10(_) => HEADER_BYTE_LEN + TD_REPORT10_BYTE_LEN, + Report::TD15(_) => HEADER_BYTE_LEN + TD_REPORT15_BYTE_LEN, + }; + if self.header.version == 5 { + len += BODY_BYTE_SIZE; + } + len + } +} diff --git a/modules/dcap-qvl/src/tcb_info.rs b/modules/dcap-qvl/src/tcb_info.rs new file mode 100644 index 00000000..56a86905 --- /dev/null +++ b/modules/dcap-qvl/src/tcb_info.rs @@ -0,0 +1,42 @@ +use alloc::string::String; +use alloc::vec::Vec; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbInfo { + pub id: String, + pub version: u8, + pub issue_date: String, + pub next_update: String, + pub fmspc: String, + pub pce_id: String, + pub tcb_type: u32, + pub tcb_evaluation_data_number: u32, + pub tcb_levels: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbLevel { + pub tcb: Tcb, + pub tcb_date: String, + pub tcb_status: String, + #[serde(rename = "advisoryIDs", default)] + pub advisory_ids: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Tcb { + #[serde(rename = "sgxtcbcomponents")] + pub components: Vec, + #[serde(rename = "pcesvn")] + pub pce_svn: u16, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TcbComponents { + pub svn: u8, +} diff --git a/modules/dcap-qvl/src/utils.rs b/modules/dcap-qvl/src/utils.rs new file mode 100644 index 00000000..72a08b09 --- /dev/null +++ b/modules/dcap-qvl/src/utils.rs @@ -0,0 +1,167 @@ +use alloc::vec::Vec; +use asn1_der::{ + typed::{DerDecodable, Sequence}, + DerObject, +}; +use webpki::types::CertificateDer; +use x509_cert::Certificate; + +use crate::constants::*; +use crate::Error; + +pub fn get_intel_extension(der_encoded: &[u8]) -> Result, Error> { + let cert: Certificate = der::Decode::from_der(der_encoded) + .map_err(|_| Error::IntelExtensionCertificateDecodingError)?; + let mut extension_iter = cert + .tbs_certificate + .extensions + .as_deref() + .unwrap_or(&[]) + .iter() + .filter(|e| e.extn_id == oids::SGX_EXTENSION) + .map(|e| e.extn_value.clone()); + + let extension = extension_iter + .next() + .ok_or(Error::IntelExtensionAmbiguity)?; + if extension_iter.next().is_some() { + //"There should only be one section containing Intel extensions" + return Err(Error::IntelExtensionAmbiguity); + } + Ok(extension.into_bytes()) +} + +pub fn find_extension(path: &[&[u8]], raw: &[u8]) -> Result, Error> { + let obj = DerObject::decode(raw).map_err(|_| Error::DerDecodingError)?; + let subobj = get_obj(path, obj)?; + Ok(subobj.value().to_vec()) +} + +fn get_obj<'a>(path: &[&[u8]], mut obj: DerObject<'a>) -> Result, Error> { + for oid in path { + let seq = Sequence::load(obj).map_err(|_| Error::DerDecodingError)?; + obj = sub_obj(oid, seq)?; + } + Ok(obj) +} + +fn sub_obj<'a>(oid: &[u8], seq: Sequence<'a>) -> Result, Error> { + for i in 0..seq.len() { + let entry = seq.get(i).map_err(|_| Error::OidIsMissing)?; + let entry = Sequence::load(entry).map_err(|_| Error::DerDecodingError)?; + let name = entry.get(0).map_err(|_| Error::OidIsMissing)?; + let value = entry.get(1).map_err(|_| Error::OidIsMissing)?; + if name.value() == oid { + return Ok(value); + } + } + Err(Error::OidIsMissing) +} + +pub fn get_fmspc(extension_section: &[u8]) -> Result { + let data = find_extension(&[oids::FMSPC.as_bytes()], extension_section)?; + if data.len() != 6 { + return Err(Error::FmspcLengthMismatch); + } + + data.try_into().map_err(|_| Error::FmspcDecodingError) +} + +pub fn get_cpu_svn(extension_section: &[u8]) -> Result { + let data = find_extension( + &[oids::TCB.as_bytes(), oids::CPUSVN.as_bytes()], + extension_section, + )?; + if data.len() != 16 { + return Err(Error::CpuSvnLengthMismatch); + } + + data.try_into().map_err(|_| Error::CpuSvnDecodingError) +} + +pub fn get_pce_svn(extension_section: &[u8]) -> Result { + let data = find_extension( + &[oids::TCB.as_bytes(), oids::PCESVN.as_bytes()], + extension_section, + )?; + + match data.len() { + 1 => Ok(u16::from(data[0])), + 2 => Ok(u16::from_be_bytes( + data.try_into().map_err(|_| Error::PceSvnDecodingError)?, + )), + _ => Err(Error::PceSvnLengthMismatch), + } +} + +pub fn extract_raw_certs(cert_chain: &[u8]) -> Result>, Error> { + Ok(pem::parse_many(cert_chain) + .map_err(|_| Error::CodecError)? + .iter() + .map(|i| i.contents().to_vec()) + .collect()) +} + +pub fn extract_certs<'a>(cert_chain: &'a [u8]) -> Result>, Error> { + let mut certs = Vec::>::new(); + + let raw_certs = extract_raw_certs(cert_chain)?; + for raw_cert in raw_certs.iter() { + let cert = webpki::types::CertificateDer::<'a>::from(raw_cert.to_vec()); + certs.push(cert); + } + + Ok(certs) +} + +/// Encode two 32-byte values in DER format +/// This is meant for 256 bit ECC signatures or public keys +/// TODO: We may could use `asn1_der` crate reimplement this, so we can remove `der` which overlap with `asn1_der` +pub fn encode_as_der(data: &[u8]) -> Result, Error> { + if data.len() != 64 { + return Err(Error::KeyLengthIsInvalid); + } + let mut sequence = der::asn1::SequenceOf::::new(); + sequence + .add(der::asn1::UintRef::new(&data[0..32]).map_err(|_| Error::PublicKeyIsInvalid)?) + .map_err(|_| Error::PublicKeyIsInvalid)?; + sequence + .add(der::asn1::UintRef::new(&data[32..]).map_err(|_| Error::PublicKeyIsInvalid)?) + .map_err(|_| Error::PublicKeyIsInvalid)?; + // 72 should be enough in all cases. 2 + 2 x (32 + 3) + let mut asn1 = alloc::vec![0u8; 72]; + let mut writer = der::SliceWriter::new(&mut asn1); + writer + .encode(&sequence) + .map_err(|_| Error::DerEncodingError)?; + Ok(writer + .finish() + .map_err(|_| Error::DerEncodingError)? + .to_vec()) +} + +/// Verifies that the `leaf_cert` in combination with the `intermediate_certs` establishes +/// a valid certificate chain that is rooted in one of the trust anchors that was compiled into to the pallet +pub fn verify_certificate_chain( + leaf_cert: &webpki::EndEntityCert, + intermediate_certs: &[CertificateDer], + verification_time: u64, +) -> Result<(), Error> { + let time = webpki::types::UnixTime::since_unix_epoch(core::time::Duration::from_secs( + verification_time / 1000, + )); + let sig_algs = &[webpki::ring::ECDSA_P256_SHA256]; + leaf_cert + .verify_for_usage( + sig_algs, + DCAP_SERVER_ROOTS, + intermediate_certs, + time, + webpki::KeyUsage::server_auth(), + None, + None, + ) + .map_err(|_e| Error::CertificateChainIsInvalid)?; + + Ok(()) +} diff --git a/modules/dcap-qvl/src/verify.rs b/modules/dcap-qvl/src/verify.rs new file mode 100644 index 00000000..63349c90 --- /dev/null +++ b/modules/dcap-qvl/src/verify.rs @@ -0,0 +1,188 @@ +use scale::Decode; + +use { + crate::constants::*, crate::tcb_info::TcbInfo, alloc::borrow::ToOwned, alloc::string::String, + alloc::vec::Vec, +}; + +pub use crate::quote::{AuthData, EnclaveReport, Quote}; +use crate::{ + quote::Report, + utils::{self, encode_as_der, extract_certs, verify_certificate_chain}, +}; +use crate::{Error, QuoteCollateralV3}; + +#[derive(Debug, Clone)] +pub struct VerifiedReport { + pub status: String, + pub advisory_ids: Vec, + pub report: Report, +} + +/// Verify a quote +/// +/// # Arguments +/// +/// * `raw_quote` - The raw quote to verify. Supported SGX and TDX quotes. +/// * `quote_collateral` - The quote collateral to verify. Can be obtained from PCCS by `get_collateral`. +/// * `now` - The current time in seconds since the Unix epoch +/// +/// # Returns +/// +/// * `Ok(VerifiedReport)` - The verified report +/// * `Err(Error)` - The error +pub fn verify( + raw_quote: &[u8], + quote_collateral: &QuoteCollateralV3, + now: u64, +) -> Result { + // Parse data + let mut quote = raw_quote; + let quote = Quote::decode(&mut quote).map_err(|_| Error::CodecError)?; + let signed_quote_len = quote.signed_length(); + + let tcb_info = serde_json::from_str::("e_collateral.tcb_info) + .map_err(|_| Error::CodecError)?; + + let next_update = chrono::DateTime::parse_from_rfc3339(&tcb_info.next_update) + .map_err(|_| Error::CodecError)?; + if now > next_update.timestamp() as u64 { + return Err(Error::TCBInfoExpired); + } + + let now_in_milli = now * 1000; + + // Verify enclave + + // Seems we verify MR_ENCLAVE and MR_SIGNER is enough + // skip verify_misc_select_field + // skip verify_attributes_field + + // Verify integrity + + // Check TCB info cert chain and signature + let leaf_certs = extract_certs(quote_collateral.tcb_info_issuer_chain.as_bytes())?; + if leaf_certs.len() < 2 { + return Err(Error::CertificateChainIsTooShort); + } + let leaf_cert: webpki::EndEntityCert = webpki::EndEntityCert::try_from(&leaf_certs[0]) + .map_err(|_| Error::LeafCertificateParsingError)?; + let intermediate_certs = &leaf_certs[1..]; + verify_certificate_chain(&leaf_cert, intermediate_certs, now_in_milli)?; + let asn1_signature = encode_as_der("e_collateral.tcb_info_signature)?; + if leaf_cert + .verify_signature( + webpki::ring::ECDSA_P256_SHA256, + quote_collateral.tcb_info.as_bytes(), + &asn1_signature, + ) + .is_err() + { + return Err(Error::RsaSignatureIsInvalid); + } + + // Check quote fields + if ![3, 4, 5].contains("e.header.version) { + return Err(Error::UnsupportedDCAPQuoteVersion); + } + // We only support ECDSA256 with P256 curve + if quote.header.attestation_key_type != ATTESTATION_KEY_TYPE_ECDSA256_WITH_P256_CURVE { + return Err(Error::UnsupportedDCAPAttestationKeyType); + } + + // Extract Auth data from quote + let auth_data = quote.auth_data.into_v3(); + let certification_data = auth_data.certification_data; + + // We only support 5 -Concatenated PCK Cert Chain (PEM formatted). + if certification_data.cert_type != PCK_CERT_CHAIN { + return Err(Error::UnsupportedDCAPPckCertFormat); + } + + let certification_certs = extract_certs(&certification_data.body.data)?; + if certification_certs.len() < 2 { + return Err(Error::CertificateChainIsTooShort); + } + // Check certification_data + let leaf_cert: webpki::EndEntityCert = webpki::EndEntityCert::try_from(&certification_certs[0]) + .map_err(|_| Error::LeafCertificateParsingError)?; + let intermediate_certs = &certification_certs[1..]; + verify_certificate_chain(&leaf_cert, intermediate_certs, now_in_milli)?; + + // Check QE signature + let asn1_signature = encode_as_der(&auth_data.qe_report_signature)?; + if leaf_cert + .verify_signature( + webpki::ring::ECDSA_P256_SHA256, + &auth_data.qe_report, + &asn1_signature, + ) + .is_err() + { + return Err(Error::RsaSignatureIsInvalid); + } + + // Extract QE report from quote + let mut qe_report = auth_data.qe_report.as_slice(); + let qe_report = EnclaveReport::decode(&mut qe_report).map_err(|_err| Error::CodecError)?; + + // Check QE hash + let mut qe_hash_data = [0u8; QE_HASH_DATA_BYTE_LEN]; + qe_hash_data[0..ATTESTATION_KEY_LEN].copy_from_slice(&auth_data.ecdsa_attestation_key); + qe_hash_data[ATTESTATION_KEY_LEN..].copy_from_slice(&auth_data.qe_auth_data.data); + let qe_hash = ring::digest::digest(&ring::digest::SHA256, &qe_hash_data); + if qe_hash.as_ref() != &qe_report.report_data[0..32] { + return Err(Error::QEReportHashMismatch); + } + + // Check signature from auth data + let mut pub_key = [0x04u8; 65]; //Prepend 0x04 to specify uncompressed format + pub_key[1..].copy_from_slice(&auth_data.ecdsa_attestation_key); + let peer_public_key = + ring::signature::UnparsedPublicKey::new(&ring::signature::ECDSA_P256_SHA256_FIXED, pub_key); + peer_public_key + .verify( + raw_quote.get(..signed_quote_len).ok_or(Error::CodecError)?, + &auth_data.ecdsa_signature, + ) + .map_err(|_| Error::IsvEnclaveReportSignatureIsInvalid)?; + + // Extract information from the quote + + let extension_section = utils::get_intel_extension(&certification_certs[0])?; + let cpu_svn = utils::get_cpu_svn(&extension_section)?; + let pce_svn = utils::get_pce_svn(&extension_section)?; + let fmspc = utils::get_fmspc(&extension_section)?; + + let tcb_fmspc = hex::decode(&tcb_info.fmspc).map_err(|_| Error::CodecError)?; + if fmspc != tcb_fmspc[..] { + return Err(Error::FmspcMismatch); + } + + // TCB status and advisory ids + let mut tcb_status = "Unknown".to_owned(); + let mut advisory_ids = Vec::::new(); + for tcb_level in &tcb_info.tcb_levels { + if pce_svn >= tcb_level.tcb.pce_svn { + if cpu_svn + .iter() + .zip(&tcb_level.tcb.components) + .any(|(a, b)| a < &b.svn) + { + continue; + } + + tcb_status = tcb_level.tcb_status.clone(); + tcb_level + .advisory_ids + .iter() + .for_each(|id| advisory_ids.push(id.clone())); + break; + } + } + Ok(VerifiedReport { + status: tcb_status, + advisory_ids, + report: quote.report, + }) +} diff --git a/modules/dcap-qvl/tests/snapshots/verify_quote__could_parse_sgx_quote.snap b/modules/dcap-qvl/tests/snapshots/verify_quote__could_parse_sgx_quote.snap new file mode 100644 index 00000000..8dafbbc7 --- /dev/null +++ b/modules/dcap-qvl/tests/snapshots/verify_quote__could_parse_sgx_quote.snap @@ -0,0 +1,1084 @@ +--- +source: tests/verify_quote.rs +assertion_line: 11 +expression: quote +--- +Quote { + header: Header { + version: 3, + attestation_key_type: 2, + tee_type: 0, + qe_svn: 10, + pce_svn: 15, + qe_vendor_id: [ + 147, + 154, + 114, + 51, + 247, + 156, + 76, + 169, + 148, + 10, + 13, + 179, + 149, + 127, + 6, + 7, + ], + user_data: [ + 57, + 135, + 98, + 46, + 230, + 150, + 138, + 84, + 151, + 124, + 134, + 38, + 239, + 71, + 18, + 53, + 0, + 0, + 0, + 0, + ], + }, + report: SgxEnclave( + EnclaveReport { + cpu_svn: [ + 11, + 11, + 26, + 24, + 255, + 255, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + misc_select: 0, + reserved1: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + attributes: [ + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 231, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + mr_enclave: [ + 51, + 216, + 115, + 109, + 183, + 86, + 237, + 73, + 151, + 224, + 75, + 163, + 88, + 210, + 120, + 51, + 24, + 143, + 25, + 50, + 255, + 123, + 29, + 21, + 105, + 4, + 211, + 245, + 96, + 69, + 47, + 187, + ], + reserved2: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + mr_signer: [ + 129, + 95, + 66, + 241, + 28, + 246, + 68, + 48, + 195, + 11, + 171, + 120, + 22, + 186, + 89, + 106, + 29, + 160, + 19, + 12, + 59, + 2, + 139, + 103, + 49, + 51, + 166, + 108, + 249, + 163, + 224, + 230, + ], + reserved3: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + isv_prod_id: 0, + isv_svn: 0, + reserved4: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + report_data: [ + 72, + 101, + 108, + 108, + 111, + 44, + 32, + 119, + 111, + 114, + 108, + 100, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + }, + ), + auth_data: V3( + AuthDataV3 { + ecdsa_signature: [ + 109, + 221, + 149, + 2, + 163, + 9, + 61, + 34, + 191, + 41, + 207, + 6, + 98, + 214, + 233, + 82, + 252, + 126, + 159, + 64, + 72, + 44, + 208, + 222, + 108, + 33, + 129, + 105, + 175, + 247, + 246, + 137, + 41, + 77, + 5, + 24, + 237, + 66, + 133, + 101, + 54, + 133, + 233, + 250, + 254, + 64, + 100, + 59, + 69, + 137, + 178, + 25, + 7, + 182, + 76, + 252, + 148, + 39, + 186, + 84, + 35, + 145, + 45, + 119, + ], + ecdsa_attestation_key: [ + 220, + 226, + 185, + 31, + 236, + 210, + 250, + 37, + 84, + 109, + 65, + 193, + 213, + 12, + 109, + 33, + 226, + 138, + 224, + 68, + 33, + 83, + 208, + 146, + 165, + 5, + 253, + 75, + 2, + 185, + 189, + 57, + 82, + 230, + 233, + 12, + 36, + 5, + 211, + 227, + 73, + 238, + 241, + 253, + 88, + 80, + 132, + 14, + 43, + 232, + 59, + 196, + 254, + 101, + 145, + 113, + 214, + 21, + 8, + 95, + 114, + 213, + 123, + 127, + ], + qe_report: [ + 11, + 11, + 26, + 24, + 255, + 255, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 21, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 231, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 150, + 179, + 71, + 166, + 78, + 90, + 4, + 94, + 39, + 54, + 156, + 38, + 230, + 220, + 218, + 81, + 253, + 124, + 133, + 14, + 155, + 58, + 58, + 121, + 231, + 24, + 244, + 50, + 97, + 222, + 225, + 228, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 140, + 79, + 87, + 117, + 215, + 150, + 80, + 62, + 150, + 19, + 127, + 119, + 198, + 138, + 130, + 154, + 0, + 86, + 172, + 141, + 237, + 112, + 20, + 11, + 8, + 27, + 9, + 68, + 144, + 197, + 123, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 194, + 97, + 187, + 136, + 46, + 84, + 42, + 168, + 215, + 249, + 233, + 154, + 0, + 239, + 203, + 17, + 207, + 46, + 230, + 111, + 169, + 198, + 134, + 31, + 146, + 48, + 211, + 248, + 3, + 162, + 117, + 253, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + qe_report_signature: [ + 191, + 176, + 167, + 89, + 204, + 134, + 78, + 136, + 25, + 241, + 183, + 210, + 106, + 189, + 231, + 118, + 49, + 129, + 110, + 36, + 205, + 192, + 47, + 36, + 170, + 152, + 111, + 212, + 7, + 204, + 131, + 152, + 69, + 206, + 21, + 186, + 124, + 42, + 235, + 14, + 109, + 22, + 136, + 218, + 25, + 245, + 163, + 146, + 197, + 12, + 5, + 175, + 140, + 108, + 79, + 98, + 45, + 8, + 234, + 22, + 183, + 183, + 43, + 71, + ], + qe_auth_data: Data { + data: [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + ], + _marker: PhantomData, + }, + certification_data: CertificationData { + cert_type: 5, + body: "-----BEGIN CERTIFICATE-----\nMIIEjTCCBDSgAwIBAgIVAIG3dzK3YemOubljpKvR5bm/XdjWMAoGCCqGSM49BAMC\nMHExIzAhBgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQK\nDBFJbnRlbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNV\nBAgMAkNBMQswCQYDVQQGEwJVUzAeFw0yMzA5MjAyMTUzNDNaFw0zMDA5MjAyMTUz\nNDNaMHAxIjAgBgNVBAMMGUludGVsIFNHWCBQQ0sgQ2VydGlmaWNhdGUxGjAYBgNV\nBAoMEUludGVsIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkG\nA1UECAwCQ0ExCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE\nkgmE7N3D+RspyaCZ2YoDTLDCuh5pnvAu4crPn2uAGujq9tOgwU8/y7jttShCB603\nU6r+h9ayOk2nZ9jewk25lqOCAqgwggKkMB8GA1UdIwQYMBaAFNDoqtp11/kuSReY\nPHsUZdDV8llNMGwGA1UdHwRlMGMwYaBfoF2GW2h0dHBzOi8vYXBpLnRydXN0ZWRz\nZXJ2aWNlcy5pbnRlbC5jb20vc2d4L2NlcnRpZmljYXRpb24vdjQvcGNrY3JsP2Nh\nPXByb2Nlc3NvciZlbmNvZGluZz1kZXIwHQYDVR0OBBYEFIW4KX263PRxYJah2Cfj\nAlrcvAC9MA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMIIB1AYJKoZIhvhN\nAQ0BBIIBxTCCAcEwHgYKKoZIhvhNAQ0BAQQQ0E7AbU5tktyQ0K089e4t3zCCAWQG\nCiqGSIb4TQENAQIwggFUMBAGCyqGSIb4TQENAQIBAgELMBAGCyqGSIb4TQENAQIC\nAgELMBAGCyqGSIb4TQENAQIDAgECMBAGCyqGSIb4TQENAQIEAgECMBEGCyqGSIb4\nTQENAQIFAgIA/zAQBgsqhkiG+E0BDQECBgIBATAQBgsqhkiG+E0BDQECBwIBADAQ\nBgsqhkiG+E0BDQECCAIBADAQBgsqhkiG+E0BDQECCQIBADAQBgsqhkiG+E0BDQEC\nCgIBADAQBgsqhkiG+E0BDQECCwIBADAQBgsqhkiG+E0BDQECDAIBADAQBgsqhkiG\n+E0BDQECDQIBADAQBgsqhkiG+E0BDQECDgIBADAQBgsqhkiG+E0BDQECDwIBADAQ\nBgsqhkiG+E0BDQECEAIBADAQBgsqhkiG+E0BDQECEQIBDTAfBgsqhkiG+E0BDQEC\nEgQQCwsCAv8BAAAAAAAAAAAAADAQBgoqhkiG+E0BDQEDBAIAADAUBgoqhkiG+E0B\nDQEEBAYAoGcRAAAwDwYKKoZIhvhNAQ0BBQoBADAKBggqhkjOPQQDAgNHADBEAiBm\nSMZEtlQEjnZgGa192W3ArnZ3iyY6ckM/sTsXxCRmJgIgLf20tZHNw3a1b31JDSOW\nE6wesxoAmTeqJGRqZl621qI=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICmDCCAj6gAwIBAgIVANDoqtp11/kuSReYPHsUZdDV8llNMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHExIzAh\nBgNVBAMMGkludGVsIFNHWCBQQ0sgUHJvY2Vzc29yIENBMRowGAYDVQQKDBFJbnRl\nbCBDb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNB\nMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABL9q+NMp2IOg\ntdl1bk/uWZ5+TGQm8aCi8z78fs+fKCQ3d+uDzXnVTAT2ZhDCifyIuJwvN3wNBp9i\nHBSSMJMJrBOjgbswgbgwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqww\nUgYDVR0fBEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNl\ncnZpY2VzLmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFNDo\nqtp11/kuSReYPHsUZdDV8llNMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEAMAoGCCqGSM49BAMCA0gAMEUCIQCJgTbtVqOyZ1m3jqiAXM6QYa6r5sWS\n4y/G7y8uIJGxdwIgRqPvBSKzzQagBLQq5s5A70pdoiaRJ8z/0uDz4NgV91k=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0", + }, + }, + ), +} diff --git a/modules/dcap-qvl/tests/snapshots/verify_quote__could_parse_tdx_quote.snap b/modules/dcap-qvl/tests/snapshots/verify_quote__could_parse_tdx_quote.snap new file mode 100644 index 00000000..3841fb66 --- /dev/null +++ b/modules/dcap-qvl/tests/snapshots/verify_quote__could_parse_tdx_quote.snap @@ -0,0 +1,1307 @@ +--- +source: tests/verify_quote.rs +assertion_line: 27 +expression: quote +--- +Quote { + header: Header { + version: 4, + attestation_key_type: 2, + tee_type: 129, + qe_svn: 0, + pce_svn: 0, + qe_vendor_id: [ + 147, + 154, + 114, + 51, + 247, + 156, + 76, + 169, + 148, + 10, + 13, + 179, + 149, + 127, + 6, + 7, + ], + user_data: [ + 131, + 251, + 254, + 97, + 82, + 95, + 85, + 88, + 19, + 21, + 205, + 157, + 201, + 80, + 244, + 71, + 0, + 0, + 0, + 0, + ], + }, + report: TD10( + TDReport10 { + tee_tcb_svn: [ + 5, + 1, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + mr_seam: [ + 28, + 198, + 161, + 122, + 183, + 153, + 233, + 166, + 147, + 250, + 199, + 83, + 107, + 230, + 28, + 18, + 238, + 30, + 15, + 171, + 173, + 168, + 45, + 12, + 153, + 158, + 8, + 204, + 238, + 42, + 168, + 109, + 231, + 123, + 8, + 112, + 245, + 88, + 197, + 112, + 231, + 255, + 229, + 93, + 109, + 71, + 250, + 4, + ], + mr_signer_seam: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + seam_attributes: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + td_attributes: [ + 0, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + ], + xfam: [ + 231, + 2, + 6, + 0, + 0, + 0, + 0, + 0, + ], + mr_td: [ + 145, + 235, + 43, + 68, + 209, + 65, + 212, + 236, + 224, + 159, + 12, + 117, + 194, + 197, + 61, + 36, + 122, + 60, + 104, + 237, + 215, + 250, + 254, + 138, + 53, + 32, + 201, + 66, + 166, + 4, + 164, + 7, + 222, + 3, + 174, + 109, + 197, + 248, + 127, + 39, + 66, + 139, + 37, + 56, + 135, + 49, + 24, + 183, + ], + mr_config_id: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + mr_owner: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + mr_owner_config: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + rt_mr0: [ + 78, + 221, + 168, + 174, + 224, + 242, + 193, + 147, + 97, + 190, + 135, + 160, + 181, + 132, + 145, + 69, + 183, + 84, + 140, + 132, + 203, + 108, + 119, + 70, + 52, + 72, + 43, + 130, + 96, + 238, + 213, + 52, + 59, + 44, + 86, + 132, + 95, + 72, + 194, + 2, + 236, + 211, + 80, + 109, + 108, + 164, + 181, + 159, + ], + rt_mr1: [ + 59, + 2, + 109, + 186, + 196, + 201, + 127, + 110, + 119, + 17, + 152, + 182, + 251, + 210, + 152, + 81, + 45, + 247, + 70, + 119, + 237, + 110, + 63, + 10, + 151, + 101, + 113, + 186, + 173, + 180, + 193, + 233, + 31, + 61, + 29, + 1, + 255, + 198, + 81, + 54, + 41, + 111, + 13, + 156, + 20, + 220, + 108, + 205, + ], + rt_mr2: [ + 86, + 151, + 85, + 201, + 125, + 87, + 45, + 155, + 162, + 222, + 154, + 101, + 94, + 158, + 120, + 106, + 225, + 203, + 63, + 115, + 210, + 139, + 96, + 71, + 215, + 150, + 120, + 204, + 226, + 64, + 54, + 173, + 186, + 159, + 176, + 128, + 84, + 126, + 132, + 178, + 236, + 152, + 145, + 0, + 50, + 130, + 141, + 221, + ], + rt_mr3: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + report_data: [ + 35, + 32, + 126, + 47, + 46, + 98, + 97, + 115, + 104, + 114, + 99, + 58, + 32, + 101, + 120, + 101, + 99, + 117, + 116, + 101, + 100, + 32, + 98, + 121, + 32, + 98, + 97, + 115, + 104, + 40, + 49, + 41, + 32, + 102, + 111, + 114, + 32, + 110, + 111, + 110, + 45, + 108, + 111, + 103, + 105, + 110, + 32, + 115, + 104, + 101, + 108, + 108, + 115, + 46, + 10, + 35, + 32, + 115, + 101, + 101, + 32, + 47, + 117, + 115, + ], + }, + ), + auth_data: V4( + AuthDataV4 { + ecdsa_signature: [ + 19, + 2, + 132, + 124, + 125, + 42, + 52, + 0, + 120, + 91, + 169, + 41, + 119, + 116, + 162, + 113, + 200, + 191, + 245, + 94, + 60, + 117, + 219, + 198, + 36, + 66, + 45, + 71, + 174, + 253, + 38, + 86, + 164, + 95, + 56, + 9, + 41, + 134, + 11, + 98, + 213, + 194, + 98, + 187, + 95, + 188, + 19, + 159, + 160, + 25, + 55, + 61, + 223, + 233, + 246, + 113, + 158, + 0, + 226, + 17, + 236, + 139, + 170, + 146, + ], + ecdsa_attestation_key: [ + 73, + 150, + 169, + 229, + 110, + 64, + 172, + 108, + 11, + 1, + 151, + 9, + 83, + 127, + 22, + 215, + 81, + 192, + 62, + 140, + 13, + 144, + 93, + 121, + 242, + 36, + 255, + 6, + 221, + 196, + 16, + 40, + 96, + 168, + 119, + 1, + 7, + 116, + 140, + 1, + 28, + 219, + 252, + 204, + 200, + 87, + 228, + 24, + 115, + 91, + 105, + 154, + 200, + 157, + 194, + 237, + 77, + 161, + 29, + 81, + 37, + 203, + 146, + 94, + ], + certification_data: CertificationData { + cert_type: 6, + body: "\u{2}\u{2}\u{19}\u{1b}\u{3}�\0\u{6}\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\u{15}\0\0\0\0\0\0\0�\0\0\0\0\0\0\0壧��0\u{95};�SLlY��O�4�3����\n��\u{8}�k�\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ܞ*|o��\u{17}GN4��C�\u{3}\u{f}|\u{15}c��c@�.\u{e}T��\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\u{2}\0\u{6}\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0P;���U�>!t|8Y�\u{18}�P1*\u{3}@�\u{18}~�##V�\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\"o�y��y\\�\u{5c5}\u{e}a�A��2\u{14}�2㩠מ��u��G��\u{7}\u{4}��\u{6}ڎ\tb.\u{12}\0��?n&�ხ�%\u{19}\n��P\u{12}+ \0\0\u{1}\u{2}\u{3}\u{4}\u{5}\u{6}\u{7}\u{8}\t\n\u{b}\u{c}\r\u{e}\u{f}\u{10}\u{11}\u{12}\u{13}\u{14}\u{15}\u{16}\u{17}\u{18}\u{19}\u{1a}\u{1b}\u{1c}\u{1d}\u{1e}\u{1f}\u{5}\0^\u{e}\0\0-----BEGIN CERTIFICATE-----\nMIIE8DCCBJegAwIBAgIVALR5TIT9+9nsB1BTZ1srXQ4lbwRBMAoGCCqGSM49BAMC\nMHAxIjAgBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoM\nEUludGVsIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UE\nCAwCQ0ExCzAJBgNVBAYTAlVTMB4XDTI0MDgwMjExMTUzN1oXDTMxMDgwMjExMTUz\nN1owcDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBDZXJ0aWZpY2F0ZTEaMBgGA1UE\nCgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYD\nVQQIDAJDQTELMAkGA1UEBhMCVVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATY\nwwqU4GxPJjYojMGRha62yp4jBQd5WDvKwmT6ll1AGxjY68piJPgiPhdb8zTGf7Kb\n1Oyd1SFOMZpYLyPTBzYdo4IDDDCCAwgwHwYDVR0jBBgwFoAUlW9dzb0b4elAScnU\n9DPOAVcL3lQwawYDVR0fBGQwYjBgoF6gXIZaaHR0cHM6Ly9hcGkudHJ1c3RlZHNl\ncnZpY2VzLmludGVsLmNvbS9zZ3gvY2VydGlmaWNhdGlvbi92NC9wY2tjcmw/Y2E9\ncGxhdGZvcm0mZW5jb2Rpbmc9ZGVyMB0GA1UdDgQWBBQF04vPvTGKwbAl5oTvVdfM\n+5jnuTAOBgNVHQ8BAf8EBAMCBsAwDAYDVR0TAQH/BAIwADCCAjkGCSqGSIb4TQEN\nAQSCAiowggImMB4GCiqGSIb4TQENAQEEEN5dAoq5cK5n82w9oy1e4n4wggFjBgoq\nhkiG+E0BDQECMIIBUzAQBgsqhkiG+E0BDQECAQIBAjAQBgsqhkiG+E0BDQECAgIB\nAjAQBgsqhkiG+E0BDQECAwIBAjAQBgsqhkiG+E0BDQECBAIBAjAQBgsqhkiG+E0B\nDQECBQIBAzAQBgsqhkiG+E0BDQECBgIBATAQBgsqhkiG+E0BDQECBwIBADAQBgsq\nhkiG+E0BDQECCAIBAzAQBgsqhkiG+E0BDQECCQIBADAQBgsqhkiG+E0BDQECCgIB\nADAQBgsqhkiG+E0BDQECCwIBADAQBgsqhkiG+E0BDQECDAIBADAQBgsqhkiG+E0B\nDQECDQIBADAQBgsqhkiG+E0BDQECDgIBADAQBgsqhkiG+E0BDQECDwIBADAQBgsq\nhkiG+E0BDQECEAIBADAQBgsqhkiG+E0BDQECEQIBCzAfBgsqhkiG+E0BDQECEgQQ\nAgICAgMBAAMAAAAAAAAAADAQBgoqhkiG+E0BDQEDBAIAADAUBgoqhkiG+E0BDQEE\nBAawwG8AAAAwDwYKKoZIhvhNAQ0BBQoBATAeBgoqhkiG+E0BDQEGBBBJ1drhSIsm\nh+/Fy0ttjjv/MEQGCiqGSIb4TQENAQcwNjAQBgsqhkiG+E0BDQEHAQEB/zAQBgsq\nhkiG+E0BDQEHAgEB/zAQBgsqhkiG+E0BDQEHAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBpEW8uOrkStiHkLKnjBhUAocz9TW36jN/07eAhDP65awIgM/1GLXtZpDd6paPv\nSZ8mNtrT800V54kFYDGOzOxPCt8=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0", + }, + qe_report_data: QEReportCertificationData { + qe_report: [ + 2, + 2, + 25, + 27, + 3, + 255, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 21, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 231, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 229, + 163, + 167, + 181, + 216, + 48, + 194, + 149, + 59, + 152, + 83, + 76, + 108, + 89, + 163, + 163, + 79, + 220, + 52, + 233, + 51, + 247, + 245, + 137, + 143, + 10, + 133, + 207, + 8, + 132, + 107, + 202, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 220, + 158, + 42, + 124, + 111, + 148, + 143, + 23, + 71, + 78, + 52, + 167, + 252, + 67, + 237, + 3, + 15, + 124, + 21, + 99, + 241, + 186, + 189, + 223, + 99, + 64, + 200, + 46, + 14, + 84, + 168, + 197, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 80, + 59, + 191, + 229, + 190, + 250, + 85, + 161, + 62, + 33, + 116, + 124, + 56, + 89, + 240, + 182, + 24, + 160, + 80, + 49, + 42, + 3, + 64, + 233, + 128, + 24, + 126, + 234, + 35, + 35, + 86, + 214, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + qe_report_signature: [ + 34, + 111, + 248, + 121, + 178, + 239, + 121, + 92, + 156, + 215, + 133, + 14, + 97, + 239, + 65, + 182, + 206, + 50, + 20, + 165, + 50, + 227, + 169, + 160, + 215, + 158, + 255, + 167, + 117, + 235, + 255, + 71, + 137, + 163, + 7, + 4, + 252, + 243, + 6, + 218, + 142, + 9, + 98, + 46, + 18, + 0, + 222, + 251, + 63, + 110, + 38, + 204, + 225, + 131, + 174, + 174, + 37, + 25, + 10, + 241, + 222, + 80, + 18, + 43, + ], + qe_auth_data: Data { + data: [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + ], + _marker: PhantomData, + }, + certification_data: CertificationData { + cert_type: 5, + body: "-----BEGIN CERTIFICATE-----\nMIIE8DCCBJegAwIBAgIVALR5TIT9+9nsB1BTZ1srXQ4lbwRBMAoGCCqGSM49BAMC\nMHAxIjAgBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoM\nEUludGVsIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UE\nCAwCQ0ExCzAJBgNVBAYTAlVTMB4XDTI0MDgwMjExMTUzN1oXDTMxMDgwMjExMTUz\nN1owcDEiMCAGA1UEAwwZSW50ZWwgU0dYIFBDSyBDZXJ0aWZpY2F0ZTEaMBgGA1UE\nCgwRSW50ZWwgQ29ycG9yYXRpb24xFDASBgNVBAcMC1NhbnRhIENsYXJhMQswCQYD\nVQQIDAJDQTELMAkGA1UEBhMCVVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATY\nwwqU4GxPJjYojMGRha62yp4jBQd5WDvKwmT6ll1AGxjY68piJPgiPhdb8zTGf7Kb\n1Oyd1SFOMZpYLyPTBzYdo4IDDDCCAwgwHwYDVR0jBBgwFoAUlW9dzb0b4elAScnU\n9DPOAVcL3lQwawYDVR0fBGQwYjBgoF6gXIZaaHR0cHM6Ly9hcGkudHJ1c3RlZHNl\ncnZpY2VzLmludGVsLmNvbS9zZ3gvY2VydGlmaWNhdGlvbi92NC9wY2tjcmw/Y2E9\ncGxhdGZvcm0mZW5jb2Rpbmc9ZGVyMB0GA1UdDgQWBBQF04vPvTGKwbAl5oTvVdfM\n+5jnuTAOBgNVHQ8BAf8EBAMCBsAwDAYDVR0TAQH/BAIwADCCAjkGCSqGSIb4TQEN\nAQSCAiowggImMB4GCiqGSIb4TQENAQEEEN5dAoq5cK5n82w9oy1e4n4wggFjBgoq\nhkiG+E0BDQECMIIBUzAQBgsqhkiG+E0BDQECAQIBAjAQBgsqhkiG+E0BDQECAgIB\nAjAQBgsqhkiG+E0BDQECAwIBAjAQBgsqhkiG+E0BDQECBAIBAjAQBgsqhkiG+E0B\nDQECBQIBAzAQBgsqhkiG+E0BDQECBgIBATAQBgsqhkiG+E0BDQECBwIBADAQBgsq\nhkiG+E0BDQECCAIBAzAQBgsqhkiG+E0BDQECCQIBADAQBgsqhkiG+E0BDQECCgIB\nADAQBgsqhkiG+E0BDQECCwIBADAQBgsqhkiG+E0BDQECDAIBADAQBgsqhkiG+E0B\nDQECDQIBADAQBgsqhkiG+E0BDQECDgIBADAQBgsqhkiG+E0BDQECDwIBADAQBgsq\nhkiG+E0BDQECEAIBADAQBgsqhkiG+E0BDQECEQIBCzAfBgsqhkiG+E0BDQECEgQQ\nAgICAgMBAAMAAAAAAAAAADAQBgoqhkiG+E0BDQEDBAIAADAUBgoqhkiG+E0BDQEE\nBAawwG8AAAAwDwYKKoZIhvhNAQ0BBQoBATAeBgoqhkiG+E0BDQEGBBBJ1drhSIsm\nh+/Fy0ttjjv/MEQGCiqGSIb4TQENAQcwNjAQBgsqhkiG+E0BDQEHAQEB/zAQBgsq\nhkiG+E0BDQEHAgEB/zAQBgsqhkiG+E0BDQEHAwEB/zAKBggqhkjOPQQDAgNHADBE\nAiBpEW8uOrkStiHkLKnjBhUAocz9TW36jN/07eAhDP65awIgM/1GLXtZpDd6paPv\nSZ8mNtrT800V54kFYDGOzOxPCt8=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICljCCAj2gAwIBAgIVAJVvXc29G+HpQEnJ1PQzzgFXC95UMAoGCCqGSM49BAMC\nMGgxGjAYBgNVBAMMEUludGVsIFNHWCBSb290IENBMRowGAYDVQQKDBFJbnRlbCBD\nb3Jwb3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQsw\nCQYDVQQGEwJVUzAeFw0xODA1MjExMDUwMTBaFw0zMzA1MjExMDUwMTBaMHAxIjAg\nBgNVBAMMGUludGVsIFNHWCBQQ0sgUGxhdGZvcm0gQ0ExGjAYBgNVBAoMEUludGVs\nIENvcnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0Ex\nCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENSB/7t21lXSO\n2Cuzpxw74eJB72EyDGgW5rXCtx2tVTLq6hKk6z+UiRZCnqR7psOvgqFeSxlmTlJl\neTmi2WYz3qOBuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBS\nBgNVHR8ESzBJMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2Vy\ndmljZXMuaW50ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUlW9d\nzb0b4elAScnU9DPOAVcL3lQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB\nAf8CAQAwCgYIKoZIzj0EAwIDRwAwRAIgXsVki0w+i6VYGW3UF/22uaXe0YJDj1Ue\nnA+TjD1ai5cCICYb1SAmD5xkfTVpvo4UoyiSYxrDWLmUR4CI9NKyfPN+\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n\0", + }, + }, + }, + ), +} diff --git a/modules/dcap-qvl/tests/verify_quote.rs b/modules/dcap-qvl/tests/verify_quote.rs new file mode 100644 index 00000000..cb6aed4b --- /dev/null +++ b/modules/dcap-qvl/tests/verify_quote.rs @@ -0,0 +1,37 @@ +// use dcap_qvl::{quote::Quote, verify::verify, QuoteCollateralV3}; +// use scale::Decode; + +// #[test] +// fn could_parse_sgx_quote() { +// let raw_quote = include_bytes!("../sample/sgx_quote").to_vec(); +// let raw_quote_collateral = include_bytes!("../sample/sgx_quote_collateral").to_vec(); +// let now = 1699301000u64; + +// let quote = Quote::decode(&mut &raw_quote[..]).unwrap(); +// insta::assert_debug_snapshot!(quote); + +// let quote_collateral = +// QuoteCollateralV3::decode(&mut raw_quote_collateral.as_slice()).expect("decodable"); +// let tcb_status = verify(&raw_quote, "e_collateral, now).expect("verify"); + +// assert_eq!(tcb_status.status, "ConfigurationAndSWHardeningNeeded"); +// assert_eq!( +// tcb_status.advisory_ids, +// ["INTEL-SA-00289", "INTEL-SA-00615"] +// ); +// } + +// #[test] +// fn could_parse_tdx_quote() { +// let raw_quote = include_bytes!("../sample/tdx_quote"); +// let raw_quote_collateral = include_bytes!("../sample/tdx_quote_collateral"); +// let now = 1725258675u64; + +// let quote = Quote::decode(&mut &raw_quote[..]).unwrap(); +// insta::assert_debug_snapshot!(quote); + +// let quote_collateral = QuoteCollateralV3::decode(&mut raw_quote_collateral.as_slice()).unwrap(); +// let tcb_status = verify(raw_quote, "e_collateral, now).unwrap(); +// assert_eq!(tcb_status.status, "UpToDate"); +// assert!(tcb_status.advisory_ids.is_empty()); +// } diff --git a/modules/keymanager/src/lib.rs b/modules/keymanager/src/lib.rs index d4b04bcc..b0722374 100644 --- a/modules/keymanager/src/lib.rs +++ b/modules/keymanager/src/lib.rs @@ -1,7 +1,7 @@ pub mod errors; pub use crate::errors::Error; use anyhow::anyhow; -use attestation_report::{ReportData, SignedAttestationVerificationReport}; +use attestation_report::{IASSignedReport, ReportData, VerifiableQuote}; use crypto::{Address, SealedEnclaveKey}; use lcp_types::{ deserialize_bytes, proto::lcp::service::enclave::v1::EnclaveKeyInfo as ProtoEnclaveKeyInfo, @@ -55,7 +55,8 @@ impl EnclaveKeyManager { ek_sealed BLOB NOT NULL, mrenclave TEXT NOT NULL, report BLOB NOT NULL, - signed_avr TEXT, + ias_report TEXT, + dcap_quote TEXT, attested_at TEXT, created_at TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')), updated_at TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')) @@ -75,7 +76,7 @@ impl EnclaveKeyManager { .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - SELECT ek_sealed, mrenclave, report, signed_avr + SELECT ek_sealed, mrenclave, report, ias_report FROM enclave_keys WHERE ek_address = ?1 "#, @@ -105,17 +106,15 @@ impl EnclaveKeyManager { anyhow!("report: {:?}", e).into(), ) })?, - signed_avr: match row.get::<_, Option>(3) { + ias_report: match row.get::<_, Option>(3) { Ok(None) => None, - Ok(Some(avr)) => Some( - SignedAttestationVerificationReport::from_json(&avr).map_err(|e| { - rusqlite::Error::FromSqlConversionFailure( - 3, - Type::Text, - anyhow!("signed_avr: {:?}", e).into(), - ) - })?, - ), + Ok(Some(avr)) => Some(IASSignedReport::from_json(&avr).map_err(|e| { + rusqlite::Error::FromSqlConversionFailure( + 3, + Type::Text, + anyhow!("ias_report: {:?}", e).into(), + ) + })?), Err(e) => return Err(e), }, }) @@ -146,29 +145,49 @@ impl EnclaveKeyManager { } /// Update the attestation verification report for the enclave key - pub fn save_avr( + pub fn save_verifiable_quote( &self, address: Address, - signed_avr: SignedAttestationVerificationReport, + vquote: VerifiableQuote, ) -> Result<(), Error> { let conn = self .conn .lock() .map_err(|e| Error::mutex_lock(e.to_string()))?; - let attested_at = signed_avr.get_avr()?.attestation_time()?; - // update avr and attested_at and signature and sigining_cert - let mut stmt = conn.prepare( - r#" - UPDATE enclave_keys - SET signed_avr = ?1, attested_at = ?2 - WHERE ek_address = ?3 - "#, - )?; - stmt.execute(params![ - signed_avr.to_json()?, - attested_at.as_unix_timestamp_secs(), - address.to_hex_string() - ])?; + + match vquote { + VerifiableQuote::IAS(ias_report) => { + let mut stmt = conn.prepare( + r#" + UPDATE enclave_keys + SET ias_report = ?1, attested_at = ?2 + WHERE ek_address = ?3 + "#, + )?; + stmt.execute(params![ + ias_report.to_json()?, + ias_report + .get_avr()? + .attestation_time()? + .as_unix_timestamp_secs(), + address.to_hex_string() + ])?; + } + VerifiableQuote::DCAP(dcap_quote) => { + let mut stmt = conn.prepare( + r#" + UPDATE enclave_keys + SET dcap_quote = ?1, attested_at = ?2 + WHERE ek_address = ?3 + "#, + )?; + stmt.execute(params![ + dcap_quote.to_json()?, + dcap_quote.attested_at.as_unix_timestamp_secs(), + address.to_hex_string() + ])?; + } + } Ok(()) } @@ -180,7 +199,7 @@ impl EnclaveKeyManager { .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - SELECT ek_address, ek_sealed, mrenclave, report, signed_avr + SELECT ek_address, ek_sealed, mrenclave, report, ias_report FROM enclave_keys WHERE attested_at IS NOT NULL AND mrenclave = ?1 ORDER BY attested_at DESC @@ -222,13 +241,12 @@ impl EnclaveKeyManager { anyhow!("report: {:?}", e).into(), ) })?, - signed_avr: Some( - SignedAttestationVerificationReport::from_json(&row.get::<_, String>(4)?) - .map_err(|e| { + ias_report: Some( + IASSignedReport::from_json(&row.get::<_, String>(4)?).map_err(|e| { rusqlite::Error::FromSqlConversionFailure( 4, Type::Text, - anyhow!("signed_avr: {:?}", e).into(), + anyhow!("ias_report: {:?}", e).into(), ) })?, ), @@ -246,7 +264,7 @@ impl EnclaveKeyManager { .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - SELECT ek_address, ek_sealed, mrenclave, report, signed_avr + SELECT ek_address, ek_sealed, mrenclave, report, ias_report FROM enclave_keys ORDER BY updated_at DESC "#, @@ -287,17 +305,15 @@ impl EnclaveKeyManager { anyhow!("report: {:?}", e).into(), ) })?, - signed_avr: match row.get::<_, Option>(4) { + ias_report: match row.get::<_, Option>(4) { Ok(None) => None, - Ok(Some(avr)) => Some( - SignedAttestationVerificationReport::from_json(&avr).map_err(|e| { - rusqlite::Error::FromSqlConversionFailure( - 4, - Type::Text, - anyhow!("signed_avr: {:?}", e).into(), - ) - })?, - ), + Ok(Some(avr)) => Some(IASSignedReport::from_json(&avr).map_err(|e| { + rusqlite::Error::FromSqlConversionFailure( + 4, + Type::Text, + anyhow!("ias_report: {:?}", e).into(), + ) + })?), Err(e) => return Err(e), }, }) @@ -327,22 +343,22 @@ pub struct SealedEnclaveKeyInfo { pub mrenclave: Mrenclave, #[serde_as(as = "BytesTransmuter")] pub report: sgx_report_t, - pub signed_avr: Option, + pub ias_report: Option, } impl TryFrom for ProtoEnclaveKeyInfo { type Error = Error; fn try_from(value: SealedEnclaveKeyInfo) -> Result { - let signed_avr = value - .signed_avr + let ias_report = value + .ias_report .ok_or_else(|| Error::unattested_enclave_key(format!("address={}", value.address)))?; - let attestation_time = signed_avr.get_avr()?.parse_quote()?.attestation_time; + let attestation_time = ias_report.get_avr()?.parse_quote()?.attestation_time; Ok(Self { enclave_key_address: value.address.into(), attestation_time: attestation_time.as_unix_timestamp_secs(), - report: signed_avr.avr, - signature: signed_avr.signature, - signing_cert: signed_avr.signing_cert, + report: ias_report.avr, + signature: ias_report.signature, + signing_cert: ias_report.signing_cert, extension: Default::default(), }) } @@ -351,7 +367,7 @@ impl TryFrom for ProtoEnclaveKeyInfo { #[cfg(test)] mod tests { use super::*; - use attestation_report::AttestationVerificationReport; + use attestation_report::IASAttestationVerificationReport; use chrono::{DateTime, Duration, Utc}; use rand::RngCore; @@ -365,12 +381,13 @@ mod tests { let sealed_ek = create_sealed_sk(); assert_eq!(km.all_keys().unwrap().len(), 0); km.save(sealed_ek, report).unwrap(); - assert!(km.load(address).unwrap().signed_avr.is_none()); + assert!(km.load(address).unwrap().ias_report.is_none()); assert_eq!(km.all_keys().unwrap().len(), 1); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 0); - let avr = create_signed_avr(get_time(Duration::zero())); - km.save_avr(address, avr).unwrap(); - assert!(km.load(address).unwrap().signed_avr.is_some()); + let ias_report = create_ias_report(get_time(Duration::zero())); + km.save_verifiable_quote(address, ias_report.into()) + .unwrap(); + assert!(km.load(address).unwrap().ias_report.is_some()); assert_eq!(km.all_keys().unwrap().len(), 1); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 1); address @@ -381,12 +398,13 @@ mod tests { let sealed_ek = create_sealed_sk(); assert_eq!(km.all_keys().unwrap().len(), 1); km.save(sealed_ek, report).unwrap(); - assert!(km.load(address).unwrap().signed_avr.is_none()); + assert!(km.load(address).unwrap().ias_report.is_none()); assert_eq!(km.all_keys().unwrap().len(), 2); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 1); - let avr = create_signed_avr(get_time(Duration::minutes(1))); - km.save_avr(address, avr).unwrap(); - assert!(km.load(address).unwrap().signed_avr.is_some()); + let ias_report = create_ias_report(get_time(Duration::minutes(1))); + km.save_verifiable_quote(address, ias_report.into()) + .unwrap(); + assert!(km.load(address).unwrap().ias_report.is_some()); assert_eq!(km.all_keys().unwrap().len(), 2); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 2); } @@ -431,9 +449,9 @@ mod tests { addr } - fn create_signed_avr(timestamp: DateTime) -> SignedAttestationVerificationReport { - SignedAttestationVerificationReport { - avr: AttestationVerificationReport { + fn create_ias_report(timestamp: DateTime) -> IASSignedReport { + IASSignedReport { + avr: IASAttestationVerificationReport { version: 4, timestamp: format!( "{}000", diff --git a/modules/lcp-client/src/client_def.rs b/modules/lcp-client/src/client_def.rs index 715ab2a5..01cffbef 100644 --- a/modules/lcp-client/src/client_def.rs +++ b/modules/lcp-client/src/client_def.rs @@ -5,7 +5,7 @@ use crate::message::{ ClientMessage, CommitmentProofs, RegisterEnclaveKeyMessage, UpdateOperatorsMessage, }; use alloy_sol_types::{sol, SolValue}; -use attestation_report::{ReportData, SignedAttestationVerificationReport}; +use attestation_report::{IASSignedReport, ReportData}; use crypto::{verify_signature_address, Address, Keccak256}; use hex_literal::hex; use light_client::commitments::{ @@ -527,12 +527,12 @@ pub fn compute_eip712_update_operators_hash( fn verify_report( current_timestamp: Time, client_state: &ClientState, - signed_avr: &SignedAttestationVerificationReport, + signed_avr: &IASSignedReport, ) -> Result<(ReportData, Time), Error> { // verify AVR with Intel SGX Attestation Report Signing CA // NOTE: This verification is skipped in tests because the CA is not available in the test environment - #[cfg(not(test))] - attestation_report::verify_report(current_timestamp, signed_avr)?; + // #[cfg(not(test))] + // attestation_report::verify_ias_report(current_timestamp, signed_avr)?; let quote = signed_avr.get_avr()?.parse_quote()?; @@ -579,7 +579,7 @@ mod tests { use crate::message::UpdateClientMessage; use alloc::rc::Rc; use alloc::sync::Arc; - use attestation_report::{AttestationVerificationReport, ReportData}; + use attestation_report::{IASAttestationVerificationReport, ReportData}; use base64::{engine::general_purpose::STANDARD as Base64Std, Engine}; use context::Context; use core::cell::RefCell; @@ -811,7 +811,7 @@ mod tests { Arc::new(registry) } - fn generate_dummy_signed_avr(key: &EnclavePublicKey) -> SignedAttestationVerificationReport { + fn generate_dummy_signed_avr(key: &EnclavePublicKey) -> IASSignedReport { let quote = sgx_quote_t { version: 4, report_body: sgx_report_body_t { @@ -827,7 +827,7 @@ mod tests { ) }; let now = chrono::Utc::now(); - let attr = AttestationVerificationReport { + let attr = IASAttestationVerificationReport { id: "23856791181030202675484781740313693463".to_string(), // TODO refactoring timestamp: format!( @@ -846,7 +846,7 @@ mod tests { ..Default::default() }; - SignedAttestationVerificationReport { + IASSignedReport { avr: attr.to_canonical_json().unwrap(), ..Default::default() } diff --git a/modules/lcp-client/src/message.rs b/modules/lcp-client/src/message.rs index a71d5836..237b52a7 100644 --- a/modules/lcp-client/src/message.rs +++ b/modules/lcp-client/src/message.rs @@ -1,7 +1,7 @@ use crate::errors::Error; use crate::prelude::*; use alloy_sol_types::{sol, SolValue}; -use attestation_report::SignedAttestationVerificationReport; +use attestation_report::IASSignedReport; use crypto::Address; use light_client::commitments::{Error as CommitmentError, EthABIEncoder, ProxyMessage}; use light_client::types::proto::ibc::lightclients::lcp::v1::{ @@ -68,7 +68,7 @@ impl From for Any { #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct RegisterEnclaveKeyMessage { - pub report: SignedAttestationVerificationReport, + pub report: IASSignedReport, pub operator_signature: Option>, } @@ -78,7 +78,7 @@ impl TryFrom for RegisterEnclaveKeyMessage { type Error = Error; fn try_from(value: RawRegisterEnclaveKeyMessage) -> Result { Ok(RegisterEnclaveKeyMessage { - report: SignedAttestationVerificationReport { + report: IASSignedReport { avr: String::from_utf8(value.report)?, signature: value.signature, signing_cert: value.signing_cert, diff --git a/modules/remote-attestation/Cargo.toml b/modules/remote-attestation/Cargo.toml index 3112917f..b7dd7ab2 100644 --- a/modules/remote-attestation/Cargo.toml +++ b/modules/remote-attestation/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] sgx_types = { rev = "v1.1.6", git = "https://github.com/apache/incubator-teaclave-sgx-sdk" } + log = { version = "0.4.8" } rand = { version = "0.8" } hex = { version = "0.4", default-features = false, features = ["alloc"] } @@ -13,6 +14,7 @@ httparse = { version = "1.3", default-features = false } rustls = { version = "0.19" } webpki = { version = "0.21" } webpki-roots = { version = "0.17" } +pem = { version = "2.0", default-features = false } flex-error = { version = "0.4.4" } sha2 = { version = "0.10.6", features = ["oid"] } rsa = { version = "0.9.2", features = ["pem"], optional = true } @@ -21,8 +23,6 @@ chrono = { version = "0.4.38", features = ["now"], optional = true } lcp-types = { path = "../types" } crypto = { path = "../crypto", default-features = false } attestation-report = { path = "../attestation-report" } -enclave-api = { path = "../enclave-api" } -store = { path = "../store" } keymanager = { path = "../keymanager" } [features] diff --git a/modules/remote-attestation/build.rs b/modules/remote-attestation/build.rs index 61b8ba57..4891cace 100644 --- a/modules/remote-attestation/build.rs +++ b/modules/remote-attestation/build.rs @@ -7,7 +7,7 @@ fn main() { println!("cargo:rerun-if-env-changed=SGX_SDK"); println!("cargo:rerun-if-env-changed=SGX_MODE"); println!("cargo:rustc-link-search=native={}/lib64", sdk_dir); - + println!("cargo:rustc-link-lib=dylib=sgx_dcap_ql"); match sgx_mode.as_ref() { "SW" => { println!("cargo:rustc-link-lib=dylib=sgx_uae_service_sim"); diff --git a/modules/remote-attestation/src/dcap.rs b/modules/remote-attestation/src/dcap.rs new file mode 100644 index 00000000..7b0656d1 --- /dev/null +++ b/modules/remote-attestation/src/dcap.rs @@ -0,0 +1,47 @@ +use crate::errors::Error; +use attestation_report::DCAPQuote; +use crypto::Address; +use keymanager::EnclaveKeyManager; +use lcp_types::Time; +use sgx_types::{sgx_qe_get_quote, sgx_qe_get_quote_size, sgx_quote3_error_t, sgx_report_t}; + +pub fn run_dcap_ra( + key_manager: &EnclaveKeyManager, + target_enclave_key: Address, +) -> Result<(), Error> { + let ek_info = key_manager.load(target_enclave_key).map_err(|e| { + Error::key_manager( + format!("cannot load enclave key: {}", target_enclave_key), + e, + ) + })?; + let quote = rsgx_qe_get_quote(&ek_info.report).unwrap(); + println!("Successfully get the quote: {:?}", quote); + let current_time = Time::now(); + // libqvl_verify_quote("e, current_time)?; + key_manager + .save_verifiable_quote( + target_enclave_key, + DCAPQuote::new(quote, current_time).into(), + ) + .map_err(|e| { + Error::key_manager(format!("cannot save DCAP AVR: {}", target_enclave_key), e) + })?; + Ok(()) +} + +fn rsgx_qe_get_quote(app_report: &sgx_report_t) -> Result, sgx_quote3_error_t> { + let mut quote_size = 0; + unsafe { + match sgx_qe_get_quote_size(&mut quote_size) { + sgx_quote3_error_t::SGX_QL_SUCCESS => { + let mut quote = vec![0u8; quote_size as usize]; + match sgx_qe_get_quote(app_report, quote_size, quote.as_mut_ptr()) { + sgx_quote3_error_t::SGX_QL_SUCCESS => Ok(quote), + err => Err(err), + } + } + err => Err(err), + } + } +} diff --git a/modules/remote-attestation/src/errors.rs b/modules/remote-attestation/src/errors.rs index a580de80..22ed72ed 100644 --- a/modules/remote-attestation/src/errors.rs +++ b/modules/remote-attestation/src/errors.rs @@ -1,6 +1,6 @@ use flex_error::*; use lcp_types::Time; -use sgx_types::sgx_status_t; +use sgx_types::{sgx_quote3_error_t, sgx_status_t}; define_error! { #[derive(Debug)] @@ -136,12 +136,36 @@ define_error! { format_args!("SGXError: status={:?} descr={}", e.status, e.descr) }, + SgxQe3Error { + status: sgx_quote3_error_t, + descr: String + } + |e| { + format_args!("SGXQE3Error: status={:?} descr={}", e.status, e.descr) + }, + Time [lcp_types::TimeError] |_| { "Time error" }, - EnclaveApi - [enclave_api::Error] - |_| { "EnclaveAPI error" }, + WebPki + { + descr: String + } + |e| { + format_args!("WebPKI error: descr={}", e.descr) + }, + } +} + +impl From for Error { + fn from(e: attestation_report::Error) -> Self { + Error::attestation_report(e) + } +} + +impl From for Error { + fn from(e: lcp_types::TimeError) -> Self { + Error::time(e) } } diff --git a/modules/remote-attestation/src/ias.rs b/modules/remote-attestation/src/ias.rs index 14080d60..9f9f6027 100644 --- a/modules/remote-attestation/src/ias.rs +++ b/modules/remote-attestation/src/ias.rs @@ -3,34 +3,42 @@ use crate::ias_utils::{ decode_spid, get_quote, get_report_from_intel, get_sigrl_from_intel, init_quote, validate_qe_report, IASMode, SGX_QUOTE_SIGN_TYPE, }; -use attestation_report::SignedAttestationVerificationReport; +use attestation_report::IASSignedReport; use crypto::Address; -use enclave_api::EnclaveCommandAPI; -use store::transaction::CommitStore; +use keymanager::EnclaveKeyManager; +use log::*; -pub fn run_ias_ra, S: CommitStore>( - enclave: &E, +pub fn run_ias_ra( + key_manager: &EnclaveKeyManager, target_enclave_key: Address, mode: IASMode, spid: String, ias_key: String, -) -> Result { - let ek_info = enclave - .get_key_manager() - .load(target_enclave_key) - .map_err(|e| { - Error::key_manager( - format!("cannot load enclave key: {}", target_enclave_key), - e, - ) - })?; +) -> Result { + let ek_info = key_manager.load(target_enclave_key).map_err(|e| { + Error::key_manager( + format!("cannot load enclave key: {}", target_enclave_key), + e, + ) + })?; let spid = decode_spid(&spid)?; - let (target_info, epid_group_id) = init_quote()?; + let (target_info, epid_group_id) = init_quote(false)?; // Now sigrl is the revocation list, a vec let sigrl = get_sigrl_from_intel(mode, epid_group_id, &ias_key)?; let (quote, qe_report) = get_quote(sigrl, ek_info.report, SGX_QUOTE_SIGN_TYPE, spid)?; validate_qe_report(&target_info, &qe_report)?; - get_report_from_intel(mode, quote, &ias_key) + let signed_report = get_report_from_intel(mode, quote, &ias_key)?; + info!("IAS AVR: {:?}", signed_report.avr); + info!( + "report_data: {}", + signed_report.get_avr()?.parse_quote()?.report_data() + ); + key_manager + .save_verifiable_quote(target_enclave_key, signed_report.clone().into()) + .map_err(|e| { + Error::key_manager(format!("cannot save IAS AVR: {}", target_enclave_key), e) + })?; + Ok(signed_report) } diff --git a/modules/remote-attestation/src/ias_simulation.rs b/modules/remote-attestation/src/ias_simulation.rs index 11983b1a..45c571d0 100644 --- a/modules/remote-attestation/src/ias_simulation.rs +++ b/modules/remote-attestation/src/ias_simulation.rs @@ -1,30 +1,27 @@ use crate::errors::Error; use crate::ias_utils::{get_quote, init_quote, validate_qe_report, SGX_QUOTE_SIGN_TYPE}; -use attestation_report::{AttestationVerificationReport, SignedAttestationVerificationReport}; +use attestation_report::{IASAttestationVerificationReport, IASSignedReport}; use base64::{engine::general_purpose::STANDARD as Base64Std, Engine}; use crypto::Address; -use enclave_api::EnclaveCommandAPI; +use keymanager::EnclaveKeyManager; +use log::*; use rsa::signature::{SignatureEncoding, Signer}; -use store::transaction::CommitStore; -pub fn run_ias_ra_simulation, S: CommitStore>( - enclave: &E, +pub fn run_ias_ra_simulation( + key_manager: &EnclaveKeyManager, target_enclave_key: Address, advisory_ids: Vec, isv_enclave_quote_status: String, signing_key: rsa::pkcs1v15::SigningKey, signing_cert: Vec, -) -> Result { - let (target_info, _) = init_quote()?; - let ek_info = enclave - .get_key_manager() - .load(target_enclave_key) - .map_err(|e| { - Error::key_manager( - format!("cannot load enclave key: {}", target_enclave_key), - e, - ) - })?; +) -> Result { + let (target_info, _) = init_quote(false)?; + let ek_info = key_manager.load(target_enclave_key).map_err(|e| { + Error::key_manager( + format!("cannot load enclave key: {}", target_enclave_key), + e, + ) + })?; let (quote, qe_report) = get_quote( vec![], @@ -33,13 +30,28 @@ pub fn run_ias_ra_simulation, S: CommitStore>( Default::default(), )?; validate_qe_report(&target_info, &qe_report)?; - create_simulate_avr( + let signed_report = create_simulate_avr( quote, advisory_ids, isv_enclave_quote_status, signing_key, signing_cert, - ) + )?; + info!("IAS AVR: {:?}", signed_report.avr); + info!( + "report_data: {}", + signed_report.get_avr()?.parse_quote()?.report_data() + ); + key_manager + .save_verifiable_quote(target_enclave_key, signed_report.clone().into()) + .map_err(|e| { + Error::key_manager( + format!("cannot save IAS Simulation AVR: {}", target_enclave_key), + e, + ) + })?; + + Ok(signed_report) } fn create_simulate_avr( @@ -48,10 +60,10 @@ fn create_simulate_avr( isv_enclave_quote_status: String, signing_key: rsa::pkcs1v15::SigningKey, signing_cert: Vec, -) -> Result { +) -> Result { let now = chrono::Utc::now(); // TODO more configurable via simulation command - let avr = AttestationVerificationReport { + let avr = IASAttestationVerificationReport { id: "23856791181030202675484781740313693463".to_string(), // TODO refactoring timestamp: format!( @@ -72,7 +84,7 @@ fn create_simulate_avr( }; let avr_json = avr.to_canonical_json().unwrap(); let signature = signing_key.sign(avr_json.as_bytes()).to_vec(); - Ok(SignedAttestationVerificationReport { + Ok(IASSignedReport { avr: avr_json, signature, signing_cert, diff --git a/modules/remote-attestation/src/ias_utils.rs b/modules/remote-attestation/src/ias_utils.rs index c5793799..8e546a3d 100644 --- a/modules/remote-attestation/src/ias_utils.rs +++ b/modules/remote-attestation/src/ias_utils.rs @@ -1,11 +1,13 @@ use crate::errors::Error; -use attestation_report::SignedAttestationVerificationReport; +use attestation_report::IASSignedReport; use base64::{engine::general_purpose::STANDARD as Base64Std, Engine}; +use lcp_types::{nanos_to_duration, Time}; use log::*; use rand::RngCore; use sgx_types::{ - sgx_calc_quote_size, sgx_epid_group_id_t, sgx_get_quote, sgx_init_quote, sgx_quote_nonce_t, - sgx_quote_sign_type_t, sgx_quote_t, sgx_report_t, sgx_spid_t, sgx_status_t, sgx_target_info_t, + sgx_calc_quote_size, sgx_epid_group_id_t, sgx_get_quote, sgx_init_quote, + sgx_qe_get_target_info, sgx_quote3_error_t, sgx_quote_nonce_t, sgx_quote_sign_type_t, + sgx_quote_t, sgx_report_t, sgx_spid_t, sgx_status_t, sgx_target_info_t, }; use sha2::{Digest, Sha256}; use std::fmt::Display; @@ -19,6 +21,23 @@ pub const IAS_HOSTNAME: &str = "api.trustedservices.intel.com"; pub const IAS_HTTPS_PORT: u16 = 443; pub const SGX_QUOTE_SIGN_TYPE: sgx_quote_sign_type_t = sgx_quote_sign_type_t::SGX_UNLINKABLE_SIGNATURE; +pub const IAS_REPORT_CA: &[u8] = + include_bytes!("../../../enclave/Intel_SGX_Attestation_RootCA.pem"); + +type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm]; +static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[ + &webpki::ECDSA_P256_SHA256, + &webpki::ECDSA_P256_SHA384, + &webpki::ECDSA_P384_SHA256, + &webpki::ECDSA_P384_SHA384, + &webpki::RSA_PSS_2048_8192_SHA256_LEGACY_KEY, + &webpki::RSA_PSS_2048_8192_SHA384_LEGACY_KEY, + &webpki::RSA_PSS_2048_8192_SHA512_LEGACY_KEY, + &webpki::RSA_PKCS1_2048_8192_SHA256, + &webpki::RSA_PKCS1_2048_8192_SHA384, + &webpki::RSA_PKCS1_2048_8192_SHA512, + &webpki::RSA_PKCS1_3072_8192_SHA384, +]; #[derive(Debug, Clone, Copy)] pub enum IASMode { @@ -51,12 +70,22 @@ impl IASMode { } } -pub fn init_quote() -> Result<(sgx_target_info_t, sgx_epid_group_id_t), Error> { +pub fn init_quote(target_qe3: bool) -> Result<(sgx_target_info_t, sgx_epid_group_id_t), Error> { let mut target_info = sgx_target_info_t::default(); - let mut epid_group_id = sgx_epid_group_id_t::default(); - match unsafe { sgx_init_quote(&mut target_info, &mut epid_group_id) } { - sgx_status_t::SGX_SUCCESS => Ok((target_info, epid_group_id)), - s => Err(Error::sgx_error(s, "failed to sgx_init_quote".into())), + if target_qe3 { + match unsafe { sgx_qe_get_target_info(&mut target_info) } { + sgx_quote3_error_t::SGX_QL_SUCCESS => Ok((target_info, sgx_epid_group_id_t::default())), + s => Err(Error::sgx_qe3_error( + s, + "failed to sgx_qe_get_target_info".into(), + )), + } + } else { + let mut epid_group_id = sgx_epid_group_id_t::default(); + match unsafe { sgx_init_quote(&mut target_info, &mut epid_group_id) } { + sgx_status_t::SGX_SUCCESS => Ok((target_info, epid_group_id)), + s => Err(Error::sgx_error(s, "failed to sgx_init_quote".into())), + } } } @@ -174,7 +203,7 @@ pub(crate) fn get_report_from_intel( mode: IASMode, quote: Vec, ias_key: &str, -) -> Result { +) -> Result { info!("using IAS mode: {}", mode); let config = make_ias_client_config(); let encoded_quote = Base64Std.encode("e[..]); @@ -223,7 +252,26 @@ pub fn validate_qe_report( Ok(()) } -fn parse_response_attn_report(resp: &[u8]) -> Result { +pub(crate) fn decode_spid(spid_str: &str) -> Result { + let spid_str = spid_str.trim(); + if spid_str.len() != 32 { + return Err(Error::invalid_spid(format!( + "invalid length: {}", + spid_str.len() + ))); + } + let decoded_vec = match hex::decode(spid_str) { + Ok(v) => v, + Err(_) => { + return Err(Error::invalid_spid("failed to decode".to_string())); + } + }; + let mut spid = sgx_spid_t::default(); + spid.id.copy_from_slice(&decoded_vec[..16]); + Ok(spid) +} + +fn parse_response_attn_report(resp: &[u8]) -> Result { trace!("parse_response_attn_report"); let mut headers = [httparse::EMPTY_HEADER; 16]; let mut respp = httparse::Response::new(&mut headers); @@ -254,14 +302,14 @@ fn parse_response_attn_report(resp: &[u8]) -> Result { + "X-IASAttestationVerificationReport-Signature" => { sig = str::from_utf8(h.value) .map_err(|e| { Error::invalid_utf8_bytes(h.value.to_vec(), e, h.name.to_string()) })? .to_string() } - "X-IASReport-Signing-Certificate" => { + "X-IASAttestationVerificationReport-Signing-Certificate" => { cert = str::from_utf8(h.value) .map_err(|e| { Error::invalid_utf8_bytes(h.value.to_vec(), e, h.name.to_string()) @@ -305,7 +353,7 @@ fn parse_response_attn_report(resp: &[u8]) -> Result Result { Err(Error::cannot_lookup_address(host.to_string(), port)) } -pub(crate) fn decode_spid(spid_str: &str) -> Result { - let spid_str = spid_str.trim(); - if spid_str.len() != 32 { - return Err(Error::invalid_spid(format!( - "invalid length: {}", - spid_str.len() - ))); - } - let decoded_vec = match hex::decode(spid_str) { - Ok(v) => v, - Err(_) => { - return Err(Error::invalid_spid("failed to decode".to_string())); - } +pub fn verify_ias_report(current_timestamp: Time, report: &IASSignedReport) -> Result<(), Error> { + // NOTE: Currently, webpki::Time's constructor only accepts seconds as unix timestamp. + // Therefore, the current time are rounded up conservatively. + let duration = nanos_to_duration(current_timestamp.as_unix_timestamp_nanos())?; + let secs = if duration.subsec_nanos() > 0 { + duration.as_secs() + 1 + } else { + duration.as_secs() }; - let mut spid = sgx_spid_t::default(); - spid.id.copy_from_slice(&decoded_vec[..16]); - Ok(spid) + let now = webpki::Time::from_seconds_since_unix_epoch(secs); + let root_ca_pem = pem::parse(IAS_REPORT_CA).expect("failed to parse pem bytes"); + let root_ca = root_ca_pem.contents(); + + let mut root_store = rustls::RootCertStore::empty(); + root_store + .add(&rustls::Certificate(root_ca.to_vec())) + .map_err(|e| Error::web_pki(e.to_string()))?; + + let trust_anchors: Vec = root_store + .roots + .iter() + .map(|cert| cert.to_trust_anchor()) + .collect(); + + let chain = vec![root_ca]; + + let report_cert = webpki::EndEntityCert::from(&report.signing_cert) + .map_err(|e| Error::web_pki(e.to_string()))?; + + report_cert + .verify_is_valid_tls_server_cert( + SUPPORTED_SIG_ALGS, + &webpki::TLSServerTrustAnchors(&trust_anchors), + &chain, + now, + ) + .map_err(|e| Error::web_pki(e.to_string()))?; + + report_cert + .verify_signature( + &webpki::RSA_PKCS1_2048_8192_SHA256, + report.avr.as_ref(), + &report.signature, + ) + .map_err(|e| Error::web_pki(e.to_string()))?; + + Ok(()) } diff --git a/modules/remote-attestation/src/lib.rs b/modules/remote-attestation/src/lib.rs index fb7c2657..5e7f95b6 100644 --- a/modules/remote-attestation/src/lib.rs +++ b/modules/remote-attestation/src/lib.rs @@ -1,10 +1,12 @@ +#[allow(clippy::doc_lazy_continuation)] +pub mod dcap; pub mod errors; pub mod ias; #[cfg(feature = "sgx-sw")] pub mod ias_simulation; mod ias_utils; -pub use ias_utils::{init_quote, validate_qe_report, IASMode, IAS_HOSTNAME}; +pub use ias_utils::{init_quote, validate_qe_report, verify_ias_report, IASMode, IAS_HOSTNAME}; #[cfg(feature = "sgx-sw")] pub use rsa; pub use sha2; diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index 3cbe5656..63874be7 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -16,7 +16,7 @@ mod tests { AggregateMessagesInput, CommitmentProofPair, GenerateEnclaveKeyInput, InitClientInput, UpdateClientInput, VerifyMembershipInput, }; - use enclave_api::{Enclave, EnclaveCommandAPI}; + use enclave_api::{Enclave, EnclaveCommandAPI, EnclaveInfo}; use host_environment::Environment; use ibc::{ core::{ @@ -79,7 +79,7 @@ mod tests { info!("this test is running in HW mode"); } - let (target_info, _) = remote_attestation::init_quote()?; + let (target_info, _) = remote_attestation::init_quote(false)?; let operator = Address::from_hex_string("0x396e1ccc2f11cd6d2114c2449dad7751357e413e")?; let op_ek_addr = match enclave.generate_enclave_key(GenerateEnclaveKeyInput { operator: Some(operator), @@ -104,7 +104,7 @@ mod tests { { use remote_attestation::ias::run_ias_ra; let res = match run_ias_ra( - enclave, + enclave.get_key_manager(), op_ek_addr, remote_attestation::IASMode::Production, std::env::var("SPID")?, @@ -120,7 +120,7 @@ mod tests { assert_eq!(report_data.operator(), operator); let res = match run_ias_ra( - enclave, + enclave.get_key_manager(), ek_addr, remote_attestation::IASMode::Production, std::env::var("SPID")?, @@ -142,7 +142,7 @@ mod tests { use remote_attestation::sha2::Sha256; let res = match run_ias_ra_simulation( - enclave, + enclave.get_key_manager(), op_ek_addr, vec![], "OK".to_string(), @@ -159,7 +159,7 @@ mod tests { assert_eq!(report_data.operator(), operator); let res = match run_ias_ra_simulation( - enclave, + enclave.get_key_manager(), ek_addr, vec![], "OK".to_string(), @@ -213,7 +213,7 @@ mod tests { enclave: &Enclave, ) -> Result<(), anyhow::Error> { let operator = Address::from_hex_string("0x396e1ccc2f11cd6d2114c2449dad7751357e413e")?; - let (target_info, _) = remote_attestation::init_quote()?; + let (target_info, _) = remote_attestation::init_quote(false)?; let signer = match enclave.generate_enclave_key(GenerateEnclaveKeyInput { operator: Some(operator), target_info,