From 9bd520c13d3997024b3694697039e53f45acad3c Mon Sep 17 00:00:00 2001 From: Tobin Feldman-Fitzthum Date: Wed, 7 Dec 2022 00:00:20 +0000 Subject: [PATCH] Initial SNP Verifier A simple verifier for SNP guests. This verifier validates an attestation report and returns a claims map parsed from the report. It does not have any support for kernel hashes and does not yet cover the full CoCo TCB. Signed-off-by: Tobin Feldman-Fitzthum --- Cargo.lock | 298 +++++++++++++----- attestation-service/Cargo.toml | 9 +- attestation-service/src/verifier/mod.rs | 16 +- .../src/verifier/snp/milan_ask_ark.pem | 74 +++++ attestation-service/src/verifier/snp/mod.rs | 275 ++++++++++++++++ .../src/verifier/snp/test-vcek.der | Bin 0 -> 1360 bytes 6 files changed, 581 insertions(+), 91 deletions(-) create mode 100644 attestation-service/src/verifier/snp/milan_ask_ark.pem create mode 100644 attestation-service/src/verifier/snp/mod.rs create mode 100644 attestation-service/src/verifier/snp/test-vcek.der diff --git a/Cargo.lock b/Cargo.lock index 356712f..86d8f86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,6 +22,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -95,6 +101,45 @@ dependencies = [ "serde_json", ] +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time 0.3.21", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -114,7 +159,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -125,7 +170,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -134,9 +179,11 @@ version = "0.1.0" dependencies = [ "anyhow", "as-types", + "asn1-rs", "async-trait", "az-snp-vtpm", "base64", + "bincode", "byteorder", "cfg-if", "chrono", @@ -147,6 +194,7 @@ dependencies = [ "kbs-types", "lazy_static", "log", + "openssl", "path-clean", "prost", "rstest", @@ -167,6 +215,7 @@ dependencies = [ "tonic-build", "uuid", "walkdir", + "x509-parser", ] [[package]] @@ -238,7 +287,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8dbeaadc2dd14dd7bb36a5c608b95959e191277a7f9852522594c17d840608" dependencies = [ "bincode", - "clap 4.2.7", + "clap 4.3.0", "jsonwebkey", "memoffset", "openssl", @@ -329,9 +378,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.2" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byteorder" @@ -380,13 +429,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "fdbc37d37da9e5bce8173f3a41b71d9bf3c674deebbaceacd0ebdabde76efb03" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "serde", "time 0.1.45", @@ -434,25 +483,25 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.7" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" dependencies = [ "clap_builder", - "clap_derive 4.2.0", + "clap_derive 4.3.0", "once_cell", ] [[package]] name = "clap_builder" -version = "4.2.7" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" dependencies = [ "anstream", "anstyle", "bitflags", - "clap_lex 0.4.1", + "clap_lex 0.5.0", "strsim", ] @@ -471,14 +520,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -492,9 +541,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "codicon" @@ -522,18 +571,18 @@ checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" [[package]] name = "const_format" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e" +checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.29" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650" +checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" dependencies = [ "proc-macro2", "quote", @@ -609,6 +658,12 @@ dependencies = [ "parking_lot_core 0.9.7", ] +[[package]] +name = "data-encoding" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" + [[package]] name = "der" version = "0.6.1" @@ -620,11 +675,25 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "const-oid", @@ -652,6 +721,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "either" version = "1.8.1" @@ -675,7 +755,7 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -851,7 +931,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1192,9 +1272,9 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi 0.3.1", "libc", @@ -1251,9 +1331,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.62" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68c16e1bfd491478ab155fd8b4896b86f9ede344949b641e61501e07c2b8b4d5" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] @@ -1296,9 +1376,9 @@ dependencies = [ [[package]] name = "kvm-ioctls" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8f8dc9c1896e5f144ec5d07169bc29f39a047686d29585a91f30489abfaeb6b" +checksum = "436246b230532c94ec619332e820e31518dac7943cf848b052e618467a7ede8a" dependencies = [ "kvm-bindings", "libc", @@ -1384,12 +1464,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" [[package]] name = "matchit" @@ -1437,14 +1514,13 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1561,17 +1637,26 @@ dependencies = [ "serde", ] +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" [[package]] name = "openssl" -version = "0.10.52" +version = "0.10.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01b8574602df80f7b85fdfc5392fa884a4e3b3f4f35402c070ab34c3d3f78d56" +checksum = "12df40a956736488b7b44fe79fe12d4f245bb5b3f5a1f6095e499760015be392" dependencies = [ "bitflags", "cfg-if", @@ -1590,7 +1675,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1604,9 +1689,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.87" +version = "0.9.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" +checksum = "c2ce0f250f34a308dcfdbb351f511359857d4ed2134ba715a4eadd46e1ffd617" dependencies = [ "cc", "libc", @@ -1777,7 +1862,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -1880,9 +1965,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] @@ -1943,9 +2028,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -2011,9 +2096,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ "aho-corasick", "memchr", @@ -2022,9 +2107,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "ring" @@ -2112,6 +2197,15 @@ dependencies = [ "semver 1.0.17", ] +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + [[package]] name = "rustix" version = "0.37.19" @@ -2307,7 +2401,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2504,9 +2598,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -2521,9 +2615,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -2536,6 +2630,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + [[package]] name = "target-lexicon" version = "0.12.7" @@ -2596,7 +2702,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2656,9 +2762,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" dependencies = [ "autocfg", "bytes", @@ -2689,7 +2795,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2814,7 +2920,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] [[package]] @@ -2913,9 +3019,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -2974,9 +3080,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" dependencies = [ "getrandom", ] @@ -3037,9 +3143,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6cb788c4e39112fbe1822277ef6fb3c55cd86b95cb3d3c4c1c9597e4ac74b4" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3047,24 +3153,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e522ed4105a9d626d885b35d62501b30d9666283a5c8be12c14a8bdafe7822" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "358a79a0cb89d21db8120cbfb91392335913e4890665b1a7981d9e956903b434" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3072,28 +3178,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4783ce29f09b9d93134d41297aded3a712b7b979e9c6f28c32cb88c973a94869" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a901d592cafaa4d711bc324edfaff879ac700b19c3dfd60058d2b445be2691eb" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" [[package]] name = "web-sys" -version = "0.3.62" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b5f940c7edfdc6d12126d98c9ef4d1b3d470011c47c76a6581df47ad9ba721" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" dependencies = [ "js-sys", "wasm-bindgen", @@ -3301,6 +3407,24 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time 0.3.21", +] + [[package]] name = "yasna" version = "0.4.0" @@ -3327,5 +3451,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.18", ] diff --git a/attestation-service/Cargo.toml b/attestation-service/Cargo.toml index eacd217..42d1b83 100644 --- a/attestation-service/Cargo.toml +++ b/attestation-service/Cargo.toml @@ -5,20 +5,23 @@ edition = "2021" [features] default = [ "rvps-native", "all-verifier" ] -all-verifier = [ "tdx-verifier", "sgx-verifier" ] +all-verifier = [ "tdx-verifier", "sgx-verifier", "snp-verifier" ] tdx-verifier = [ "eventlog-rs", "scroll", "intel-tee-quote-verification-rs" ] sgx-verifier = [ "scroll", "intel-tee-quote-verification-rs" ] az-snp-vtpm-verifier = [ "az-snp-vtpm", "sev" ] +snp-verifier = [ "asn1-rs", "openssl", "sev", "x509-parser" ] rvps-native = [] rvps-grpc = [ "tonic" ] [dependencies] anyhow.workspace = true +asn1-rs = { version = "0.5.1", optional = true } async-trait.workspace = true as-types = { path = "../as-types" } az-snp-vtpm = { version = "0.2", default-features = false, features = ["verifier"], optional = true } base64 = "0.13.0" +bincode = "1.3.3" byteorder = "1" cfg-if = "1.0.0" chrono = { version = "0.4.19", features = [ "serde" ] } @@ -29,12 +32,13 @@ intel-tee-quote-verification-rs = { version = "0.2.1", optional = true } kbs-types = "0.3" lazy_static = "1.4.0" log.workspace = true +openssl = { version = "0.10.43", optional = true } path-clean = "0.1.0" prost.workspace = true scroll = { version = "0.11.0", default-features = false, features = ["derive"], optional = true } serde.workspace = true serde_json.workspace = true -sev = { version = "1.1.0", optional = true } +sev = { version = "= 1.1.0", features = ["openssl"], optional = true } sha2.workspace = true shadow-rs.workspace = true sled = "0.34.7" @@ -44,6 +48,7 @@ tempfile = "3.3.0" tokio.workspace = true tonic = { workspace = true, optional = true } uuid = { version = "1.1.2", features = ["v4"] } +x509-parser = { version = "0.14.0", optional = true } [build-dependencies] shadow-rs.workspace = true diff --git a/attestation-service/src/verifier/mod.rs b/attestation-service/src/verifier/mod.rs index 7003f10..7a9950f 100644 --- a/attestation-service/src/verifier/mod.rs +++ b/attestation-service/src/verifier/mod.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::*; use as_types::TeeEvidenceParsedClaim; use async_trait::async_trait; use kbs_types::{Attestation, Tee}; @@ -8,6 +8,9 @@ pub mod sample; #[cfg(feature = "az-snp-vtpm-verifier")] pub mod az_snp_vtpm; +#[cfg(feature = "snp-verifier")] +pub mod snp; + #[cfg(feature = "tdx-verifier")] pub mod tdx; @@ -16,7 +19,7 @@ pub mod sgx; pub(crate) fn to_verifier(tee: &Tee) -> Result> { match tee { - Tee::Sev | Tee::Snp | Tee::Cca => todo!(), + Tee::Sev | Tee::Cca => todo!(), Tee::AzSnpVtpm => { cfg_if::cfg_if! { if #[cfg(feature = "az-snp-vtpm-verifier")] { @@ -35,6 +38,15 @@ pub(crate) fn to_verifier(tee: &Tee) -> Result> } } } + Tee::Snp => { + cfg_if::cfg_if! { + if #[cfg(feature = "snp-verifier")] { + Ok(Box::::default() as Box) + } else { + bail!("SNP Verifier not enabled.") + } + } + } Tee::Sample => Ok(Box::::default() as Box), Tee::Sgx => { cfg_if::cfg_if! { diff --git a/attestation-service/src/verifier/snp/milan_ask_ark.pem b/attestation-service/src/verifier/snp/milan_ask_ark.pem new file mode 100644 index 0000000..148ca46 --- /dev/null +++ b/attestation-service/src/verifier/snp/milan_ask_ark.pem @@ -0,0 +1,74 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC +BQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS +BgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg +Q2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp +Y2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy +MTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS +BgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j +ZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg +W41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta +1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2 +SzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0 +60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05 +gmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg +bKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs ++gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi +Qi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ +eTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18 +fHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j +WhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI +rFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG +KWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG +SIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI +AWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel +ETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw +STjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK +dHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq +zT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp +KGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e +pmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq +HnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh +3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn +JZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH +CViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4 +AFZEAwoKCQ== +-----END CERTIFICATE----- diff --git a/attestation-service/src/verifier/snp/mod.rs b/attestation-service/src/verifier/snp/mod.rs new file mode 100644 index 0000000..c0adbc9 --- /dev/null +++ b/attestation-service/src/verifier/snp/mod.rs @@ -0,0 +1,275 @@ +use anyhow::{anyhow, Context, Result}; +extern crate serde; +use self::serde::{Deserialize, Serialize}; +use super::*; +use asn1_rs::{oid, Integer, Oid}; +use async_trait::async_trait; +use kbs_types::TeePubKey; +use openssl::{ + ec::EcKey, + ecdsa, + pkey::{PKey, Public}, + x509, +}; +use serde_json::json; +use sev::firmware::guest::types::AttestationReport; +use sev::firmware::host::types::{CertTableEntry, SnpCertType}; +use sha2::{Digest, Sha384}; +use x509_parser::prelude::*; + +#[derive(Serialize, Deserialize)] +struct SnpEvidence { + attestation_report: AttestationReport, + cert_chain: Vec, +} + +const HW_ID_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .4); +const UCODE_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .8); +const SNP_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .3); +const TEE_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .2); +const LOADER_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .1); + +#[derive(Debug, Default)] +pub struct Snp {} + +#[async_trait] +impl Verifier for Snp { + async fn evaluate( + &self, + nonce: String, + attestation: &Attestation, + ) -> Result { + let tee_evidence = serde_json::from_str::(&attestation.tee_evidence) + .context("Deserialize Quote failed.")?; + + verify_report_signature(&tee_evidence)?; + + let report = tee_evidence.attestation_report; + if report.version != 2 { + return Err(anyhow!("Unexpected report version")); + } + + if report.vmpl != 0 { + return Err(anyhow!("VMPL Check Failed")); + } + + let expected_report_data = calculate_expected_report_data(&nonce, &attestation.tee_pubkey); + if report.report_data != expected_report_data { + return Err(anyhow!("Report Data Mismatch")); + } + + Ok(parse_tee_evidence(&report)) + } +} + +fn get_oid( + vcek: &x509_parser::certificate::TbsCertificate, + oid: Oid, +) -> Result<[u8; N]> { + let val = vcek + .get_extension_unique(&oid)? + .ok_or_else(|| anyhow!("Oid not found"))? + .value; + + val.try_into().context("Oid data has wrong length.") +} + +fn get_oid_int(vcek: &x509_parser::certificate::TbsCertificate, oid: Oid) -> Result { + let val = vcek + .get_extension_unique(&oid)? + .ok_or_else(|| anyhow!("Oid not found"))? + .value; + + let (_, val_int) = Integer::from_der(val)?; + val_int.as_u8().context("Unexpected data size") +} + +fn verify_report_signature(evidence: &SnpEvidence) -> Result<()> { + // check cert chain + let vcek = verify_cert_chain(&evidence.cert_chain)?; + + // OpenSSL bindings do not expose custom extensions + // Parse the vcek using x509_parser + let vcek_der = &vcek.to_der()?; + let parsed_vcek = X509Certificate::from_der(vcek_der)?.1.tbs_certificate; + + // verify vcek fields + // chip id + if get_oid::<64>(&parsed_vcek, HW_ID_OID)? != evidence.attestation_report.chip_id { + return Err(anyhow!("Chip ID mismatch")); + } + + // tcb version + // these integer extensions are 3 bytes with the last byte as the data + if get_oid_int(&parsed_vcek, UCODE_SPL_OID)? + != evidence.attestation_report.reported_tcb.microcode + { + return Err(anyhow!("Microcode verion mismatch")); + } + + if get_oid_int(&parsed_vcek, SNP_SPL_OID)? != evidence.attestation_report.reported_tcb.snp { + return Err(anyhow!("SNP verion mismatch")); + } + + if get_oid_int(&parsed_vcek, TEE_SPL_OID)? != evidence.attestation_report.reported_tcb.tee { + return Err(anyhow!("TEE verion mismatch")); + } + + if get_oid_int(&parsed_vcek, LOADER_SPL_OID)? + != evidence.attestation_report.reported_tcb.boot_loader + { + return Err(anyhow!("Boot loader verion mismatch")); + } + + // verify report signature + let sig = ecdsa::EcdsaSig::try_from(&evidence.attestation_report.signature)?; + let data = &bincode::serialize(&evidence.attestation_report)?[..=0x29f]; + + sig.verify(data, EcKey::try_from(vcek.public_key()?)?.as_ref()) + .context("Signature validation failed.")?; + + Ok(()) +} + +fn load_milan_cert_chain() -> Result<(x509::X509, x509::X509)> { + let certs = x509::X509::stack_from_pem(include_bytes!("milan_ask_ark.pem"))?; + if certs.len() != 2 { + bail!("Malformed Milan ASK/ARK"); + } + + // ask, ark + Ok((certs[0].clone(), certs[1].clone())) +} + +fn verify_cert_chain(cert_chain: &[CertTableEntry]) -> Result { + let (ask, ark) = load_milan_cert_chain()?; + + let raw_vcek = cert_chain + .iter() + .find(|c| c.cert_type == SnpCertType::VCEK) + .ok_or_else(|| anyhow!("VCEK not found."))?; + let vcek = x509::X509::from_der(raw_vcek.data()).context("Failed to load VCEK")?; + + // ARK -> ARK + ark.verify(&(ark.public_key().unwrap() as PKey)) + .context("Invalid ARK Signature")?; + + // ARK -> ASK + ask.verify(&(ark.public_key()? as PKey)) + .context("Invalid ASK Signature")?; + + // ASK -> VCEK + vcek.verify(&(ask.public_key()? as PKey)) + .context("Invalid VCEK Signature")?; + + Ok(vcek) +} + +fn calculate_expected_report_data(nonce: &String, tee_pubkey: &TeePubKey) -> [u8; 64] { + let mut hasher = Sha384::new(); + + hasher.update(nonce.as_bytes()); + hasher.update(&tee_pubkey.k_mod); + hasher.update(&tee_pubkey.k_exp); + + let partial_hash = hasher.finalize(); + + let mut hash = [0u8; 64]; + hash[..48].copy_from_slice(&partial_hash); + + hash +} + +fn parse_tee_evidence(report: &AttestationReport) -> TeeEvidenceParsedClaim { + let claims_map = json!({ + // policy fields + "policy_abi_major": format!("{}",report.policy.abi_major()), + "policy_abi_minor": format!("{}", report.policy.abi_minor()), + "policy_smt_allowed": format!("{}", report.policy.smt_allowed()), + "policy_migrate_ma": format!("{}", report.policy.migrate_ma_allowed()), + "policy_debug_allowed": format!("{}", report.policy.debug_allowed()), + "policy_single_socket": format!("{}", report.policy.single_socket_required()), + + // versioning info + "reported_tcb_bootloader": format!("{}", report.reported_tcb.boot_loader), + "reported_tcb_tee": format!("{}", report.reported_tcb.tee), + "reported_tcb_snp": format!("{}", report.reported_tcb.snp), + "reported_tcb_microcode": format!("{}", report.reported_tcb.microcode), + + // platform info + "platform_tsme_enabled": format!("{}", report.plat_info.tsme_enabled()), + "platform_smt_enabled": format!("{}", report.plat_info.smt_enabled()), + + // measurement + "measurement": format!("{}", base64::encode(report.measurement)), + }); + + claims_map as TeeEvidenceParsedClaim +} + +#[cfg(test)] +mod tests { + use super::*; + use openssl::nid::Nid; + use sev::firmware::host::types::CertTableEntry; + + #[test] + fn check_milan_certificates() { + let (ask, ark) = load_milan_cert_chain().unwrap(); + assert_eq!(get_common_name(&ark).unwrap(), "ARK-Milan"); + assert_eq!(get_common_name(&ask).unwrap(), "SEV-Milan"); + + assert!(ark + .verify(&(ark.public_key().unwrap() as PKey)) + .context("Invalid ARK Signature") + .unwrap()); + + assert!(ask + .verify(&(ark.public_key().unwrap() as PKey)) + .context("Invalid ASK Signature") + .unwrap()); + } + + fn get_common_name(cert: &x509::X509) -> Result { + let mut entries = cert.subject_name().entries_by_nid(Nid::COMMONNAME); + + if let Some(e) = entries.next() { + assert_eq!(entries.count(), 0); + return Ok(e.data().as_utf8()?.to_string()); + } + Err(anyhow!("No CN found")) + } + + #[test] + fn check_vcek_parsing() { + let vcek_der = include_bytes!("test-vcek.der"); + let parsed_vcek = X509Certificate::from_der(vcek_der) + .unwrap() + .1 + .tbs_certificate; + + get_oid::<64>(&parsed_vcek, HW_ID_OID).unwrap(); + let oids = vec![UCODE_SPL_OID, SNP_SPL_OID, TEE_SPL_OID, LOADER_SPL_OID]; + for oid in oids { + get_oid_int(&parsed_vcek, oid).unwrap(); + } + } + + #[test] + fn check_vcek_signature_verification() { + let vcek = include_bytes!("test-vcek.der").to_vec(); + let cert_table = vec![CertTableEntry::new(SnpCertType::VCEK, vcek)]; + verify_cert_chain(&cert_table).unwrap(); + } + + #[test] + fn check_vcek_signature_failure() { + let mut vcek = include_bytes!("test-vcek.der").to_vec(); + + // corrupt some byte + vcek[7] += 1; + + let cert_table = vec![CertTableEntry::new(SnpCertType::VCEK, vcek)]; + assert!(verify_cert_chain(&cert_table).is_err()); + } +} diff --git a/attestation-service/src/verifier/snp/test-vcek.der b/attestation-service/src/verifier/snp/test-vcek.der new file mode 100644 index 0000000000000000000000000000000000000000..7fab200f41f03b324c9bbe169fb311a5990425b3 GIT binary patch literal 1360 zcmXqLV)Zd-V*0&+nTe5!iIKs;jg3>Q&7$*l(NLUIdNViBSRxY6GICFGh@prAlDL!YfuHVnbwXIG~kCg zjsxVlFlSe9gEF9d*?~cP&X$Rhja9pmg+YlqiGgKS9ow5_3*G*v#BR?|xBT_uuLb9! zxIZTopZLE&lN}*4Rs5^+7H1wo#}bZrk|`HbpSp8oRq$*GQqS@+Jyfe68tB28VCR44 zuC~y;2gW&jW|f?`?6+sxDkh|SV;$EF?RD!HH!+GCG%t7;4sv6GB6NiE`Jg8tWC&-)xq7bH)RKK#Ee+Uv%V-UW_3k8Yk**ksL|!+dMK z+F9?rDSj_9u9w9I^_G45?f(11@i1y7dFCcyU>e_?n_PLII9K$>#~+8pWIrmc=6PkG z?WI`l8rZ3BJlFZb9Ph`myptQ<-Z>nQjpupT70*#=HLF~c`Nj1`{)byXC57JV^H54^ z{jhfR`6sID*Z(;6c9QAx5}CUbudvM#&(1nI@2T#m2m5AnoIdt+uG;!pE7|@=E&o(L zb@SX=mp)ou^r@e7Jo4C?FTu0&f6ZpucjEg4d*6yvOdcC&ARox zTdaLXMRURaBWmU0(?b1nS1niFpcSvIurW;5%fmlg;@^>VmllfrJaDn@Qa1MLT}%@v$8G+F77s%KSlq;vsGKqSS&kQq`&5G z)wjjBH?lsx(xtd1OPI~)T>R&Q7kB?Ot6e0sH*EQu7wxIri!xq4z5Y}Dd#Kim2ht^{ z&fPwv9br7Ms(F~b8DN4i5sRw9@jZ0x#ZIc+s{2`QVzYb33iK3ePZW5G4+ts z>ENX73WbuG>sm_}w0N%G`gi)3+toGVq23ZV8?Rd54Qt~3Uc5VPFN3zktToy`iYh_? De74A# literal 0 HcmV?d00001