From 0a907d43ceac3e3dcd03c22aa399057f6d409685 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Thu, 1 Aug 2024 00:05:23 -0700 Subject: [PATCH] examples: adds an agent storing keys on TPMs Signed-off-by: Arthur Gautier --- Cargo.lock | 494 +++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 7 + examples/tpm-backed.rs | 156 +++++++++++++ 3 files changed, 639 insertions(+), 18 deletions(-) create mode 100644 examples/tpm-backed.rs diff --git a/Cargo.lock b/Cargo.lock index ae5b00b..e71e1f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,7 +171,16 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", ] [[package]] @@ -213,6 +222,29 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bindgen" +version = "0.66.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.66", + "which", +] + [[package]] name = "bitfield" version = "0.14.0" @@ -225,6 +257,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "blake2" version = "0.10.6" @@ -350,6 +388,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfb-mode" version = "0.8.2" @@ -389,6 +436,17 @@ dependencies = [ "inout", ] +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.7" @@ -420,7 +478,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -440,6 +498,12 @@ dependencies = [ "digest", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "colorchoice" version = "1.0.1" @@ -488,6 +552,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -544,7 +614,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -568,7 +638,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.66", ] [[package]] @@ -579,7 +649,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -598,10 +668,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" 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.66", +] + [[package]] name = "derive_builder" version = "0.20.0" @@ -620,7 +703,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -630,7 +713,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn", + "syn 2.0.66", ] [[package]] @@ -727,6 +810,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -748,6 +837,32 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "env_filter" version = "0.1.0" @@ -777,6 +892,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -799,6 +924,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +[[package]] +name = "flagset" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" + [[package]] name = "flate2" version = "1.0.30" @@ -871,7 +1002,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -965,12 +1096,35 @@ dependencies = [ "subtle", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin 0.9.8", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -1019,6 +1173,21 @@ dependencies = [ "digest", ] +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "hostname-validator" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" + [[package]] name = "humantime" version = "2.1.0" @@ -1163,9 +1332,15 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "spin", + "spin 0.5.2", ] +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.155" @@ -1183,18 +1358,50 @@ dependencies = [ "once_cell", ] +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.5", +] + [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "malloced" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dfebb2f9e0b39509c62eead6ec7ae0c0ed45bb61d12bbcf4e976c566c5400ec" + [[package]] name = "md-5" version = "0.10.6" @@ -1265,6 +1472,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-derive" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -1323,7 +1541,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -1375,6 +1593,30 @@ dependencies = [ "thiserror", ] +[[package]] +name = "p192" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0533bc6c238f2669aab8db75ae52879dc74e88d6bd3685bd4022a00fa85cd2" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sec1", +] + +[[package]] +name = "p224" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30c06436d66652bc2f01ade021592c80a2aad401570a18aa18b82e440d2b9aa1" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "p256" version = "0.13.2" @@ -1424,13 +1666,19 @@ dependencies = [ "subtle", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pcsc" version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ed9d7f816b7d9ce9ddb0062dd2f393b3af31411a95a35411809b4b9116ea08" dependencies = [ - "bitflags", + "bitflags 1.3.2", "pcsc-sys", ] @@ -1443,6 +1691,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -1567,12 +1821,34 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "heapless", + "serde", +] + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "prettyplease" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +dependencies = [ + "proc-macro2", + "syn 2.0.66", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -1768,7 +2044,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn", + "syn 2.0.66", "unicode-ident", ] @@ -1778,6 +2054,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1787,6 +2069,25 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sec1" version = "0.7.3" @@ -1833,7 +2134,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -1887,6 +2188,12 @@ 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 = "2.2.0" @@ -1906,6 +2213,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sm2" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b22092ef242a118f03ee41dc46b2720c0ca076f544116dbc915cacf532cfaa" +dependencies = [ + "elliptic-curve", + "primeorder", + "rfc6979", + "signature", + "sm3", +] + +[[package]] +name = "sm3" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebb9a3b702d0a7e33bc4d85a14456633d2b165c2ad839c5fd9a8417c1ab15860" +dependencies = [ + "digest", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -1928,6 +2257,15 @@ 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" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.7.3" @@ -1956,6 +2294,7 @@ dependencies = [ "openpgp-card", "p256", "pgp", + "postcard", "rand", "retainer", "rsa", @@ -1963,6 +2302,7 @@ dependencies = [ "secrecy", "service-binding", "sha1", + "sha2", "signature", "ssh-encoding", "ssh-key", @@ -1971,6 +2311,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", + "tss-esapi", ] [[package]] @@ -2025,6 +2366,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -2037,6 +2384,17 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.66" @@ -2048,6 +2406,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "testresult" version = "0.4.0" @@ -2071,7 +2435,28 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", +] + +[[package]] +name = "tls_codec" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e78c9c330f8c85b2bae7c8368f2739157db9991235123aa1b15ef9502bfb6a" +dependencies = [ + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9ef545650e79f30233c0003bcc2504d7efac6dad25fca40744de773fe2049c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", ] [[package]] @@ -2098,7 +2483,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] [[package]] @@ -2131,6 +2516,55 @@ dependencies = [ "winnow", ] +[[package]] +name = "tss-esapi" +version = "8.0.0-alpha" +source = "git+https://github.com/baloo/rust-tss-esapi.git?branch=baloo/rust-crypto/signer-interface#336466d3f925d73cb689dc78f39a4de76b84e8f6" +dependencies = [ + "bitfield", + "cfg-if", + "digest", + "elliptic-curve", + "enumflags2", + "getrandom", + "hostname-validator", + "log", + "malloced", + "num-derive", + "num-traits", + "p192", + "p224", + "p256", + "p384", + "p521", + "paste", + "regex", + "rsa", + "semver", + "serde", + "sha1", + "sha2", + "sha3", + "signature", + "sm2", + "sm3", + "tss-esapi-sys", + "x509-cert", + "zeroize", +] + +[[package]] +name = "tss-esapi-sys" +version = "0.5.0" +source = "git+https://github.com/baloo/rust-tss-esapi.git?branch=baloo/rust-crypto/signer-interface#336466d3f925d73cb689dc78f39a4de76b84e8f6" +dependencies = [ + "bindgen", + "cfg-if", + "pkg-config", + "semver", + "target-lexicon", +] + [[package]] name = "twofish" version = "0.7.1" @@ -2207,7 +2641,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -2229,7 +2663,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2240,6 +2674,18 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "widestring" version = "1.1.0" @@ -2437,6 +2883,18 @@ dependencies = [ "zeroize", ] +[[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", + "tls_codec", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -2454,5 +2912,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.66", ] diff --git a/Cargo.toml b/Cargo.toml index 0bc9150..4c14e62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ rand = "0.8.5" rsa = { version = "0.9.6", features = ["sha2", "sha1"] } tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync"] } sha1 = { version = "0.10.6", default-features = false, features = ["oid"] } +sha2 = { version = "0.10.6", default-features = false } testresult = "0.4.0" hex-literal = "0.4.1" ssh-key = { version = "0.6.6", features = ["p256", "rsa"] } @@ -58,3 +59,9 @@ retainer = "0.3.0" pgp = "0.13.0" chrono = "0.4.38" interprocess = "2.2.0" +tss-esapi = { version = "8.0.0-alpha", features = ["generate-bindings", "abstraction", "serde"] } +postcard = { version = "1.0.8", features = ["use-std"] } + +[patch.crates-io] +tss-esapi = { git = "https://github.com/baloo/rust-tss-esapi.git", branch = "baloo/rust-crypto/signer-interface" } +tss-esapi-sys = { git = "https://github.com/baloo/rust-tss-esapi.git", branch = "baloo/rust-crypto/signer-interface" } diff --git a/examples/tpm-backed.rs b/examples/tpm-backed.rs new file mode 100644 index 0000000..684f8db --- /dev/null +++ b/examples/tpm-backed.rs @@ -0,0 +1,156 @@ +#![cfg(not(windows))] +//! TPM-backed storage for SSH keys + +use std::{fs::File, mem, path::PathBuf, sync::Arc}; + +use async_trait::async_trait; +use clap::{Parser, Subcommand}; +use p256::{ecdsa::signature::DigestSigner, NistP256}; +use sha2::{Digest as _, Sha256}; +use ssh_key::{ + public::{EcdsaPublicKey, KeyData}, + Signature, +}; +use tokio::net::UnixListener as Listener; +use tss_esapi::{ + abstraction::transient::{Ecdsa, TransientKeyContextBuilder}, + TctiNameConf, +}; + +use ssh_agent_lib::{ + agent::{listen, Session}, + error::AgentError, + proto::{message, Extension, SignRequest}, +}; + +#[derive(Subcommand, Default, Debug)] +enum Command { + /// Run the agent with the key stored in the TPM. + #[default] + Run, + /// Generate a key on the TPM and store the encrypted private material in the state file. + /// + /// The private material is stored on a storage key of the TPM. + GenerateKey, +} + +#[derive(Debug, Parser)] +struct Args { + /// File where the encrypted private material are to be stored + #[arg(short, long)] + state_file: PathBuf, + + /// Path to the listening socket of the ssh agent + #[arg(short, long, default_value = "ssh-agent.sock")] + agent_sock: PathBuf, + + #[command(subcommand)] + command: Command, +} + +#[derive(Debug)] +struct Inner { + signer: Ecdsa<'static, NistP256>, +} + +#[derive(Clone, Debug)] +struct TpmBackend { + inner: Arc, +} + +impl TpmBackend { + fn new(signer: Ecdsa<'static, NistP256>) -> Self { + let inner = Inner { signer }; + + Self { + inner: Arc::new(inner), + } + } +} + +#[crate::async_trait] +impl Session for TpmBackend { + async fn sign(&mut self, sign_request: SignRequest) -> Result { + let data = &sign_request.data; + let inner: &Inner = &self.inner; + + let signer_key: &p256::ecdsa::VerifyingKey = inner.signer.as_ref(); + let public_key = EcdsaPublicKey::from(signer_key); + + if sign_request.pubkey == KeyData::from(public_key) { + let mut hash = Sha256::new(); + hash.update(data); + + let signature: p256::ecdsa::Signature = inner + .signer + .try_sign_digest(hash) + .map_err(AgentError::other)?; + + Ok(Signature::try_from(signature).map_err(AgentError::other)?) + } else { + Err(std::io::Error::other("Failed to create signature: identity not found").into()) + } + } + + async fn request_identities(&mut self) -> Result, AgentError> { + let inner: &Inner = &self.inner; + + let signer_key: &p256::ecdsa::VerifyingKey = inner.signer.as_ref(); + let public_key = EcdsaPublicKey::from(signer_key); + + Ok(vec![message::Identity { + pubkey: public_key.into(), + comment: "tpm backed key".to_string(), + }]) + } + + async fn extension(&mut self, _extension: Extension) -> Result, AgentError> { + Ok(None) + } +} + +#[tokio::main] +async fn main() -> Result<(), AgentError> { + env_logger::init(); + let args = Args::parse(); + + let _ = std::fs::remove_file(&args.agent_sock); // remove the socket if exists + + let conf = TctiNameConf::from_environment_variable() + .expect("Failed to get TCTI / TPM2TOOLS_TCTI from environment. Try `export TCTI=device:/dev/tpmrm0`"); + let mut ctx = TransientKeyContextBuilder::new() + .with_tcti(conf) + .build() + .map_err(AgentError::other)?; + + match args.command { + Command::GenerateKey => { + let (tpm_km, _tpm_auth) = ctx + .create_key(Ecdsa::::key_params_default(), 0) + .map_err(AgentError::other)?; + + let mut f = File::create(args.state_file)?; + postcard::to_io(&tpm_km, &mut f).map_err(AgentError::other)?; + Ok(()) + } + Command::Run => { + let tpm_km = { + let mut buf = [0; 1024]; + let mut f = File::open(args.state_file)?; + let (out, _) = postcard::from_io((&mut f, &mut buf)).map_err(AgentError::other)?; + out + }; + + let signer = + Ecdsa::::new(&mut ctx, tpm_km, None).map_err(AgentError::other)?; + + // async_trait does not allow us to specify a lifetime for the context + // we'll downcast the context to a 'static lifetime instead. + // This is acceptable as the context continues to live beyond the lifetime of the server + let signer = unsafe { mem::transmute(signer) }; + + listen(Listener::bind(args.agent_sock)?, TpmBackend::new(signer)).await?; + Ok(()) + } + } +}