From 29464612ded4eeaa1b898158c8352f4315b8791b Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:28:29 +0800 Subject: [PATCH 01/38] refactor the whole structure --- Cargo.lock | 232 +++++++++++++++++++++-------------- Cargo.toml | 22 ++-- src/aead/chacha20.rs | 197 +----------------------------- src/aead/chacha20/tls12.rs | 106 ++++++++++++++++ src/aead/chacha20/tls13.rs | 94 ++++++++++++++ src/aead/gcm.rs | 236 +----------------------------------- src/aead/gcm/tls12.rs | 136 +++++++++++++++++++++ src/aead/gcm/tls13.rs | 93 ++++++++++++++ src/kx.rs | 111 +---------------- src/kx/nist.rs | 64 ++++++++++ src/kx/x25519.rs | 47 +++++++ src/lib.rs | 207 ++++--------------------------- src/quic.rs | 142 ---------------------- src/sign/ecdsa.rs | 68 +---------- src/sign/ecdsa/nist.rs | 67 ++++++++++ src/sign/eddsa.rs | 59 +-------- src/sign/eddsa/ed25519.rs | 50 ++++++++ src/sign/rsa.rs | 13 +- src/tls12.rs | 16 +++ src/tls12/ecdsa.rs | 52 ++++++++ src/tls12/rsa.rs | 52 ++++++++ src/tls12/schemes.rs | 16 +++ src/tls13.rs | 14 +++ src/tls13/aes.rs | 31 +++++ src/tls13/chacha20.rs | 16 +++ src/verify.rs | 32 ++++- src/verify/ecdsa.rs | 56 +-------- src/verify/ecdsa/nist.rs | 59 +++++++++ src/verify/eddsa.rs | 35 +----- src/verify/eddsa/ed25519.rs | 42 +++++++ src/verify/rsa.rs | 19 ++- 31 files changed, 1206 insertions(+), 1178 deletions(-) create mode 100644 src/aead/chacha20/tls12.rs create mode 100644 src/aead/chacha20/tls13.rs create mode 100644 src/aead/gcm/tls12.rs create mode 100644 src/aead/gcm/tls13.rs create mode 100644 src/kx/nist.rs create mode 100644 src/kx/x25519.rs delete mode 100644 src/quic.rs create mode 100644 src/sign/ecdsa/nist.rs create mode 100644 src/sign/eddsa/ed25519.rs create mode 100644 src/tls12.rs create mode 100644 src/tls12/ecdsa.rs create mode 100644 src/tls12/rsa.rs create mode 100644 src/tls12/schemes.rs create mode 100644 src/tls13.rs create mode 100644 src/tls13/aes.rs create mode 100644 src/tls13/chacha20.rs create mode 100644 src/verify/ecdsa/nist.rs create mode 100644 src/verify/eddsa/ed25519.rs diff --git a/Cargo.lock b/Cargo.lock index 3e1d73e..240d64b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base16ct" @@ -72,9 +72,12 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.90" +version = "1.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -125,9 +128,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -165,16 +168,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -202,6 +204,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + [[package]] name = "digest" version = "0.10.7" @@ -285,9 +308,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "generic-array" @@ -302,9 +325,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -361,18 +384,18 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libm" @@ -382,9 +405,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "num-bigint-dig" @@ -414,9 +437,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -425,9 +448,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -471,9 +494,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem-rfc7468" @@ -516,12 +539,6 @@ dependencies = [ "spki", ] -[[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - [[package]] name = "poly1305" version = "0.8.0" @@ -547,9 +564,12 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "primeorder" @@ -562,18 +582,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -627,7 +647,7 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", "windows-sys", ] @@ -655,18 +675,18 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustls" -version = "0.23.2" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbdb5ddfafe3040e01fe9dced711e27b5336ac97d4a9b2089f0066a04b5846" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "log", "once_cell", @@ -678,19 +698,20 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-rustcrypto" -version = "0.0.1-alpha" +version = "0.0.2-alpha" dependencies = [ "aead", "aes-gcm", "chacha20poly1305", "crypto-common", "der", + "derive_more", "digest", "ecdsa", "ed25519-dalek", @@ -699,6 +720,7 @@ dependencies = [ "p256", "p384", "paste", + "pkcs1", "pkcs8", "rand_core", "rsa", @@ -713,9 +735,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -738,24 +760,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -773,6 +795,12 @@ dependencies = [ "digest", ] +[[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" @@ -785,15 +813,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" - -[[package]] -name = "spin" -version = "0.5.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "spin" @@ -813,15 +835,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.52" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -836,9 +858,15 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -858,9 +886,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -879,13 +907,14 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +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", @@ -894,45 +923,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +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 = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "x25519-dalek" @@ -945,11 +980,32 @@ dependencies = [ "zeroize", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 6ff6103..5b00616 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,22 +23,24 @@ aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "al chacha20poly1305 = { version = "0.10.1", default-features = false } crypto-common = { version = "0.1.6", default-features = false } der = { version = "0.7.9", default-features = false } +derive_more = { version = "1.0.0", default-features = false, features = ["display", "debug", "deref", "from", "into", "error"] } digest = { version = "0.10.7", default-features = false } -ecdsa = { version = "0.16.8", default-features = false, features = ["alloc"] } +ecdsa = { version = "0.16.9", default-features = false, features = ["alloc"] } ed25519-dalek = { version = "2", default-features = false, features = ["pkcs8"] } hmac = { version = "0.12.1", default-features = false } p256 = { version = "0.13.2", default-features = false, features = ["pem", "ecdsa", "ecdh"] } p384 = { version = "0.13.0", default-features = false, features = ["pem", "ecdsa", "ecdh"] } -paste = { version = "1.0.14", default-features = false } +paste = { version = "1.0.15", default-features = false } +pkcs1 = { version = "0.7.5", default-features = false } pkcs8 = { version = "0.10.2", default-features = false, features = ["pem", "pkcs5"] } -pki-types = { package = "rustls-pki-types", version = "1.0.1", default-features = false } +pki-types = { package = "rustls-pki-types", version = "1.8.0", default-features = false } rand_core = { version = "0.6.4", default-features = false, features = ["getrandom"] } -rsa = { version = "0.9.2", default-features = false, features = ["sha2"] } -rustls = { version = "0.23.0", default-features = false } +rsa = { version = "0.9.6", default-features = false, features = ["sha2"] } +rustls = { version = "0.23.13", default-features = false } sec1 = { version = "0.7.3", default-features = false, features = ["pkcs8", "pem"] } -sha2 = { version = "0.10.7", default-features = false } -signature = { version = "2.1.0", default-features = false } -webpki = { package = "rustls-webpki", version = "0.102.0", default-features = false } +sha2 = { version = "0.10.8", default-features = false } +signature = { version = "2.2.0", default-features = false } +webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false } x25519-dalek = { version = "2", default-features = false } [dev-dependencies] @@ -53,7 +55,7 @@ tls12 = ["rustls/tls12"] # zeroize is another typical that can be turned off # TODO: go through all of these that what gets exposed re: std error type -std = ["alloc", "webpki/std", "pki-types/std", "rustls/std", "ed25519-dalek/std"] +std = ["alloc", "webpki/std", "pki-types/std", "rustls/std", "ed25519-dalek/std", "pkcs1/std"] # TODO: go through all of these to ensure to_vec etc. impls are exposed -alloc = ["webpki/alloc", "pki-types/alloc", "aead/alloc", "ed25519-dalek/alloc"] +alloc = ["webpki/alloc", "pki-types/alloc", "aead/alloc", "ed25519-dalek/alloc", "pkcs1/alloc"] zeroize = ["ed25519-dalek/zeroize", "x25519-dalek/zeroize"] diff --git a/src/aead/chacha20.rs b/src/aead/chacha20.rs index 995b79e..d9f3216 100644 --- a/src/aead/chacha20.rs +++ b/src/aead/chacha20.rs @@ -1,197 +1,8 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use super::{DecryptBufferAdapter, EncryptBufferAdapter}; - -use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; -use rustls::crypto::cipher::{ - self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, - MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, - Tls13AeadAlgorithm, UnsupportedOperationError, -}; -use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; - -#[cfg(feature = "tls12")] -use rustls::crypto::cipher::{KeyBlockShape, Tls12AeadAlgorithm, NONCE_LEN}; - -pub struct Chacha20Poly1305; - -impl Tls13AeadAlgorithm for Chacha20Poly1305 { - fn encrypter(&self, key: AeadKey, iv: Iv) -> Box { - Box::new(Tls13Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - iv, - )) - } - - fn decrypter(&self, key: AeadKey, iv: Iv) -> Box { - Box::new(Tls13Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - iv, - )) - } - - fn key_len(&self) -> usize { - chacha20poly1305::ChaCha20Poly1305::key_size() - } - - fn extract_keys( - &self, - key: AeadKey, - iv: Iv, - ) -> Result { - Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }) - } -} - -#[cfg(feature = "tls12")] -impl Tls12AeadAlgorithm for Chacha20Poly1305 { - fn encrypter(&self, key: AeadKey, iv: &[u8], _: &[u8]) -> Box { - Box::new(Tls12Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - Iv::copy(iv), - )) - } - - fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box { - Box::new(Tls12Cipher( - chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - Iv::copy(iv), - )) - } - - fn key_block_shape(&self) -> KeyBlockShape { - KeyBlockShape { - enc_key_len: 32, - fixed_iv_len: 12, - explicit_nonce_len: 0, - } - } - - fn extract_keys( - &self, - key: AeadKey, - iv: &[u8], - _explicit: &[u8], - ) -> Result { - // This should always be true because KeyBlockShape and the Iv nonce len are in - // agreement. - debug_assert_eq!(NONCE_LEN, iv.len()); - Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { - key, - iv: Iv::new(iv[..].try_into().expect("conversion should succeed")), - }) - } -} - -struct Tls13Cipher(chacha20poly1305::ChaCha20Poly1305, Iv); - -impl MessageEncrypter for Tls13Cipher { - fn encrypt( - &mut self, - m: OutboundPlainMessage<'_>, - seq: u64, - ) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - payload.extend_from_chunks(&m.payload); - payload.extend_from_slice(&m.typ.to_array()); - - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls13_aad(total_len); - - self.0 - .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|()| { - OutboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_2, - payload, - ) - }) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + 1 + CHACHAPOLY1305_OVERHEAD - } -} - -impl MessageDecrypter for Tls13Cipher { - fn decrypt<'a>( - &mut self, - mut m: InboundOpaqueMessage<'a>, - seq: u64, - ) -> Result, rustls::Error> { - let payload = &mut m.payload; - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls13_aad(payload.len()); - - self.0 - .decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; - - m.into_tls13_unpadded_message() - } -} - -#[cfg(feature = "tls12")] -struct Tls12Cipher(chacha20poly1305::ChaCha20Poly1305, Iv); - -#[cfg(feature = "tls12")] -impl MessageEncrypter for Tls12Cipher { - fn encrypt( - &mut self, - m: OutboundPlainMessage<'_>, - seq: u64, - ) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - payload.extend_from_chunks(&m.payload); - - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls12_aad(seq, m.typ, m.version, m.payload.len()); - - self.0 - .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) - } +const CHACHAPOLY1305_OVERHEAD: usize = 16; - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + CHACHAPOLY1305_OVERHEAD - } -} +pub struct ChaCha20Poly1305; #[cfg(feature = "tls12")] -impl MessageDecrypter for Tls12Cipher { - fn decrypt<'a>( - &mut self, - mut m: InboundOpaqueMessage<'a>, - seq: u64, - ) -> Result, rustls::Error> { - let payload = &m.payload; - let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); - let aad = cipher::make_tls12_aad( - seq, - m.typ, - m.version, - payload.len() - CHACHAPOLY1305_OVERHEAD, - ); - - let payload = &mut m.payload; - self.0 - .decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; +pub mod tls12; - Ok(m.into_plain_message()) - } -} - -const CHACHAPOLY1305_OVERHEAD: usize = 16; +pub mod tls13; diff --git a/src/aead/chacha20/tls12.rs b/src/aead/chacha20/tls12.rs new file mode 100644 index 0000000..e93e293 --- /dev/null +++ b/src/aead/chacha20/tls12.rs @@ -0,0 +1,106 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; +use chacha20poly1305::{AeadInPlace, KeyInit}; +use rustls::crypto::cipher::{ + self, make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + UnsupportedOperationError, +}; +use rustls::crypto::cipher::{KeyBlockShape, Tls12AeadAlgorithm, NONCE_LEN}; +use rustls::ConnectionTrafficSecrets; + +use super::{ChaCha20Poly1305, CHACHAPOLY1305_OVERHEAD}; + +struct CipherAdapter(chacha20poly1305::ChaCha20Poly1305, Iv); + +impl Tls12AeadAlgorithm for ChaCha20Poly1305 { + fn encrypter(&self, key: AeadKey, iv: &[u8], _: &[u8]) -> Box { + Box::new(CipherAdapter( + chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) + .expect("key should be valid"), + Iv::copy(iv), + )) + } + + fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box { + Box::new(CipherAdapter( + chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) + .expect("key should be valid"), + Iv::copy(iv), + )) + } + + fn key_block_shape(&self) -> KeyBlockShape { + KeyBlockShape { + enc_key_len: 32, + fixed_iv_len: 12, + explicit_nonce_len: 0, + } + } + + fn extract_keys( + &self, + key: AeadKey, + iv: &[u8], + _explicit: &[u8], + ) -> Result { + // This should always be true because KeyBlockShape and the Iv nonce len are in + // agreement. + debug_assert_eq!(NONCE_LEN, iv.len()); + Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { + key, + iv: Iv::new(iv[..].try_into().expect("conversion should succeed")), + }) + } +} + +impl MessageEncrypter for CipherAdapter { + fn encrypt( + &mut self, + m: OutboundPlainMessage<'_>, + seq: u64, + ) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + payload.extend_from_chunks(&m.payload); + + let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); + let aad = make_tls12_aad(seq, m.typ, m.version, m.payload.len()); + + self.0 + .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + CHACHAPOLY1305_OVERHEAD + } +} + +impl MessageDecrypter for CipherAdapter { + fn decrypt<'a>( + &mut self, + mut m: InboundOpaqueMessage<'a>, + seq: u64, + ) -> Result, rustls::Error> { + let payload = &m.payload; + let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); + let aad = make_tls12_aad( + seq, + m.typ, + m.version, + payload.len() - CHACHAPOLY1305_OVERHEAD, + ); + + let payload = &mut m.payload; + self.0 + .decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload)) + .map_err(|_| rustls::Error::DecryptError)?; + + Ok(m.into_plain_message()) + } +} diff --git a/src/aead/chacha20/tls13.rs b/src/aead/chacha20/tls13.rs new file mode 100644 index 0000000..ab7043b --- /dev/null +++ b/src/aead/chacha20/tls13.rs @@ -0,0 +1,94 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use super::{ChaCha20Poly1305, CHACHAPOLY1305_OVERHEAD}; +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; +use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; +use rustls::crypto::cipher::{ + self, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + Tls13AeadAlgorithm, UnsupportedOperationError, +}; +use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; + +impl Tls13AeadAlgorithm for ChaCha20Poly1305 { + fn encrypter(&self, key: AeadKey, iv: Iv) -> Box { + Box::new(CipherAdapter( + chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) + .expect("key should be valid"), + iv, + )) + } + + fn decrypter(&self, key: AeadKey, iv: Iv) -> Box { + Box::new(CipherAdapter( + chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) + .expect("key should be valid"), + iv, + )) + } + + fn key_len(&self) -> usize { + chacha20poly1305::ChaCha20Poly1305::key_size() + } + + fn extract_keys( + &self, + key: AeadKey, + iv: Iv, + ) -> Result { + Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }) + } +} + +struct CipherAdapter(chacha20poly1305::ChaCha20Poly1305, Iv); + +impl MessageEncrypter for CipherAdapter { + fn encrypt( + &mut self, + m: OutboundPlainMessage<'_>, + seq: u64, + ) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + payload.extend_from_chunks(&m.payload); + payload.extend_from_slice(&m.typ.to_array()); + + let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); + let aad = make_tls13_aad(total_len); + + self.0 + .encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload)) + .map_err(|_| rustls::Error::EncryptError) + .map(|()| { + OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + ) + }) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + 1 + CHACHAPOLY1305_OVERHEAD + } +} + +impl MessageDecrypter for CipherAdapter { + fn decrypt<'a>( + &mut self, + mut m: InboundOpaqueMessage<'a>, + seq: u64, + ) -> Result, rustls::Error> { + let payload = &mut m.payload; + let nonce: chacha20poly1305::Nonce = cipher::Nonce::new(&self.1, seq).0.into(); + let aad = make_tls13_aad(payload.len()); + + self.0 + .decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload)) + .map_err(|_| rustls::Error::DecryptError)?; + + m.into_tls13_unpadded_message() + } +} diff --git a/src/aead/gcm.rs b/src/aead/gcm.rs index 14be62b..90d635b 100644 --- a/src/aead/gcm.rs +++ b/src/aead/gcm.rs @@ -1,235 +1,7 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use super::{DecryptBufferAdapter, EncryptBufferAdapter}; - -use aead::AeadInPlace; -use crypto_common::{KeyInit, KeySizeUser}; -use paste::paste; -use rustls::crypto::cipher::{ - self, AeadKey, InboundOpaqueMessage, InboundPlainMessage, MessageDecrypter, MessageEncrypter, - OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, Tls13AeadAlgorithm, -}; -use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; - -#[cfg(feature = "tls12")] -use { - aead::AeadCore, - crypto_common::typenum::Unsigned, - rustls::crypto::cipher::{Iv, KeyBlockShape, Tls12AeadAlgorithm}, -}; - -#[cfg(feature = "tls12")] -const TLS12_GCM_EXPLICIT_NONCE_LEN: usize = 8; - -#[cfg(feature = "tls12")] -const TLS12_GCM_OVERHEAD: usize = TLS12_GCM_EXPLICIT_NONCE_LEN + 16; - -macro_rules! impl_gcm_tls13 { - ($name: ident, $aead: ty, $overhead: expr) => { - paste! { - pub struct []; - - impl Tls13AeadAlgorithm for [] { - fn encrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - iv, - )) - } - - fn decrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - iv, - )) - } - - fn key_len(&self) -> usize { - $aead::key_size() - } - fn extract_keys( - &self, - key: AeadKey, - iv: cipher::Iv, - ) -> Result { - Ok(ConnectionTrafficSecrets::Aes256Gcm { key, iv }) - } - } - - struct []($aead, cipher::Iv); - - impl MessageEncrypter for [] { - fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - let nonce = cipher::Nonce::new(&self.1, seq).0; - let aad = cipher::make_tls13_aad(total_len); - payload.extend_from_chunks(&m.payload); - payload.extend_from_slice(&m.typ.to_array()); - - self.0 - .encrypt_in_place(&nonce.into(), &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_2, - payload, - )) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + 1 + $overhead - } - } - - impl MessageDecrypter for [] { - fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { - let payload = &mut m.payload; - let nonce = cipher::Nonce::new(&self.1, seq).0; - let aad = cipher::make_tls13_aad(payload.len()); - - self.0 - .decrypt_in_place(&nonce.into(), &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; - - m.into_tls13_unpadded_message() - } - } - - } - }; -} +pub struct Aes128Gcm; +pub struct Aes256Gcm; #[cfg(feature = "tls12")] -macro_rules! impl_gcm_tls12 { - ($name: ident, $aead: ty, $nonce: expr, $overhead: expr) => { - paste! { - #[cfg(feature = "tls12")] - pub struct []; +pub mod tls12; - #[cfg(feature = "tls12")] - impl Tls12AeadAlgorithm for [] { - fn encrypter(&self, key: AeadKey, write_iv: &[u8], explicit: &[u8]) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - { - let mut iv: [u8; 12] = [0; 12]; - iv[..4].copy_from_slice(write_iv); - iv[4..].copy_from_slice(explicit); - iv - }, - )) - } - - fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { - Box::new([]( - $aead::new_from_slice(dec_key.as_ref()).unwrap(), - dec_iv.try_into().unwrap(), - )) - } - - fn key_block_shape(&self) -> KeyBlockShape { - KeyBlockShape { - enc_key_len: $aead::key_size(), - fixed_iv_len: 4, - explicit_nonce_len: 8, - } - } - - fn extract_keys( - &self, - key: AeadKey, - iv: &[u8], - _explicit: &[u8], - ) -> Result { - Ok(ConnectionTrafficSecrets::Aes128Gcm { - key, - iv: Iv::new(iv[..].try_into().unwrap()), - }) - } - } - - #[cfg(feature = "tls12")] - struct []($aead, [u8; 12]); - - #[cfg(feature = "tls12")] - impl MessageEncrypter for [] { - fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - let nonce = cipher::Nonce::new(&self.1.into(), seq).0; - let aad = cipher::make_tls12_aad(seq, m.typ, m.version, m.payload.len()); - payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit - payload.extend_from_chunks(&m.payload); - - self.0 - .encrypt_in_place_detached(&nonce.into(), &aad, &mut payload.as_mut()[$nonce..]) - .map(|tag| payload.extend(tag.as_ref() as &[u8])) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) - } - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + $nonce + <$aead as AeadCore>::TagSize::USIZE - } - } - - #[cfg(feature = "tls12")] - struct []($aead, [u8; 4]); - - #[cfg(feature = "tls12")] - impl MessageDecrypter for [] { - fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { - type TagSize = <$aead as AeadCore>::TagSize; - - let payload = &m.payload; - - if payload.len() < $overhead { - return Err(rustls::Error::DecryptError); - } - - let nonce: aead::Nonce<$aead> = { - let mut nonce = [0u8; 12]; - nonce[..4].copy_from_slice(&self.1); // dec_iv - nonce[4..].copy_from_slice(&payload[..$nonce]); - nonce.into() - }; - - let aad = cipher::make_tls12_aad(seq, m.typ, m.version, payload.len() - $overhead); - - let payload = &mut m.payload; - let tag_pos = { - let payload = &mut payload[$nonce..]; - let tag_pos = payload.len() - TagSize::to_usize(); - let (msg, tag) = payload.split_at_mut(tag_pos); - - let tag = aes_gcm::Tag::::from_slice(tag); - self.0 - .decrypt_in_place_detached(&nonce, &aad, msg, tag) - .map_err(|_| rustls::Error::DecryptError)?; - tag_pos - }; - - // We defer the truncation to here, because we may inadvertently shifted the - // original data if the decryption failed. Another way to avoid this is - // to clone the payload slice starting after the explicit nonce, - // but this will cause an additional cloning and copying - payload.rotate_left($nonce); - payload.truncate(tag_pos); - Ok(m.into_plain_message()) - } - } - } - }; -} - -impl_gcm_tls13! {Aes128Gcm, aes_gcm::Aes128Gcm, 16} -impl_gcm_tls13! {Aes256Gcm, aes_gcm::Aes256Gcm, 16} - -#[cfg(feature = "tls12")] -impl_gcm_tls12! {Aes128Gcm, aes_gcm::Aes128Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} - -#[cfg(feature = "tls12")] -impl_gcm_tls12! {Aes256Gcm, aes_gcm::Aes256Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} +pub mod tls13; diff --git a/src/aead/gcm/tls12.rs b/src/aead/gcm/tls12.rs new file mode 100644 index 0000000..16c10c9 --- /dev/null +++ b/src/aead/gcm/tls12.rs @@ -0,0 +1,136 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use aead::{AeadCore, AeadInPlace}; +use crypto_common::typenum::Unsigned; +use crypto_common::{KeyInit, KeySizeUser}; +use paste::paste; +use rustls::crypto::cipher::{ + self, make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, + MessageDecrypter, MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, + PrefixedPayload, Tls12AeadAlgorithm, +}; +use rustls::ConnectionTrafficSecrets; + +use super::{Aes128Gcm, Aes256Gcm}; + +const TLS12_GCM_EXPLICIT_NONCE_LEN: usize = 8; + +const TLS12_GCM_OVERHEAD: usize = TLS12_GCM_EXPLICIT_NONCE_LEN + 16; + +macro_rules! impl_gcm { + ($name: ident, $aead: ty, $nonce_pos: expr, $overhead: expr) => { + paste! { + impl Tls12AeadAlgorithm for $name { + fn encrypter(&self, key: AeadKey, write_iv: &[u8], explicit: &[u8]) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + { + let mut iv: [u8; 12] = [0; 12]; + iv[..4].copy_from_slice(write_iv); + iv[4..].copy_from_slice(explicit); + iv + }, + )) + } + + fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { + Box::new([]( + $aead::new_from_slice(dec_key.as_ref()).unwrap(), + dec_iv.try_into().unwrap(), + )) + } + + fn key_block_shape(&self) -> KeyBlockShape { + KeyBlockShape { + enc_key_len: $aead::key_size(), + fixed_iv_len: 4, + explicit_nonce_len: 8, + } + } + + fn extract_keys( + &self, + key: AeadKey, + iv: &[u8], + _explicit: &[u8], + ) -> Result { + Ok(ConnectionTrafficSecrets::$name { + key, + iv: Iv::new(iv[..].try_into().unwrap()), + }) + } + } + + struct []($aead, [u8; 12]); + + impl MessageEncrypter for [] { + fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + let nonce = cipher::Nonce::new(&self.1.into(), seq).0; + let aad = make_tls12_aad(seq, m.typ, m.version, m.payload.len()); + payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit + payload.extend_from_chunks(&m.payload); + + self.0 + .encrypt_in_place_detached(&nonce.into(), &aad, &mut payload.as_mut()[$nonce_pos..]) + .map(|tag| payload.extend(tag.as_ref() as &[u8])) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) + } + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + $nonce_pos + <$aead as AeadCore>::TagSize::USIZE + } + } + + struct []($aead, [u8; 4]); + + impl MessageDecrypter for [] { + fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { + type TagSize = <$aead as AeadCore>::TagSize; + + let payload = &m.payload; + + if payload.len() < $overhead { + return Err(rustls::Error::DecryptError); + } + + let nonce: aead::Nonce<$aead> = { + let mut nonce = [0u8; 12]; + nonce[..4].copy_from_slice(&self.1); // dec_iv + nonce[4..].copy_from_slice(&payload[..$nonce_pos]); + nonce.into() + }; + + let aad = make_tls12_aad(seq, m.typ, m.version, payload.len() - $overhead); + + let payload = &mut m.payload; + let tag_pos = { + let payload = &mut payload[$nonce_pos..]; + let tag_pos = payload.len() - TagSize::to_usize(); + let (msg, tag) = payload.split_at_mut(tag_pos); + + let tag = aes_gcm::Tag::::from_slice(tag); + self.0 + .decrypt_in_place_detached(&nonce, &aad, msg, tag) + .map_err(|_| rustls::Error::DecryptError)?; + tag_pos + }; + + // We defer the truncation to here, because we may inadvertently shifted the + // original data if the decryption failed. Another way to avoid this is + // to clone the payload slice starting after the explicit nonce, + // but this will cause an additional cloning and copying + payload.rotate_left($nonce_pos); + payload.truncate(tag_pos); + Ok(m.into_plain_message()) + } + } + } + }; +} + +impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} +impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} diff --git a/src/aead/gcm/tls13.rs b/src/aead/gcm/tls13.rs new file mode 100644 index 0000000..6a3c689 --- /dev/null +++ b/src/aead/gcm/tls13.rs @@ -0,0 +1,93 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use super::{Aes128Gcm, Aes256Gcm}; +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; +use aead::AeadInPlace; +use crypto_common::{KeyInit, KeySizeUser}; +use paste::paste; +use rustls::crypto::cipher::{ + self, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + Tls13AeadAlgorithm, +}; +use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; + +macro_rules! impl_gcm { + ($name: ident, $aead: ty, $overhead: expr) => { + paste! { + + impl Tls13AeadAlgorithm for $name { + fn encrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + iv, + )) + } + + fn decrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + iv, + )) + } + + fn key_len(&self) -> usize { + $aead::key_size() + } + fn extract_keys( + &self, + key: AeadKey, + iv: cipher::Iv, + ) -> Result { + Ok(ConnectionTrafficSecrets::$name { key, iv }) + } + } + + struct []($aead, cipher::Iv); + + impl MessageEncrypter for [] { + fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + let nonce = cipher::Nonce::new(&self.1, seq).0; + let aad = make_tls13_aad(total_len); + payload.extend_from_chunks(&m.payload); + payload.extend_from_slice(&m.typ.to_array()); + + self.0 + .encrypt_in_place(&nonce.into(), &aad, &mut EncryptBufferAdapter(&mut payload)) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + )) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + 1 + $overhead + } + } + + impl MessageDecrypter for [] { + fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { + let payload = &mut m.payload; + let nonce = cipher::Nonce::new(&self.1, seq).0; + let aad = make_tls13_aad(payload.len()); + + self.0 + .decrypt_in_place(&nonce.into(), &aad, &mut DecryptBufferAdapter(payload)) + .map_err(|_| rustls::Error::DecryptError)?; + + m.into_tls13_unpadded_message() + } + } + + } + }; +} + +impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, 16} +impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, 16} diff --git a/src/kx.rs b/src/kx.rs index 66341f2..23ad2bf 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -1,108 +1,9 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; +use rustls::crypto::SupportedKxGroup; -use crypto::{SharedSecret, SupportedKxGroup}; -use paste::paste; -use rustls::crypto; - -#[derive(Debug)] -pub struct X25519; - -impl crypto::SupportedKxGroup for X25519 { - fn name(&self) -> rustls::NamedGroup { - rustls::NamedGroup::X25519 - } - - fn start(&self) -> Result, rustls::Error> { - let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(rand_core::OsRng); - let pub_key = (&priv_key).into(); - Ok(Box::new(X25519KeyExchange { priv_key, pub_key })) - } -} - -pub struct X25519KeyExchange { - priv_key: x25519_dalek::EphemeralSecret, - pub_key: x25519_dalek::PublicKey, -} - -impl crypto::ActiveKeyExchange for X25519KeyExchange { - fn complete(self: Box, peer: &[u8]) -> Result { - let peer_array: [u8; 32] = peer - .try_into() - .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; - Ok(self - .priv_key - .diffie_hellman(&peer_array.into()) - .as_ref() - .into()) - } - - fn pub_key(&self) -> &[u8] { - self.pub_key.as_bytes() - } - - fn group(&self) -> rustls::NamedGroup { - X25519.name() - } -} - -macro_rules! impl_kx { - ($name:ident, $kx_name:ty, $secret:ty, $public_key:ty) => { - paste! { - - #[derive(Debug)] - #[allow(non_camel_case_types)] - pub struct $name; - - impl crypto::SupportedKxGroup for $name { - fn name(&self) -> rustls::NamedGroup { - $kx_name - } - - fn start(&self) -> Result, rustls::Error> { - let priv_key = $secret::random(&mut rand_core::OsRng); - let pub_key: $public_key = (&priv_key).into(); - Ok(Box::new([<$name KeyExchange>] { - priv_key, - pub_key: pub_key.to_sec1_bytes(), - })) - } - } - - #[allow(non_camel_case_types)] - pub struct [<$name KeyExchange>] { - priv_key: $secret, - pub_key: Box<[u8]>, - } - - impl crypto::ActiveKeyExchange for [<$name KeyExchange>] { - fn complete( - self: Box<[<$name KeyExchange>]>, - peer: &[u8], - ) -> Result { - let their_pub = $public_key::from_sec1_bytes(peer) - .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; - Ok(self - .priv_key - .diffie_hellman(&their_pub) - .raw_secret_bytes() - .as_slice() - .into()) - } - - fn pub_key(&self) -> &[u8] { - &self.pub_key - } - - fn group(&self) -> rustls::NamedGroup { - $name.name() - } - } - } - }; -} +pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1]; -impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, p256::ecdh::EphemeralSecret, p256::PublicKey} -impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, p384::ecdh::EphemeralSecret, p384::PublicKey} +mod nist; +mod x25519; -pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1]; +pub use nist::*; +pub use x25519::*; diff --git a/src/kx/nist.rs b/src/kx/nist.rs new file mode 100644 index 0000000..a9983bd --- /dev/null +++ b/src/kx/nist.rs @@ -0,0 +1,64 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crypto::{SharedSecret, SupportedKxGroup}; +use paste::paste; +use rustls::crypto; + +macro_rules! impl_kx { + ($name:ident, $kx_name:ty, $secret:ty, $public_key:ty) => { + paste! { + #[derive(Debug)] + #[allow(non_camel_case_types)] + pub struct $name; + + impl crypto::SupportedKxGroup for $name { + fn name(&self) -> rustls::NamedGroup { + $kx_name + } + + fn start(&self) -> Result, rustls::Error> { + let priv_key = $secret::random(&mut rand_core::OsRng); + let pub_key: $public_key = (&priv_key).into(); + Ok(Box::new([<$name KeyExchange>] { + priv_key, + pub_key: pub_key.to_sec1_bytes(), + })) + } + } + + #[allow(non_camel_case_types)] + pub struct [<$name KeyExchange>] { + priv_key: $secret, + pub_key: Box<[u8]>, + } + + impl crypto::ActiveKeyExchange for [<$name KeyExchange>] { + fn complete( + self: Box<[<$name KeyExchange>]>, + peer: &[u8], + ) -> Result { + let their_pub = $public_key::from_sec1_bytes(peer) + .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; + Ok(self + .priv_key + .diffie_hellman(&their_pub) + .raw_secret_bytes() + .as_slice() + .into()) + } + + fn pub_key(&self) -> &[u8] { + &self.pub_key + } + + fn group(&self) -> rustls::NamedGroup { + $name.name() + } + } + } + }; +} + +impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, ::p256::ecdh::EphemeralSecret, ::p256::PublicKey} +impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, ::p384::ecdh::EphemeralSecret, ::p384::PublicKey} diff --git a/src/kx/x25519.rs b/src/kx/x25519.rs new file mode 100644 index 0000000..0711678 --- /dev/null +++ b/src/kx/x25519.rs @@ -0,0 +1,47 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crypto::{SharedSecret, SupportedKxGroup}; +use rustls::crypto::{self, ActiveKeyExchange}; +use x25519_dalek::{EphemeralSecret, PublicKey}; + +#[derive(Debug)] +pub struct X25519; + +impl crypto::SupportedKxGroup for X25519 { + fn name(&self) -> rustls::NamedGroup { + rustls::NamedGroup::X25519 + } + + fn start(&self) -> Result, rustls::Error> { + let priv_key = EphemeralSecret::random_from_rng(rand_core::OsRng); + let pub_key = PublicKey::from(&priv_key); + Ok(Box::new(X25519KeyExchange { priv_key, pub_key })) + } +} + +pub struct X25519KeyExchange { + priv_key: EphemeralSecret, + pub_key: PublicKey, +} + +impl ActiveKeyExchange for X25519KeyExchange { + fn complete(self: Box, peer: &[u8]) -> Result { + let peer_array: [u8; 32] = peer + .try_into() + .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; + Ok(self + .priv_key + .diffie_hellman(&peer_array.into()) + .as_ref() + .into()) + } + + fn pub_key(&self) -> &[u8] { + self.pub_key.as_bytes() + } + + fn group(&self) -> rustls::NamedGroup { + X25519.name() + } +} diff --git a/src/lib.rs b/src/lib.rs index 1b108b8..47a34e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,13 +41,9 @@ extern crate alloc; #[cfg(feature = "alloc")] use alloc::sync::Arc; -use rustls::crypto::{ - CipherSuiteCommon, CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom, -}; -use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; - -#[cfg(feature = "tls12")] -use rustls::SignatureScheme; +use rustls::crypto::{CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom}; +use rustls::sign::SigningKey; +use rustls::SupportedCipherSuite; #[derive(Debug)] pub struct Provider; @@ -75,188 +71,22 @@ impl KeyProvider for Provider { fn load_private_key( &self, key_der: pki_types::PrivateKeyDer<'static>, - ) -> Result, rustls::Error> { + ) -> Result, rustls::Error> { sign::any_supported_type(&key_der) } } -#[cfg(feature = "tls12")] -const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::ED25519, -]; - -#[cfg(feature = "tls12")] -const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [ - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, -]; - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - aead_alg: &aead::gcm::Tls12Aes128Gcm, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA384), - aead_alg: &aead::gcm::Tls12Aes256Gcm, - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - aead_alg: &aead::chacha20::Chacha20Poly1305, - }); - -#[cfg(feature = "tls12")] -const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, -]; - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - aead_alg: &aead::gcm::Tls12Aes128Gcm, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA384), - aead_alg: &aead::gcm::Tls12Aes256Gcm, - }); - -#[cfg(feature = "tls12")] -pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&rustls::Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: rustls::crypto::KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - prf_provider: &rustls::crypto::tls12::PrfUsingHmac(hmac::SHA256), - aead_alg: &aead::chacha20::Chacha20Poly1305, - }); - -#[cfg(feature = "tls12")] -const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, -]; - -#[cfg(feature = "tls12")] -const TLS12_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( +pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( SupportedCipherSuite, - TLS_ECDHE_ECDSA_SUITES, - TLS_ECDHE_RSA_SUITES -); - -#[cfg(not(feature = "tls12"))] -const TLS12_SUITES: &[SupportedCipherSuite] = &[]; - -pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS13_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(hmac::SHA256), - aead_alg: &aead::gcm::Tls13Aes128Gcm, - quic: None, - }); - -pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS13_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(hmac::SHA384), - aead_alg: &aead::gcm::Tls13Aes256Gcm, - quic: None, - }); - -const TLS13_AES_SUITES: &[SupportedCipherSuite] = - &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384]; - -pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls13(&Tls13CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - hkdf_provider: &rustls::crypto::tls13::HkdfUsingHmac(hmac::SHA256), - aead_alg: &aead::chacha20::Chacha20Poly1305, - quic: None, - }); - -const TLS13_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( - SupportedCipherSuite, - TLS13_AES_SUITES, - &[TLS13_CHACHA20_POLY1305_SHA256] -); - -static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices!( - SupportedCipherSuite, - if cfg!(feature = "tls12") { - TLS12_SUITES - } else { - &[] + { + #[cfg(feature = "tls12")] + { + TLS12_SUITES + } + #[cfg(not(feature = "tls12"))] + { + &[] + } }, TLS13_SUITES, ); @@ -266,6 +96,13 @@ mod hash; mod hmac; mod kx; mod misc; -pub mod quic; pub mod sign; mod verify; + +#[cfg(feature = "tls12")] +pub mod tls12; +pub mod tls13; + +#[cfg(feature = "tls12")] +pub use tls12::*; +pub use tls13::*; diff --git a/src/quic.rs b/src/quic.rs deleted file mode 100644 index f849835..0000000 --- a/src/quic.rs +++ /dev/null @@ -1,142 +0,0 @@ -#![allow(clippy::duplicate_mod)] - -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use aead::AeadCore; -use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; -use crypto_common::typenum::Unsigned; -use rustls::crypto::cipher::{self, AeadKey, Iv}; -use rustls::{quic, Error, Tls13CipherSuite}; - -#[allow(dead_code)] // TODO -pub struct HeaderProtectionKey(AeadKey); - -impl HeaderProtectionKey { - pub fn new(key: AeadKey) -> Self { - Self(key) - } -} - -impl quic::HeaderProtectionKey for HeaderProtectionKey { - fn encrypt_in_place( - &self, - _sample: &[u8], - _first: &mut u8, - _packet_number: &mut [u8], - ) -> Result<(), Error> { - todo!() - } - - fn decrypt_in_place( - &self, - _sample: &[u8], - _first: &mut u8, - _packet_number: &mut [u8], - ) -> Result<(), Error> { - todo!() - } - - #[inline] - fn sample_len(&self) -> usize { - todo!() - } -} - -pub struct PacketKey { - /// Computes unique nonces for each packet - iv: Iv, - - /// The cipher suite used for this packet key - #[allow(dead_code)] - suite: &'static Tls13CipherSuite, - - crypto: chacha20poly1305::ChaCha20Poly1305, -} - -impl PacketKey { - pub fn new(suite: &'static Tls13CipherSuite, key: AeadKey, iv: Iv) -> Self { - Self { - iv, - suite, - crypto: chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()) - .expect("key should be valid"), - } - } -} - -impl quic::PacketKey for PacketKey { - fn encrypt_in_place( - &self, - packet_number: u64, - aad: &[u8], - payload: &mut [u8], - ) -> Result { - let nonce = cipher::Nonce::new(&self.iv, packet_number).0; - - let tag = self - .crypto - .encrypt_in_place_detached(&nonce.into(), aad, payload) - .map_err(|_| rustls::Error::EncryptError)?; - Ok(quic::Tag::from(tag.as_ref())) - } - - /// Decrypt a QUIC packet - /// - /// Takes the packet `header`, which is used as the additional authenticated - /// data, and the `payload`, which includes the authentication tag. - /// - /// If the return value is `Ok`, the decrypted payload can be found in - /// `payload`, up to the length found in the return value. - fn decrypt_in_place<'a>( - &self, - packet_number: u64, - aad: &[u8], - payload: &'a mut [u8], - ) -> Result<&'a [u8], Error> { - let mut payload_ = payload.to_vec(); - let payload_len = payload_.len(); - let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.iv, packet_number).0); - - self.crypto - .decrypt_in_place(&nonce, aad, &mut payload_) - .map_err(|_| rustls::Error::DecryptError)?; - - // Unfortunately the lifetime bound on decrypt_in_place sucks - payload.copy_from_slice(&payload_); - - let plain_len = payload_len - self.tag_len(); - Ok(&payload[..plain_len]) - } - - /// Tag length for the underlying AEAD algorithm - #[inline] - fn tag_len(&self) -> usize { - ::TagSize::to_usize() - } - - fn integrity_limit(&self) -> u64 { - 1 << 36 - } - - fn confidentiality_limit(&self) -> u64 { - u64::MAX - } -} - -#[allow(dead_code)] // TODO -pub struct KeyBuilder(AeadKey); - -impl rustls::quic::Algorithm for KeyBuilder { - fn packet_key(&self, _key: AeadKey, _iv: Iv) -> Box { - todo!() - } - - fn header_protection_key(&self, key: AeadKey) -> Box { - Box::new(HeaderProtectionKey::new(key)) - } - - fn aead_key_len(&self) -> usize { - chacha20poly1305::ChaCha20Poly1305::key_size() - } -} diff --git a/src/sign/ecdsa.rs b/src/sign/ecdsa.rs index 3f4a2bc..04c3f0f 100644 --- a/src/sign/ecdsa.rs +++ b/src/sign/ecdsa.rs @@ -1,66 +1,2 @@ -#[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, sync::Arc}; -use core::marker::PhantomData; - -use paste::paste; -use pkcs8::DecodePrivateKey; -use pki_types::PrivateKeyDer; -use rustls::sign::SigningKey; -use rustls::{SignatureAlgorithm, SignatureScheme}; -use sec1::DecodeEcPrivateKey; - -macro_rules! impl_ecdsa { - ($name: ident, $scheme: expr, $signing_key: ty, $signature: ty) => { - paste! { - #[derive(Debug)] - pub struct [] { - key: Arc<$signing_key>, - scheme: SignatureScheme, - } - - impl TryFrom<&PrivateKeyDer<'_>> for [] { - type Error = rustls::Error; - - fn try_from(value: &PrivateKeyDer<'_>) -> Result { - let pkey = match value { - PrivateKeyDer::Pkcs8(der) => { - $signing_key::from_pkcs8_der(der.secret_pkcs8_der()).map_err(|e| format!("failed to decrypt private key: {e}")) - }, - PrivateKeyDer::Sec1(sec1) => { - $signing_key::from_sec1_der(sec1.secret_sec1_der()).map_err(|e| format!("failed to decrypt private key: {e}")) - }, - PrivateKeyDer::Pkcs1(_) => Err(format!("ECDSA does not support PKCS#1 key")), - _ => Err("not supported".into()), - }; - pkey.map(|kp| { - Self { - key: Arc::new(kp), - scheme: $scheme, - } - }).map_err(rustls::Error::General) - } - } - - impl SigningKey for [] { - fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { - if offered.contains(&self.scheme) { - Some(Box::new(super::GenericRandomizedSigner::<$signature, _> { - _marker: PhantomData, - key: self.key.clone(), - scheme: self.scheme, - })) - } else { - None - } - } - - fn algorithm(&self) -> SignatureAlgorithm { - SignatureAlgorithm::ECDSA - } - } - } - }; -} - -impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, p256::ecdsa::SigningKey, p256::ecdsa::DerSignature} -impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, p384::ecdsa::SigningKey, p384::ecdsa::DerSignature} +mod nist; +pub use nist::*; diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs new file mode 100644 index 0000000..4a70551 --- /dev/null +++ b/src/sign/ecdsa/nist.rs @@ -0,0 +1,67 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, format, sync::Arc}; +use core::marker::PhantomData; + +use crate::sign::GenericRandomizedSigner; +use paste::paste; +use pkcs8::DecodePrivateKey; +use pki_types::PrivateKeyDer; +use rustls::sign::SigningKey; +use rustls::{SignatureAlgorithm, SignatureScheme}; +use sec1::DecodeEcPrivateKey; + +macro_rules! impl_ecdsa { +($name: ident, $scheme: expr, $signing_key: ty, $signature: ty) => { + paste! { + #[derive(Debug)] + pub struct [] { + key: Arc<$signing_key>, + scheme: SignatureScheme, + } + + impl TryFrom<&PrivateKeyDer<'_>> for [] { + type Error = rustls::Error; + + fn try_from(value: &PrivateKeyDer<'_>) -> Result { + let pkey = match value { + PrivateKeyDer::Pkcs8(der) => { + $signing_key::from_pkcs8_der(der.secret_pkcs8_der()).map_err(|e| format!("failed to decrypt private key: {e}")) + }, + PrivateKeyDer::Sec1(sec1) => { + $signing_key::from_sec1_der(sec1.secret_sec1_der()).map_err(|e| format!("failed to decrypt private key: {e}")) + }, + PrivateKeyDer::Pkcs1(_) => Err(format!("ECDSA does not support PKCS#1 key")), + _ => Err("not supported".into()), + }; + pkey.map(|kp| { + Self { + key: Arc::new(kp), + scheme: $scheme, + } + }).map_err(rustls::Error::General) + } + } + + impl SigningKey for [] { + fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { + if offered.contains(&self.scheme) { + Some(Box::new(GenericRandomizedSigner::<$signature, _> { + _marker: PhantomData, + key: self.key.clone(), + scheme: self.scheme, + })) + } else { + None + } + } + + fn algorithm(&self) -> SignatureAlgorithm { + SignatureAlgorithm::ECDSA + } + } + } +}; +} + +impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, ::p256::ecdsa::SigningKey, ::p256::ecdsa::DerSignature} +impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, ::p384::ecdsa::SigningKey, ::p384::ecdsa::DerSignature} diff --git a/src/sign/eddsa.rs b/src/sign/eddsa.rs index e6f0d1a..67c97fc 100644 --- a/src/sign/eddsa.rs +++ b/src/sign/eddsa.rs @@ -1,57 +1,2 @@ -#[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, string::ToString, sync::Arc}; -use core::marker::PhantomData; - -use pkcs8::DecodePrivateKey; -use pki_types::PrivateKeyDer; -use rustls::sign::{Signer, SigningKey}; -use rustls::{SignatureAlgorithm, SignatureScheme}; -use sec1::DecodeEcPrivateKey; - -#[derive(Debug)] -pub struct Ed25519SigningKey { - key: Arc, - scheme: SignatureScheme, -} - -impl TryFrom<&PrivateKeyDer<'_>> for Ed25519SigningKey { - type Error = rustls::Error; - - fn try_from(value: &PrivateKeyDer<'_>) -> Result { - let pkey = match value { - PrivateKeyDer::Pkcs8(der) => { - ed25519_dalek::SigningKey::from_pkcs8_der(der.secret_pkcs8_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")) - } - PrivateKeyDer::Sec1(sec1) => { - ed25519_dalek::SigningKey::from_sec1_der(sec1.secret_sec1_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")) - } - PrivateKeyDer::Pkcs1(_) => Err("ED25519 does not support PKCS#1 key".to_string()), - _ => Err("not supported".into()), - }; - pkey.map(|kp| Self { - key: Arc::new(kp), - scheme: SignatureScheme::ED25519, - }) - .map_err(rustls::Error::General) - } -} - -impl SigningKey for Ed25519SigningKey { - fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { - if offered.contains(&self.scheme) { - Some(Box::new(super::GenericSigner { - _marker: PhantomData, - key: self.key.clone(), - scheme: self.scheme, - })) - } else { - None - } - } - - fn algorithm(&self) -> SignatureAlgorithm { - SignatureAlgorithm::ED25519 - } -} +mod ed25519; +pub use ed25519::*; diff --git a/src/sign/eddsa/ed25519.rs b/src/sign/eddsa/ed25519.rs new file mode 100644 index 0000000..2d1d1ea --- /dev/null +++ b/src/sign/eddsa/ed25519.rs @@ -0,0 +1,50 @@ +#[cfg(feature = "alloc")] +use alloc::{boxed::Box, format, string::ToString, sync::Arc}; +use core::marker::PhantomData; +use ed25519_dalek::SigningKey; +use rustls::{sign::Signer, SignatureAlgorithm, SignatureScheme}; + +use pkcs8::DecodePrivateKey; +use pki_types::PrivateKeyDer; +use sec1::DecodeEcPrivateKey; + +use crate::sign::GenericSigner; + +#[derive(Debug)] +pub struct Ed25519SigningKey(Arc); + +impl TryFrom<&PrivateKeyDer<'_>> for Ed25519SigningKey { + type Error = rustls::Error; + + fn try_from(value: &PrivateKeyDer<'_>) -> Result { + let pkey = match value { + PrivateKeyDer::Pkcs8(der) => SigningKey::from_pkcs8_der(der.secret_pkcs8_der()) + .map_err(|e| format!("failed to decrypt private key: {e}")), + PrivateKeyDer::Sec1(sec1) => SigningKey::from_sec1_der(sec1.secret_sec1_der()) + .map_err(|e| format!("failed to decrypt private key: {e}")), + PrivateKeyDer::Pkcs1(_) => Err("ED25519 does not support PKCS#1 key".to_string()), + _ => Err("not supported".into()), + }; + pkey.map(|kp| Self(Arc::new(kp))) + .map_err(rustls::Error::General) + } +} + +impl rustls::sign::SigningKey for Ed25519SigningKey { + fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option> { + const SCHEME: SignatureScheme = SignatureScheme::ED25519; + if offered.contains(&SCHEME) { + Some(Box::new(GenericSigner { + _marker: PhantomData, + key: self.0.clone(), + scheme: SCHEME, + })) + } else { + None + } + } + + fn algorithm(&self) -> SignatureAlgorithm { + SignatureAlgorithm::ED25519 + } +} diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index ab27d36..a69c1da 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -1,6 +1,7 @@ #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, string::ToString, sync::Arc}; +use derive_more::{Debug, Deref}; use pkcs8::DecodePrivateKey; use pki_types::PrivateKeyDer; use rsa::pkcs1::DecodeRsaPrivateKey; @@ -18,7 +19,7 @@ const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ SignatureScheme::RSA_PKCS1_SHA256, ]; -#[derive(Debug)] +#[derive(Debug, Deref, Clone)] pub struct RsaSigningKey(RsaPrivateKey); impl TryFrom<&PrivateKeyDer<'_>> for RsaSigningKey { @@ -55,17 +56,17 @@ impl SigningKey for RsaSigningKey { } match scheme { - SignatureScheme::RSA_PSS_SHA512 => signer! {rsa::pss::SigningKey::}, - SignatureScheme::RSA_PSS_SHA384 => signer! {rsa::pss::SigningKey::}, + SignatureScheme::RSA_PSS_SHA512 => signer! {::rsa::pss::SigningKey::}, + SignatureScheme::RSA_PSS_SHA384 => signer! {::rsa::pss::SigningKey::}, SignatureScheme::RSA_PSS_SHA256 => signer! {rsa::pss::SigningKey::}, SignatureScheme::RSA_PKCS1_SHA512 => { - signer! {rsa::pkcs1v15::SigningKey::} + signer! {::rsa::pkcs1v15::SigningKey::} } SignatureScheme::RSA_PKCS1_SHA384 => { - signer! {rsa::pkcs1v15::SigningKey::} + signer! {::rsa::pkcs1v15::SigningKey::} } SignatureScheme::RSA_PKCS1_SHA256 => { - signer! {rsa::pkcs1v15::SigningKey::} + signer! {::rsa::pkcs1v15::SigningKey::} } _ => None, } diff --git a/src/tls12.rs b/src/tls12.rs new file mode 100644 index 0000000..963567a --- /dev/null +++ b/src/tls12.rs @@ -0,0 +1,16 @@ +use crate::misc::const_concat_slices; +use rustls::SupportedCipherSuite; + +pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + TLS_ECDHE_ECDSA_SUITES, + TLS_ECDHE_RSA_SUITES +); + +pub mod ecdsa; +pub mod rsa; +pub mod schemes; + +pub use ecdsa::*; +pub use rsa::*; +pub use schemes::*; diff --git a/src/tls12/ecdsa.rs b/src/tls12/ecdsa.rs new file mode 100644 index 0000000..46aad02 --- /dev/null +++ b/src/tls12/ecdsa.rs @@ -0,0 +1,52 @@ +use crate::aead::chacha20::ChaCha20Poly1305; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::{hash, hmac}; +use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorithm}; +use rustls::{CipherSuite, SupportedCipherSuite, Tls12CipherSuite}; + +use super::schemes::TLS12_ECDSA_SCHEMES; + +pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: &TLS12_ECDSA_SCHEMES, + aead_alg: &Aes128Gcm, + prf_provider: &PrfUsingHmac(hmac::SHA256), + }); + +pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + hash_provider: hash::SHA384, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: &TLS12_ECDSA_SCHEMES, + prf_provider: &PrfUsingHmac(hmac::SHA384), + aead_alg: &Aes256Gcm, + }); + +pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + prf_provider: &PrfUsingHmac(hmac::SHA256), + kx: KeyExchangeAlgorithm::ECDHE, + sign: &TLS12_ECDSA_SCHEMES, + aead_alg: &ChaCha20Poly1305, + }); + +pub const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, +]; diff --git a/src/tls12/rsa.rs b/src/tls12/rsa.rs new file mode 100644 index 0000000..a04e4a6 --- /dev/null +++ b/src/tls12/rsa.rs @@ -0,0 +1,52 @@ +use crate::aead::chacha20::ChaCha20Poly1305; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::{hash, hmac}; +use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorithm}; +use rustls::{CipherSuite, SupportedCipherSuite, Tls12CipherSuite}; + +use super::schemes::TLS12_RSA_SCHEMES; + +pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: &TLS12_RSA_SCHEMES, + aead_alg: &Aes128Gcm, + prf_provider: &PrfUsingHmac(hmac::SHA256), + }); + +pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + hash_provider: hash::SHA384, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: &TLS12_RSA_SCHEMES, + prf_provider: &PrfUsingHmac(hmac::SHA384), + aead_alg: &Aes256Gcm, + }); + +pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls12(&Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: &TLS12_RSA_SCHEMES, + prf_provider: &PrfUsingHmac(hmac::SHA256), + aead_alg: &ChaCha20Poly1305, + }); + +pub const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +]; diff --git a/src/tls12/schemes.rs b/src/tls12/schemes.rs new file mode 100644 index 0000000..a850e3c --- /dev/null +++ b/src/tls12/schemes.rs @@ -0,0 +1,16 @@ +use rustls::SignatureScheme; + +pub const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ + SignatureScheme::ECDSA_NISTP256_SHA256, + SignatureScheme::ECDSA_NISTP384_SHA384, + SignatureScheme::ECDSA_NISTP521_SHA512, + SignatureScheme::ED25519, +]; +pub const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [ + SignatureScheme::RSA_PKCS1_SHA256, + SignatureScheme::RSA_PKCS1_SHA384, + SignatureScheme::RSA_PKCS1_SHA512, + SignatureScheme::RSA_PSS_SHA256, + SignatureScheme::RSA_PSS_SHA384, + SignatureScheme::RSA_PSS_SHA512, +]; diff --git a/src/tls13.rs b/src/tls13.rs new file mode 100644 index 0000000..d4c069e --- /dev/null +++ b/src/tls13.rs @@ -0,0 +1,14 @@ +use crate::const_concat_slices; +use rustls::SupportedCipherSuite; + +pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + TLS13_AES_SUITES, + &[TLS13_CHACHA20_POLY1305_SHA256] +); + +pub mod aes; +pub mod chacha20; + +pub use aes::*; +pub use chacha20::*; diff --git a/src/tls13/aes.rs b/src/tls13/aes.rs new file mode 100644 index 0000000..99d9081 --- /dev/null +++ b/src/tls13/aes.rs @@ -0,0 +1,31 @@ +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::{hash, hmac}; +use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; +use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; + +pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls13(&Tls13CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS13_AES_128_GCM_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &HkdfUsingHmac(hmac::SHA256), + aead_alg: &Aes128Gcm, + quic: None, + }); + +pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = + SupportedCipherSuite::Tls13(&Tls13CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS13_AES_256_GCM_SHA384, + hash_provider: hash::SHA384, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &HkdfUsingHmac(hmac::SHA384), + aead_alg: &Aes256Gcm, + quic: None, + }); + +pub const TLS13_AES_SUITES: &[SupportedCipherSuite] = + &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384]; diff --git a/src/tls13/chacha20.rs b/src/tls13/chacha20.rs new file mode 100644 index 0000000..4fd8847 --- /dev/null +++ b/src/tls13/chacha20.rs @@ -0,0 +1,16 @@ +use crate::aead::chacha20::ChaCha20Poly1305; +use crate::{hash, hmac}; +use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; +use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; + +pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls13(&Tls13CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &HkdfUsingHmac(hmac::SHA256), + aead_alg: &ChaCha20Poly1305, + quic: None, + }); diff --git a/src/verify.rs b/src/verify.rs index 2043b64..0f50a6c 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,5 +1,4 @@ -use rustls::crypto::WebPkiSupportedAlgorithms; -use rustls::SignatureScheme; +use core::array::TryFromSliceError; use self::ecdsa::{ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384}; use self::eddsa::ED25519; @@ -7,6 +6,35 @@ use self::rsa::{ RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384, RSA_PSS_SHA512, }; +use derive_more::From; +use rustls::crypto::WebPkiSupportedAlgorithms; +use rustls::SignatureScheme; + +#[derive(From)] +pub(crate) enum Error { + Signature, + TryFromSlice(TryFromSliceError), + Der, + Pkcs1, +} + +impl From for Error { + fn from(_: signature::Error) -> Self { + Self::Signature + } +} + +impl From for Error { + fn from(_: der::Error) -> Self { + Self::Der + } +} + +impl From for Error { + fn from(_: pkcs1::Error) -> Self { + Self::Pkcs1 + } +} pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { all: &[ diff --git a/src/verify/ecdsa.rs b/src/verify/ecdsa.rs index 669f03d..04c3f0f 100644 --- a/src/verify/ecdsa.rs +++ b/src/verify/ecdsa.rs @@ -1,54 +1,2 @@ -use der::Decode; -use digest::Digest; -use paste::paste; -use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use signature::hazmat::PrehashVerifier; -use webpki::alg_id; - -macro_rules! impl_generic_ecdsa_verifer { - ( - $name:ident, - $public_key_algo:expr, - $signature_alg_id:expr, - $verifying_key:ty, - $signature:ty, - $hash:ty - ) => { - paste! { - #[allow(non_camel_case_types)] - #[derive(Debug)] - struct []; - - impl SignatureVerificationAlgorithm for [] { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - $public_key_algo - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - $signature_alg_id - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let signature = <$signature>::from_der(signature).map_err(|_| InvalidSignature)?; - let verifying_key = <$verifying_key>::from_sec1_bytes(public_key).map_err(|_| InvalidSignature)?; - let digest = &<$hash>::digest(&message); - verifying_key - .verify_prehash(digest, &signature) - .map_err(|_| InvalidSignature) - } - } - - pub const $name: &dyn SignatureVerificationAlgorithm = &[]; - } - }; -} - -impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, p256::ecdsa::VerifyingKey, p256::ecdsa::DerSignature, sha2::Sha256} -impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, p256::ecdsa::VerifyingKey, p256::ecdsa::DerSignature, sha2::Sha384} -impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, p384::ecdsa::VerifyingKey, p384::ecdsa::DerSignature, sha2::Sha256} -impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, p384::ecdsa::VerifyingKey, p384::ecdsa::DerSignature, sha2::Sha384} +mod nist; +pub use nist::*; diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs new file mode 100644 index 0000000..34a7c11 --- /dev/null +++ b/src/verify/ecdsa/nist.rs @@ -0,0 +1,59 @@ +use der::Decode; +use digest::Digest; +use paste::paste; +use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; +use signature::hazmat::PrehashVerifier; +use webpki::alg_id; + +macro_rules! impl_generic_ecdsa_verifer { +( + $name:ident, + $public_key_algo:expr, + $signature_alg_id:expr, + $verifying_key:ty, + $signature:ty, + $hash:ty +) => { + paste! { + #[allow(non_camel_case_types)] + #[derive(Debug)] + struct []; + + impl [] { + fn verify_inner(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result<(), crate::verify::Error> { + let signature = <$signature>::from_der(signature)?; + let verifying_key = <$verifying_key>::from_sec1_bytes(public_key)?; + let digest = &<$hash>::digest(&message); + verifying_key.verify_prehash(digest, &signature)?; + Ok(()) + } + } + + impl SignatureVerificationAlgorithm for [] { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + $public_key_algo + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + $signature_alg_id + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) + } + } + + pub const $name: &dyn SignatureVerificationAlgorithm = &[]; + } +}; +} + +impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha256} +impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha384} +impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha256} +impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha384} diff --git a/src/verify/eddsa.rs b/src/verify/eddsa.rs index 334321c..67c97fc 100644 --- a/src/verify/eddsa.rs +++ b/src/verify/eddsa.rs @@ -1,33 +1,2 @@ -use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use signature::Verifier; -use webpki::alg_id; - -#[derive(Debug)] -struct Ed25519Verify; - -impl SignatureVerificationAlgorithm for Ed25519Verify { - fn public_key_alg_id(&self) -> AlgorithmIdentifier { - alg_id::ED25519 - } - - fn signature_alg_id(&self) -> AlgorithmIdentifier { - alg_id::ED25519 - } - - fn verify_signature( - &self, - public_key: &[u8], - message: &[u8], - signature: &[u8], - ) -> Result<(), InvalidSignature> { - let public_key = public_key.try_into().map_err(|_| InvalidSignature)?; - let signature = - ed25519_dalek::Signature::from_slice(signature).map_err(|_| InvalidSignature)?; - ed25519_dalek::VerifyingKey::from_bytes(public_key) - .map_err(|_| InvalidSignature)? - .verify(message, &signature) - .map_err(|_| InvalidSignature) - } -} - -pub const ED25519: &dyn SignatureVerificationAlgorithm = &Ed25519Verify; +mod ed25519; +pub use ed25519::*; diff --git a/src/verify/eddsa/ed25519.rs b/src/verify/eddsa/ed25519.rs new file mode 100644 index 0000000..d669d70 --- /dev/null +++ b/src/verify/eddsa/ed25519.rs @@ -0,0 +1,42 @@ +use ed25519_dalek::{Signature, VerifyingKey}; +use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; +use signature::Verifier; +use webpki::alg_id; + +#[derive(Debug)] +struct Ed25519Verify; + +impl Ed25519Verify { + fn verify_inner( + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), crate::verify::Error> { + let public_key = public_key.try_into()?; + let signature = Signature::from_slice(signature)?; + let verifying_key = VerifyingKey::from_bytes(public_key)?; + verifying_key.verify(message, &signature)?; + Ok(()) + } +} + +impl SignatureVerificationAlgorithm for Ed25519Verify { + fn public_key_alg_id(&self) -> AlgorithmIdentifier { + alg_id::ED25519 + } + + fn signature_alg_id(&self) -> AlgorithmIdentifier { + alg_id::ED25519 + } + + fn verify_signature( + &self, + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), InvalidSignature> { + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) + } +} + +pub const ED25519: &dyn SignatureVerificationAlgorithm = &Ed25519Verify; diff --git a/src/verify/rsa.rs b/src/verify/rsa.rs index f7a1889..e6ee5a8 100644 --- a/src/verify/rsa.rs +++ b/src/verify/rsa.rs @@ -19,6 +19,19 @@ macro_rules! impl_generic_rsa_verifer { #[derive(Debug)] struct []; + impl [] { + fn verify_inner( + public_key: &[u8], + message: &[u8], + signature: &[u8], + ) -> Result<(), crate::verify::Error> { + let public_key = RsaPublicKey::from_pkcs1_der(public_key)?; + let signature = <$signature>::try_from(signature)?; + <$verifying_key>::new(public_key).verify(message, &signature)?; + Ok(()) + } + } + impl SignatureVerificationAlgorithm for [] { fn public_key_alg_id(&self) -> AlgorithmIdentifier { $public_key_algo @@ -34,11 +47,7 @@ macro_rules! impl_generic_rsa_verifer { message: &[u8], signature: &[u8], ) -> Result<(), InvalidSignature> { - let public_key = RsaPublicKey::from_pkcs1_der(public_key).map_err(|_| InvalidSignature)?; - let signature = <$signature>::try_from(signature).map_err(|_| InvalidSignature)?; - <$verifying_key>::new(public_key) - .verify(message, &signature) - .map_err(|_| InvalidSignature) + Self::verify_inner(public_key, message, signature).map_err(|_| InvalidSignature) } } From 7e5bd91da38c711b73de4f3ec627f166b368c9b5 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:55:21 +0800 Subject: [PATCH 02/38] fixup! refactor the whole structure --- src/aead.rs | 11 +- src/aead/chacha20.rs | 8 -- src/aead/gcm.rs | 7 - src/aead/gcm/tls12.rs | 136 ------------------ src/aead/gcm/tls13.rs | 93 ------------ src/hash.rs | 4 +- src/hmac.rs | 4 +- src/kx.rs | 9 +- src/lib.rs | 20 ++- src/sign.rs | 4 +- src/sign/ecdsa.rs | 3 +- src/sign/eddsa.rs | 3 +- src/tls12.rs | 18 +-- src/tls12/aead.rs | 2 + .../tls12.rs => tls12/aead/chacha20.rs} | 8 +- src/tls12/aead/gcm.rs | 135 +++++++++++++++++ src/tls12/suites.rs | 14 ++ src/tls12/{ => suites}/ecdsa.rs | 3 +- src/tls12/{ => suites}/rsa.rs | 3 +- src/tls12/{ => suites}/schemes.rs | 0 src/tls13.rs | 16 +-- src/tls13/aead.rs | 2 + .../tls13.rs => tls13/aead/chacha20.rs} | 7 +- src/tls13/aead/gcm.rs | 91 ++++++++++++ src/tls13/suites.rs | 13 ++ src/tls13/{ => suites}/aes.rs | 2 +- src/tls13/{ => suites}/chacha20.rs | 2 +- src/verify.rs | 6 +- src/verify/ecdsa.rs | 3 +- src/verify/ecdsa/nist.rs | 2 +- src/verify/eddsa.rs | 3 +- src/verify/eddsa/ed25519.rs | 2 +- src/verify/rsa.rs | 2 +- 33 files changed, 309 insertions(+), 327 deletions(-) delete mode 100644 src/aead/chacha20.rs delete mode 100644 src/aead/gcm.rs delete mode 100644 src/aead/gcm/tls12.rs delete mode 100644 src/aead/gcm/tls13.rs create mode 100644 src/tls12/aead.rs rename src/{aead/chacha20/tls12.rs => tls12/aead/chacha20.rs} (94%) create mode 100644 src/tls12/aead/gcm.rs create mode 100644 src/tls12/suites.rs rename src/tls12/{ => suites}/ecdsa.rs (95%) rename src/tls12/{ => suites}/rsa.rs (95%) rename src/tls12/{ => suites}/schemes.rs (100%) create mode 100644 src/tls13/aead.rs rename src/{aead/chacha20/tls13.rs => tls13/aead/chacha20.rs} (94%) create mode 100644 src/tls13/aead/gcm.rs create mode 100644 src/tls13/suites.rs rename src/tls13/{ => suites}/aes.rs (95%) rename src/tls13/{ => suites}/chacha20.rs (92%) diff --git a/src/aead.rs b/src/aead.rs index 6ff57b7..c2d96ab 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -1,10 +1,13 @@ use aead::Buffer; use rustls::crypto::cipher::{BorrowedPayload, PrefixedPayload}; -pub mod chacha20; -pub mod gcm; +pub const CHACHAPOLY1305_OVERHEAD: usize = 16; -pub(crate) struct EncryptBufferAdapter<'a>(&'a mut PrefixedPayload); +pub struct ChaCha20Poly1305; +pub struct Aes128Gcm; +pub struct Aes256Gcm; + +pub(crate) struct EncryptBufferAdapter<'a>(pub(crate) &'a mut PrefixedPayload); impl AsRef<[u8]> for EncryptBufferAdapter<'_> { fn as_ref(&self) -> &[u8] { @@ -29,7 +32,7 @@ impl Buffer for EncryptBufferAdapter<'_> { } } -pub(crate) struct DecryptBufferAdapter<'a, 'p>(&'a mut BorrowedPayload<'p>); +pub(crate) struct DecryptBufferAdapter<'a, 'p>(pub(crate) &'a mut BorrowedPayload<'p>); impl AsRef<[u8]> for DecryptBufferAdapter<'_, '_> { fn as_ref(&self) -> &[u8] { diff --git a/src/aead/chacha20.rs b/src/aead/chacha20.rs deleted file mode 100644 index d9f3216..0000000 --- a/src/aead/chacha20.rs +++ /dev/null @@ -1,8 +0,0 @@ -const CHACHAPOLY1305_OVERHEAD: usize = 16; - -pub struct ChaCha20Poly1305; - -#[cfg(feature = "tls12")] -pub mod tls12; - -pub mod tls13; diff --git a/src/aead/gcm.rs b/src/aead/gcm.rs deleted file mode 100644 index 90d635b..0000000 --- a/src/aead/gcm.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub struct Aes128Gcm; -pub struct Aes256Gcm; - -#[cfg(feature = "tls12")] -pub mod tls12; - -pub mod tls13; diff --git a/src/aead/gcm/tls12.rs b/src/aead/gcm/tls12.rs deleted file mode 100644 index 16c10c9..0000000 --- a/src/aead/gcm/tls12.rs +++ /dev/null @@ -1,136 +0,0 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use aead::{AeadCore, AeadInPlace}; -use crypto_common::typenum::Unsigned; -use crypto_common::{KeyInit, KeySizeUser}; -use paste::paste; -use rustls::crypto::cipher::{ - self, make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, - MessageDecrypter, MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, - PrefixedPayload, Tls12AeadAlgorithm, -}; -use rustls::ConnectionTrafficSecrets; - -use super::{Aes128Gcm, Aes256Gcm}; - -const TLS12_GCM_EXPLICIT_NONCE_LEN: usize = 8; - -const TLS12_GCM_OVERHEAD: usize = TLS12_GCM_EXPLICIT_NONCE_LEN + 16; - -macro_rules! impl_gcm { - ($name: ident, $aead: ty, $nonce_pos: expr, $overhead: expr) => { - paste! { - impl Tls12AeadAlgorithm for $name { - fn encrypter(&self, key: AeadKey, write_iv: &[u8], explicit: &[u8]) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - { - let mut iv: [u8; 12] = [0; 12]; - iv[..4].copy_from_slice(write_iv); - iv[4..].copy_from_slice(explicit); - iv - }, - )) - } - - fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { - Box::new([]( - $aead::new_from_slice(dec_key.as_ref()).unwrap(), - dec_iv.try_into().unwrap(), - )) - } - - fn key_block_shape(&self) -> KeyBlockShape { - KeyBlockShape { - enc_key_len: $aead::key_size(), - fixed_iv_len: 4, - explicit_nonce_len: 8, - } - } - - fn extract_keys( - &self, - key: AeadKey, - iv: &[u8], - _explicit: &[u8], - ) -> Result { - Ok(ConnectionTrafficSecrets::$name { - key, - iv: Iv::new(iv[..].try_into().unwrap()), - }) - } - } - - struct []($aead, [u8; 12]); - - impl MessageEncrypter for [] { - fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - let nonce = cipher::Nonce::new(&self.1.into(), seq).0; - let aad = make_tls12_aad(seq, m.typ, m.version, m.payload.len()); - payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit - payload.extend_from_chunks(&m.payload); - - self.0 - .encrypt_in_place_detached(&nonce.into(), &aad, &mut payload.as_mut()[$nonce_pos..]) - .map(|tag| payload.extend(tag.as_ref() as &[u8])) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) - } - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + $nonce_pos + <$aead as AeadCore>::TagSize::USIZE - } - } - - struct []($aead, [u8; 4]); - - impl MessageDecrypter for [] { - fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { - type TagSize = <$aead as AeadCore>::TagSize; - - let payload = &m.payload; - - if payload.len() < $overhead { - return Err(rustls::Error::DecryptError); - } - - let nonce: aead::Nonce<$aead> = { - let mut nonce = [0u8; 12]; - nonce[..4].copy_from_slice(&self.1); // dec_iv - nonce[4..].copy_from_slice(&payload[..$nonce_pos]); - nonce.into() - }; - - let aad = make_tls12_aad(seq, m.typ, m.version, payload.len() - $overhead); - - let payload = &mut m.payload; - let tag_pos = { - let payload = &mut payload[$nonce_pos..]; - let tag_pos = payload.len() - TagSize::to_usize(); - let (msg, tag) = payload.split_at_mut(tag_pos); - - let tag = aes_gcm::Tag::::from_slice(tag); - self.0 - .decrypt_in_place_detached(&nonce, &aad, msg, tag) - .map_err(|_| rustls::Error::DecryptError)?; - tag_pos - }; - - // We defer the truncation to here, because we may inadvertently shifted the - // original data if the decryption failed. Another way to avoid this is - // to clone the payload slice starting after the explicit nonce, - // but this will cause an additional cloning and copying - payload.rotate_left($nonce_pos); - payload.truncate(tag_pos); - Ok(m.into_plain_message()) - } - } - } - }; -} - -impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} -impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} diff --git a/src/aead/gcm/tls13.rs b/src/aead/gcm/tls13.rs deleted file mode 100644 index 6a3c689..0000000 --- a/src/aead/gcm/tls13.rs +++ /dev/null @@ -1,93 +0,0 @@ -#[cfg(feature = "alloc")] -use alloc::boxed::Box; - -use super::{Aes128Gcm, Aes256Gcm}; -use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; -use aead::AeadInPlace; -use crypto_common::{KeyInit, KeySizeUser}; -use paste::paste; -use rustls::crypto::cipher::{ - self, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, MessageDecrypter, - MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, - Tls13AeadAlgorithm, -}; -use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; - -macro_rules! impl_gcm { - ($name: ident, $aead: ty, $overhead: expr) => { - paste! { - - impl Tls13AeadAlgorithm for $name { - fn encrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - iv, - )) - } - - fn decrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { - Box::new([]( - $aead::new_from_slice(key.as_ref()).unwrap(), - iv, - )) - } - - fn key_len(&self) -> usize { - $aead::key_size() - } - fn extract_keys( - &self, - key: AeadKey, - iv: cipher::Iv, - ) -> Result { - Ok(ConnectionTrafficSecrets::$name { key, iv }) - } - } - - struct []($aead, cipher::Iv); - - impl MessageEncrypter for [] { - fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { - let total_len = self.encrypted_payload_len(m.payload.len()); - let mut payload = PrefixedPayload::with_capacity(total_len); - - let nonce = cipher::Nonce::new(&self.1, seq).0; - let aad = make_tls13_aad(total_len); - payload.extend_from_chunks(&m.payload); - payload.extend_from_slice(&m.typ.to_array()); - - self.0 - .encrypt_in_place(&nonce.into(), &aad, &mut EncryptBufferAdapter(&mut payload)) - .map_err(|_| rustls::Error::EncryptError) - .map(|_| OutboundOpaqueMessage::new( - ContentType::ApplicationData, - ProtocolVersion::TLSv1_2, - payload, - )) - } - - fn encrypted_payload_len(&self, payload_len: usize) -> usize { - payload_len + 1 + $overhead - } - } - - impl MessageDecrypter for [] { - fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { - let payload = &mut m.payload; - let nonce = cipher::Nonce::new(&self.1, seq).0; - let aad = make_tls13_aad(payload.len()); - - self.0 - .decrypt_in_place(&nonce.into(), &aad, &mut DecryptBufferAdapter(payload)) - .map_err(|_| rustls::Error::DecryptError)?; - - m.into_tls13_unpadded_message() - } - } - - } - }; -} - -impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, 16} -impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, 16} diff --git a/src/hash.rs b/src/hash.rs index dfa58e1..c15a65e 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -10,7 +10,7 @@ macro_rules! impl_hash { ($name:ident, $ty:ty, $algo:ty) => { paste! { #[allow(non_camel_case_types)] - struct []; + pub struct []; impl hash::Hash for [] { fn start(&self) -> Box { @@ -31,7 +31,7 @@ macro_rules! impl_hash { } #[allow(non_camel_case_types)] - struct []($ty); + pub struct []($ty); impl hash::Context for [] { fn fork_finish(&self) -> hash::Output { diff --git a/src/hmac.rs b/src/hmac.rs index 8388c27..a99d81d 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -14,7 +14,7 @@ macro_rules! impl_hmac { ) => { paste! { #[allow(non_camel_case_types)] - struct []; + pub struct []; impl crypto::hmac::Hmac for [] { fn with_key(&self, key: &[u8]) -> Box { @@ -29,7 +29,7 @@ macro_rules! impl_hmac { } #[allow(non_camel_case_types)] - struct [](hmac::Hmac<$ty>); + pub struct [](hmac::Hmac<$ty>); impl crypto::hmac::Key for [] { fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> crypto::hmac::Tag { diff --git a/src/kx.rs b/src/kx.rs index 23ad2bf..e64bed1 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -1,9 +1,8 @@ +use nist::{SecP256R1, SecP384R1}; use rustls::crypto::SupportedKxGroup; +use x25519::X25519; pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1]; -mod nist; -mod x25519; - -pub use nist::*; -pub use x25519::*; +pub mod nist; +pub mod x25519; diff --git a/src/lib.rs b/src/lib.rs index 47a34e9..f2fd74d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,28 +81,24 @@ pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices { #[cfg(feature = "tls12")] { - TLS12_SUITES + tls12::suites::TLS12_SUITES } #[cfg(not(feature = "tls12"))] { &[] } }, - TLS13_SUITES, + tls13::suites::TLS13_SUITES, ); -mod aead; -mod hash; -mod hmac; -mod kx; -mod misc; +pub mod aead; +pub mod hash; +pub mod hmac; +pub mod kx; +pub mod misc; pub mod sign; -mod verify; +pub mod verify; #[cfg(feature = "tls12")] pub mod tls12; pub mod tls13; - -#[cfg(feature = "tls12")] -pub use tls12::*; -pub use tls13::*; diff --git a/src/sign.rs b/src/sign.rs index e6109f5..9aa7e52 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -2,8 +2,8 @@ use alloc::{sync::Arc, vec::Vec}; use core::marker::PhantomData; -use self::ecdsa::{EcdsaSigningKeyP256, EcdsaSigningKeyP384}; -use self::eddsa::Ed25519SigningKey; +use self::ecdsa::nist::{EcdsaSigningKeyP256, EcdsaSigningKeyP384}; +use self::eddsa::ed25519::Ed25519SigningKey; use self::rsa::RsaSigningKey; use pki_types::PrivateKeyDer; diff --git a/src/sign/ecdsa.rs b/src/sign/ecdsa.rs index 04c3f0f..a6db7e6 100644 --- a/src/sign/ecdsa.rs +++ b/src/sign/ecdsa.rs @@ -1,2 +1 @@ -mod nist; -pub use nist::*; +pub mod nist; diff --git a/src/sign/eddsa.rs b/src/sign/eddsa.rs index 67c97fc..58845d3 100644 --- a/src/sign/eddsa.rs +++ b/src/sign/eddsa.rs @@ -1,2 +1 @@ -mod ed25519; -pub use ed25519::*; +pub mod ed25519; diff --git a/src/tls12.rs b/src/tls12.rs index 963567a..809f0e5 100644 --- a/src/tls12.rs +++ b/src/tls12.rs @@ -1,16 +1,2 @@ -use crate::misc::const_concat_slices; -use rustls::SupportedCipherSuite; - -pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( - SupportedCipherSuite, - TLS_ECDHE_ECDSA_SUITES, - TLS_ECDHE_RSA_SUITES -); - -pub mod ecdsa; -pub mod rsa; -pub mod schemes; - -pub use ecdsa::*; -pub use rsa::*; -pub use schemes::*; +pub mod aead; +pub mod suites; diff --git a/src/tls12/aead.rs b/src/tls12/aead.rs new file mode 100644 index 0000000..be14f13 --- /dev/null +++ b/src/tls12/aead.rs @@ -0,0 +1,2 @@ +pub mod chacha20; +pub mod gcm; diff --git a/src/aead/chacha20/tls12.rs b/src/tls12/aead/chacha20.rs similarity index 94% rename from src/aead/chacha20/tls12.rs rename to src/tls12/aead/chacha20.rs index e93e293..be74677 100644 --- a/src/aead/chacha20/tls12.rs +++ b/src/tls12/aead/chacha20.rs @@ -1,7 +1,9 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; -use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; +use crate::aead::{ + ChaCha20Poly1305, DecryptBufferAdapter, EncryptBufferAdapter, CHACHAPOLY1305_OVERHEAD, +}; use chacha20poly1305::{AeadInPlace, KeyInit}; use rustls::crypto::cipher::{ self, make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, @@ -11,9 +13,7 @@ use rustls::crypto::cipher::{ use rustls::crypto::cipher::{KeyBlockShape, Tls12AeadAlgorithm, NONCE_LEN}; use rustls::ConnectionTrafficSecrets; -use super::{ChaCha20Poly1305, CHACHAPOLY1305_OVERHEAD}; - -struct CipherAdapter(chacha20poly1305::ChaCha20Poly1305, Iv); +pub struct CipherAdapter(chacha20poly1305::ChaCha20Poly1305, Iv); impl Tls12AeadAlgorithm for ChaCha20Poly1305 { fn encrypter(&self, key: AeadKey, iv: &[u8], _: &[u8]) -> Box { diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs new file mode 100644 index 0000000..dbc18d3 --- /dev/null +++ b/src/tls12/aead/gcm.rs @@ -0,0 +1,135 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crate::aead::{Aes128Gcm, Aes256Gcm}; +use aead::{AeadCore, AeadInPlace}; +use crypto_common::typenum::Unsigned; +use crypto_common::{KeyInit, KeySizeUser}; +use paste::paste; +use rustls::crypto::cipher::{ + self, make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, + MessageDecrypter, MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, + PrefixedPayload, Tls12AeadAlgorithm, +}; +use rustls::ConnectionTrafficSecrets; + +const TLS12_GCM_EXPLICIT_NONCE_LEN: usize = 8; + +const TLS12_GCM_OVERHEAD: usize = TLS12_GCM_EXPLICIT_NONCE_LEN + 16; + +macro_rules! impl_gcm { +($name: ident, $aead: ty, $nonce_pos: expr, $overhead: expr) => { + paste! { + impl Tls12AeadAlgorithm for $name { + fn encrypter(&self, key: AeadKey, write_iv: &[u8], explicit: &[u8]) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + { + let mut iv: [u8; 12] = [0; 12]; + iv[..4].copy_from_slice(write_iv); + iv[4..].copy_from_slice(explicit); + iv + }, + )) + } + + fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { + Box::new([]( + $aead::new_from_slice(dec_key.as_ref()).unwrap(), + dec_iv.try_into().unwrap(), + )) + } + + fn key_block_shape(&self) -> KeyBlockShape { + KeyBlockShape { + enc_key_len: $aead::key_size(), + fixed_iv_len: 4, + explicit_nonce_len: 8, + } + } + + fn extract_keys( + &self, + key: AeadKey, + iv: &[u8], + _explicit: &[u8], + ) -> Result { + Ok(ConnectionTrafficSecrets::$name { + key, + iv: Iv::new(iv[..].try_into().unwrap()), + }) + } + } + + pub struct []($aead, [u8; 12]); + + impl MessageEncrypter for [] { + fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + let nonce = cipher::Nonce::new(&self.1.into(), seq).0; + let aad = make_tls12_aad(seq, m.typ, m.version, m.payload.len()); + payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit + payload.extend_from_chunks(&m.payload); + + self.0 + .encrypt_in_place_detached(&nonce.into(), &aad, &mut payload.as_mut()[$nonce_pos..]) + .map(|tag| payload.extend(tag.as_ref() as &[u8])) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) + } + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + $nonce_pos + <$aead as AeadCore>::TagSize::USIZE + } + } + + pub struct []($aead, [u8; 4]); + + impl MessageDecrypter for [] { + fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { + type TagSize = <$aead as AeadCore>::TagSize; + + let payload = &m.payload; + + if payload.len() < $overhead { + return Err(rustls::Error::DecryptError); + } + + let nonce: aead::Nonce<$aead> = { + let mut nonce = [0u8; 12]; + nonce[..4].copy_from_slice(&self.1); // dec_iv + nonce[4..].copy_from_slice(&payload[..$nonce_pos]); + nonce.into() + }; + + let aad = make_tls12_aad(seq, m.typ, m.version, payload.len() - $overhead); + + let payload = &mut m.payload; + let tag_pos = { + let payload = &mut payload[$nonce_pos..]; + let tag_pos = payload.len() - TagSize::to_usize(); + let (msg, tag) = payload.split_at_mut(tag_pos); + + let tag = aes_gcm::Tag::::from_slice(tag); + self.0 + .decrypt_in_place_detached(&nonce, &aad, msg, tag) + .map_err(|_| rustls::Error::DecryptError)?; + tag_pos + }; + + // We defer the truncation to here, because we may inadvertently shifted the + // original data if the decryption failed. Another way to avoid this is + // to clone the payload slice starting after the explicit nonce, + // but this will cause an additional cloning and copying + payload.rotate_left($nonce_pos); + payload.truncate(tag_pos); + Ok(m.into_plain_message()) + } + } + } +}; +} + +impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} +impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} diff --git a/src/tls12/suites.rs b/src/tls12/suites.rs new file mode 100644 index 0000000..e8b8188 --- /dev/null +++ b/src/tls12/suites.rs @@ -0,0 +1,14 @@ +use crate::misc::const_concat_slices; +use ecdsa::TLS_ECDHE_ECDSA_SUITES; +use rsa::TLS_ECDHE_RSA_SUITES; +use rustls::SupportedCipherSuite; + +pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + TLS_ECDHE_ECDSA_SUITES, + TLS_ECDHE_RSA_SUITES +); + +pub mod ecdsa; +pub mod rsa; +pub mod schemes; diff --git a/src/tls12/ecdsa.rs b/src/tls12/suites/ecdsa.rs similarity index 95% rename from src/tls12/ecdsa.rs rename to src/tls12/suites/ecdsa.rs index 46aad02..8d14f40 100644 --- a/src/tls12/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -1,5 +1,4 @@ -use crate::aead::chacha20::ChaCha20Poly1305; -use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::aead::{Aes128Gcm, Aes256Gcm, ChaCha20Poly1305}; use crate::{hash, hmac}; use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorithm}; use rustls::{CipherSuite, SupportedCipherSuite, Tls12CipherSuite}; diff --git a/src/tls12/rsa.rs b/src/tls12/suites/rsa.rs similarity index 95% rename from src/tls12/rsa.rs rename to src/tls12/suites/rsa.rs index a04e4a6..b1c6997 100644 --- a/src/tls12/rsa.rs +++ b/src/tls12/suites/rsa.rs @@ -1,5 +1,4 @@ -use crate::aead::chacha20::ChaCha20Poly1305; -use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::aead::{Aes128Gcm, Aes256Gcm, ChaCha20Poly1305}; use crate::{hash, hmac}; use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorithm}; use rustls::{CipherSuite, SupportedCipherSuite, Tls12CipherSuite}; diff --git a/src/tls12/schemes.rs b/src/tls12/suites/schemes.rs similarity index 100% rename from src/tls12/schemes.rs rename to src/tls12/suites/schemes.rs diff --git a/src/tls13.rs b/src/tls13.rs index d4c069e..809f0e5 100644 --- a/src/tls13.rs +++ b/src/tls13.rs @@ -1,14 +1,2 @@ -use crate::const_concat_slices; -use rustls::SupportedCipherSuite; - -pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( - SupportedCipherSuite, - TLS13_AES_SUITES, - &[TLS13_CHACHA20_POLY1305_SHA256] -); - -pub mod aes; -pub mod chacha20; - -pub use aes::*; -pub use chacha20::*; +pub mod aead; +pub mod suites; diff --git a/src/tls13/aead.rs b/src/tls13/aead.rs new file mode 100644 index 0000000..be14f13 --- /dev/null +++ b/src/tls13/aead.rs @@ -0,0 +1,2 @@ +pub mod chacha20; +pub mod gcm; diff --git a/src/aead/chacha20/tls13.rs b/src/tls13/aead/chacha20.rs similarity index 94% rename from src/aead/chacha20/tls13.rs rename to src/tls13/aead/chacha20.rs index ab7043b..058482c 100644 --- a/src/aead/chacha20/tls13.rs +++ b/src/tls13/aead/chacha20.rs @@ -1,8 +1,9 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; -use super::{ChaCha20Poly1305, CHACHAPOLY1305_OVERHEAD}; -use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; +use crate::aead::{ + ChaCha20Poly1305, DecryptBufferAdapter, EncryptBufferAdapter, CHACHAPOLY1305_OVERHEAD, +}; use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser}; use rustls::crypto::cipher::{ self, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, MessageDecrypter, @@ -41,7 +42,7 @@ impl Tls13AeadAlgorithm for ChaCha20Poly1305 { } } -struct CipherAdapter(chacha20poly1305::ChaCha20Poly1305, Iv); +pub struct CipherAdapter(chacha20poly1305::ChaCha20Poly1305, Iv); impl MessageEncrypter for CipherAdapter { fn encrypt( diff --git a/src/tls13/aead/gcm.rs b/src/tls13/aead/gcm.rs new file mode 100644 index 0000000..9dd30cd --- /dev/null +++ b/src/tls13/aead/gcm.rs @@ -0,0 +1,91 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crate::aead::{Aes128Gcm, Aes256Gcm, DecryptBufferAdapter, EncryptBufferAdapter}; +use aead::AeadInPlace; +use crypto_common::{KeyInit, KeySizeUser}; +use paste::paste; +use rustls::crypto::cipher::{ + self, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + Tls13AeadAlgorithm, +}; +use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; + +macro_rules! impl_gcm { +($name: ident, $aead: ty, $overhead: expr) => { + paste! { + impl Tls13AeadAlgorithm for $name { + fn encrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + iv, + )) + } + + fn decrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + iv, + )) + } + + fn key_len(&self) -> usize { + $aead::key_size() + } + fn extract_keys( + &self, + key: AeadKey, + iv: cipher::Iv, + ) -> Result { + Ok(ConnectionTrafficSecrets::$name { key, iv }) + } + } + + pub struct []($aead, cipher::Iv); + + impl MessageEncrypter for [] { + fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + let nonce = cipher::Nonce::new(&self.1, seq).0; + let aad = make_tls13_aad(total_len); + payload.extend_from_chunks(&m.payload); + payload.extend_from_slice(&m.typ.to_array()); + + self.0 + .encrypt_in_place(&nonce.into(), &aad, &mut EncryptBufferAdapter(&mut payload)) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + )) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + 1 + $overhead + } + } + + impl MessageDecrypter for [] { + fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { + let payload = &mut m.payload; + let nonce = cipher::Nonce::new(&self.1, seq).0; + let aad = make_tls13_aad(payload.len()); + + self.0 + .decrypt_in_place(&nonce.into(), &aad, &mut DecryptBufferAdapter(payload)) + .map_err(|_| rustls::Error::DecryptError)?; + + m.into_tls13_unpadded_message() + } + } + + } +}; +} + +impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, 16} +impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, 16} diff --git a/src/tls13/suites.rs b/src/tls13/suites.rs new file mode 100644 index 0000000..299dfe2 --- /dev/null +++ b/src/tls13/suites.rs @@ -0,0 +1,13 @@ +use crate::const_concat_slices; +use aes::TLS13_AES_SUITES; +use chacha20::TLS13_CHACHA20_POLY1305_SHA256; +use rustls::SupportedCipherSuite; + +pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + TLS13_AES_SUITES, + &[TLS13_CHACHA20_POLY1305_SHA256] +); + +pub mod aes; +pub mod chacha20; diff --git a/src/tls13/aes.rs b/src/tls13/suites/aes.rs similarity index 95% rename from src/tls13/aes.rs rename to src/tls13/suites/aes.rs index 99d9081..9db122b 100644 --- a/src/tls13/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,4 +1,4 @@ -use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::aead::{Aes128Gcm, Aes256Gcm}; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; diff --git a/src/tls13/chacha20.rs b/src/tls13/suites/chacha20.rs similarity index 92% rename from src/tls13/chacha20.rs rename to src/tls13/suites/chacha20.rs index 4fd8847..ceae440 100644 --- a/src/tls13/chacha20.rs +++ b/src/tls13/suites/chacha20.rs @@ -1,4 +1,4 @@ -use crate::aead::chacha20::ChaCha20Poly1305; +use crate::aead::ChaCha20Poly1305; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; diff --git a/src/verify.rs b/src/verify.rs index 0f50a6c..3169f65 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,7 +1,9 @@ use core::array::TryFromSliceError; -use self::ecdsa::{ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384}; -use self::eddsa::ED25519; +use self::ecdsa::nist::{ + ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384, +}; +use self::eddsa::ed25519::ED25519; use self::rsa::{ RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384, RSA_PSS_SHA512, diff --git a/src/verify/ecdsa.rs b/src/verify/ecdsa.rs index 04c3f0f..a6db7e6 100644 --- a/src/verify/ecdsa.rs +++ b/src/verify/ecdsa.rs @@ -1,2 +1 @@ -mod nist; -pub use nist::*; +pub mod nist; diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs index 34a7c11..7155990 100644 --- a/src/verify/ecdsa/nist.rs +++ b/src/verify/ecdsa/nist.rs @@ -17,7 +17,7 @@ macro_rules! impl_generic_ecdsa_verifer { paste! { #[allow(non_camel_case_types)] #[derive(Debug)] - struct []; + pub struct []; impl [] { fn verify_inner(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result<(), crate::verify::Error> { diff --git a/src/verify/eddsa.rs b/src/verify/eddsa.rs index 67c97fc..58845d3 100644 --- a/src/verify/eddsa.rs +++ b/src/verify/eddsa.rs @@ -1,2 +1 @@ -mod ed25519; -pub use ed25519::*; +pub mod ed25519; diff --git a/src/verify/eddsa/ed25519.rs b/src/verify/eddsa/ed25519.rs index d669d70..c57dbfe 100644 --- a/src/verify/eddsa/ed25519.rs +++ b/src/verify/eddsa/ed25519.rs @@ -4,7 +4,7 @@ use signature::Verifier; use webpki::alg_id; #[derive(Debug)] -struct Ed25519Verify; +pub struct Ed25519Verify; impl Ed25519Verify { fn verify_inner( diff --git a/src/verify/rsa.rs b/src/verify/rsa.rs index e6ee5a8..1b46362 100644 --- a/src/verify/rsa.rs +++ b/src/verify/rsa.rs @@ -17,7 +17,7 @@ macro_rules! impl_generic_rsa_verifer { paste! { #[allow(non_camel_case_types)] #[derive(Debug)] - struct []; + pub struct []; impl [] { fn verify_inner( From 8f93ce904403b995f1526a5136177887a97f7a97 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:00:39 +0800 Subject: [PATCH 03/38] remove derive_more --- Cargo.lock | 28 ---------------------------- Cargo.toml | 1 - src/sign/rsa.rs | 3 +-- src/verify.rs | 10 +++++++--- 4 files changed, 8 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 240d64b..9fc44bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,27 +204,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "derive_more" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "digest" version = "0.10.7" @@ -711,7 +690,6 @@ dependencies = [ "chacha20poly1305", "crypto-common", "der", - "derive_more", "digest", "ecdsa", "ed25519-dalek", @@ -862,12 +840,6 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "universal-hash" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 5b00616..7e3732b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "al chacha20poly1305 = { version = "0.10.1", default-features = false } crypto-common = { version = "0.1.6", default-features = false } der = { version = "0.7.9", default-features = false } -derive_more = { version = "1.0.0", default-features = false, features = ["display", "debug", "deref", "from", "into", "error"] } digest = { version = "0.10.7", default-features = false } ecdsa = { version = "0.16.9", default-features = false, features = ["alloc"] } ed25519-dalek = { version = "2", default-features = false, features = ["pkcs8"] } diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index a69c1da..bfaf6c9 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -1,7 +1,6 @@ #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, string::ToString, sync::Arc}; -use derive_more::{Debug, Deref}; use pkcs8::DecodePrivateKey; use pki_types::PrivateKeyDer; use rsa::pkcs1::DecodeRsaPrivateKey; @@ -19,7 +18,7 @@ const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ SignatureScheme::RSA_PKCS1_SHA256, ]; -#[derive(Debug, Deref, Clone)] +#[derive(Debug, Clone)] pub struct RsaSigningKey(RsaPrivateKey); impl TryFrom<&PrivateKeyDer<'_>> for RsaSigningKey { diff --git a/src/verify.rs b/src/verify.rs index 3169f65..61c6d2d 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -8,14 +8,12 @@ use self::rsa::{ RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384, RSA_PSS_SHA512, }; -use derive_more::From; use rustls::crypto::WebPkiSupportedAlgorithms; use rustls::SignatureScheme; -#[derive(From)] pub(crate) enum Error { Signature, - TryFromSlice(TryFromSliceError), + TryFromSlice, Der, Pkcs1, } @@ -38,6 +36,12 @@ impl From for Error { } } +impl From for Error { + fn from(_: TryFromSliceError) -> Self { + Self::TryFromSlice + } +} + pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { all: &[ ECDSA_P256_SHA256, From 7e7326363d8bff4fa3c8c5629e6fdb40b94792d2 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 28 Sep 2024 01:56:33 +0800 Subject: [PATCH 04/38] let tls suite features be optional --- Cargo.lock | 11 ++ Cargo.toml | 116 ++++++++++++++++---- src/kx.rs | 14 ++- src/kx/nist.rs | 3 + src/lib.rs | 7 +- src/sign.rs | 51 +++++++-- src/sign/ecdsa.rs | 1 + src/sign/ecdsa/nist.rs | 12 ++- src/sign/eddsa.rs | 1 + src/sign/eddsa/ed25519.rs | 26 +++-- src/sign/rsa.rs | 22 ++-- src/tls12/aead.rs | 3 + src/tls12/aead/gcm.rs | 9 +- src/tls12/suites.rs | 28 ++++- src/tls12/suites/ecdsa.rs | 106 ++++++++++-------- src/tls12/suites/rsa.rs | 106 ++++++++++-------- src/tls12/suites/schemes.rs | 18 +++- src/tls13/aead.rs | 3 + src/tls13/suites.rs | 30 +++++- src/verify.rs | 207 +++++++++++++++++++++++++++++------- src/verify/ecdsa.rs | 1 + src/verify/ecdsa/nist.rs | 7 +- src/verify/rsa.rs | 37 ++++--- 23 files changed, 603 insertions(+), 216 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9fc44bd..02fd241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -471,6 +471,16 @@ dependencies = [ "sha2", ] +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "elliptic-curve", +] + [[package]] name = "paste" version = "1.0.15" @@ -697,6 +707,7 @@ dependencies = [ "hmac", "p256", "p384", + "p521", "paste", "pkcs1", "pkcs8", diff --git a/Cargo.toml b/Cargo.toml index 7e3732b..50127fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,35 +18,65 @@ resolver = "1" # Hack to enable the `custom` feature of `getrandom` # Ensure all dependencies + feats are mapped to crate features for correct usage # default features often have std breaking no_std and potentially other unwanted [dependencies] -aead = { version = "0.5.2", default-features = false } -aes-gcm = { version = "0.10.3", default-features = false, features = ["aes", "alloc"] } -chacha20poly1305 = { version = "0.10.1", default-features = false } +aead = { version = "0.5.2", default-features = false, optional = true } +aes-gcm = { version = "0.10.3", default-features = false, features = [ + "aes", +], optional = true } +chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } -der = { version = "0.7.9", default-features = false } +der = { version = "0.7.9", default-features = false, optional = true } digest = { version = "0.10.7", default-features = false } -ecdsa = { version = "0.16.9", default-features = false, features = ["alloc"] } -ed25519-dalek = { version = "2", default-features = false, features = ["pkcs8"] } +ecdsa = { version = "0.16.9", default-features = false, optional = true } +ed25519-dalek = { version = "2", default-features = false, optional = true } hmac = { version = "0.12.1", default-features = false } -p256 = { version = "0.13.2", default-features = false, features = ["pem", "ecdsa", "ecdh"] } -p384 = { version = "0.13.0", default-features = false, features = ["pem", "ecdsa", "ecdh"] } +p256 = { version = "0.13.2", default-features = false, optional = true } +p384 = { version = "0.13.0", default-features = false, optional = true } +pkcs1 = { version = "0.7.5", default-features = false, optional = true } +pkcs8 = { version = "0.10.2", default-features = false, features = [ + "pkcs5", +], optional = true } +rsa = { version = "0.9.6", default-features = false, features = [ + "sha2", +], optional = true } +sec1 = { version = "0.7.3", default-features = false, optional = true } +sha2 = { version = "0.10.8", default-features = false } +signature = { version = "2.2.0", features = [ + "rand_core", +], default-features = false } +x25519-dalek = { version = "2", default-features = false, optional = true } + paste = { version = "1.0.15", default-features = false } -pkcs1 = { version = "0.7.5", default-features = false } -pkcs8 = { version = "0.10.2", default-features = false, features = ["pem", "pkcs5"] } pki-types = { package = "rustls-pki-types", version = "1.8.0", default-features = false } -rand_core = { version = "0.6.4", default-features = false, features = ["getrandom"] } -rsa = { version = "0.9.6", default-features = false, features = ["sha2"] } +rand_core = { version = "0.6.4", default-features = false, features = [ + "getrandom", +] } rustls = { version = "0.23.13", default-features = false } -sec1 = { version = "0.7.3", default-features = false, features = ["pkcs8", "pem"] } -sha2 = { version = "0.10.8", default-features = false } -signature = { version = "2.2.0", default-features = false } webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false } -x25519-dalek = { version = "2", default-features = false } +p521 = { version = "0.13.3", default-features = false, optional = true } + [dev-dependencies] -getrandom = { version = "0.2", features = ["custom"] } # workaround to build on no_std targets +getrandom = { version = "0.2", features = [ + "custom", +] } # workaround to build on no_std targets [features] -default = ["std", "tls12", "zeroize"] +default = ["std", "tls12", "zeroize", "full"] +full = [ + "aes-gcm", + "chacha20poly1305", + "ed25519", + "p256", + "p384", + "pem", + "pkcs1", + "pkcs8", + "rsa-pkcs1", + "rsa-pss", + "sec1", + "x25519", + "der", +] logging = ["rustls/logging"] tls12 = ["rustls/tls12"] @@ -54,7 +84,49 @@ tls12 = ["rustls/tls12"] # zeroize is another typical that can be turned off # TODO: go through all of these that what gets exposed re: std error type -std = ["alloc", "webpki/std", "pki-types/std", "rustls/std", "ed25519-dalek/std", "pkcs1/std"] -# TODO: go through all of these to ensure to_vec etc. impls are exposed -alloc = ["webpki/alloc", "pki-types/alloc", "aead/alloc", "ed25519-dalek/alloc", "pkcs1/alloc"] -zeroize = ["ed25519-dalek/zeroize", "x25519-dalek/zeroize"] +std = [ + "alloc", + "webpki/std", + "pki-types/std", + "rustls/std", + "ed25519-dalek?/std", + "pkcs1?/std", +] + +alloc = ["webpki/alloc", "ecdsa?/alloc", "signature/alloc"] +zeroize = ["ed25519-dalek?/zeroize", "x25519-dalek?/zeroize"] + +nist = [] +p256 = ["dep:p256", "nist", "kx", "ecdsa"] +p384 = ["dep:p384", "nist", "kx", "ecdsa"] +p521 = ["dep:p521", "nist", "kx", "ecdsa"] + +sec1 = ["dep:sec1"] +pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem"] + +pkcs1 = ["dep:pkcs1"] +pkcs8 = [ + "dep:pkcs8", + "ed25519-dalek?/pkcs8", + "sec1?/pkcs8", + "p256?/pkcs8", + "p384?/pkcs8", +] + +ecdsa = ["dep:ecdsa", "p256?/ecdsa", "p384?/ecdsa"] + +eddsa = [] +ed25519 = ["dep:ed25519-dalek", "eddsa"] + +kx = ["p256?/ecdh", "p384?/ecdh"] +x25519 = ["dep:x25519-dalek", "kx"] + +rsa = ["dep:rsa"] +rsa-pkcs1 = ["rsa", "pkcs1"] +rsa-pss = ["rsa"] + +aead = ["dep:aead"] +aes-gcm = ["dep:aes-gcm", "aead"] +chacha20poly1305 = ["dep:chacha20poly1305", "aead"] + +der = ["dep:der"] diff --git a/src/kx.rs b/src/kx.rs index e64bed1..a9bdd05 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -1,8 +1,16 @@ -use nist::{SecP256R1, SecP384R1}; use rustls::crypto::SupportedKxGroup; -use x25519::X25519; -pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1]; +pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ + #[cfg(feature = "x25519")] + &x25519::X25519, + #[cfg(feature = "p256")] + &nist::SecP256R1, + #[cfg(feature = "p384")] + &nist::SecP384R1, +]; +#[cfg(feature = "nist")] pub mod nist; + +#[cfg(feature = "x25519")] pub mod x25519; diff --git a/src/kx/nist.rs b/src/kx/nist.rs index a9983bd..c817b43 100644 --- a/src/kx/nist.rs +++ b/src/kx/nist.rs @@ -60,5 +60,8 @@ macro_rules! impl_kx { }; } +#[cfg(feature = "p256")] impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, ::p256::ecdh::EphemeralSecret, ::p256::PublicKey} + +#[cfg(feature = "p384")] impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, ::p384::ecdh::EphemeralSecret, ::p384::PublicKey} diff --git a/src/lib.rs b/src/lib.rs index f2fd74d..6be60ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,18 +83,17 @@ pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices { tls12::suites::TLS12_SUITES } - #[cfg(not(feature = "tls12"))] - { - &[] - } }, tls13::suites::TLS13_SUITES, ); +#[cfg(feature = "aead")] pub mod aead; pub mod hash; pub mod hmac; + pub mod kx; + pub mod misc; pub mod sign; pub mod verify; diff --git a/src/sign.rs b/src/sign.rs index 9aa7e52..b08841b 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -2,8 +2,13 @@ use alloc::{sync::Arc, vec::Vec}; use core::marker::PhantomData; +#[cfg(all(feature = "ecdsa", feature = "der"))] use self::ecdsa::nist::{EcdsaSigningKeyP256, EcdsaSigningKeyP384}; + +#[cfg(all(feature = "eddsa", feature = "ed25519"))] use self::eddsa::ed25519::Ed25519SigningKey; + +#[cfg(feature = "rsa")] use self::rsa::RsaSigningKey; use pki_types::PrivateKeyDer; @@ -72,11 +77,24 @@ where /// # Errors /// /// Returns an error if the key couldn't be decoded. +#[allow(unused_variables)] pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - RsaSigningKey::try_from(der) - .map(|x| Arc::new(x) as _) - .or_else(|_| any_ecdsa_type(der)) - .or_else(|_| any_eddsa_type(der)) + #[cfg(feature = "rsa")] + if let Ok(key) = RsaSigningKey::try_from(der) { + return Ok(Arc::new(key) as _); + } + + #[cfg(feature = "ecdsa")] + if let Ok(key) = any_ecdsa_type(der) { + return Ok(key); + } + + #[cfg(feature = "eddsa")] + if let Ok(key) = any_eddsa_type(der) { + return Ok(key); + } + + Err(rustls::Error::General("not supported".into())) } /// Extract any supported ECDSA key from the given DER input. @@ -84,10 +102,18 @@ pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result /// # Errors /// /// Returns an error if the key couldn't be decoded. +#[allow(unused_variables)] pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - let p256 = |_| EcdsaSigningKeyP256::try_from(der).map(|x| Arc::new(x) as _); - let p384 = |_| EcdsaSigningKeyP384::try_from(der).map(|x| Arc::new(x) as _); - p256(()).or_else(p384) + #[cfg(all(feature = "der", feature = "p256"))] + if let Ok(key) = EcdsaSigningKeyP256::try_from(der) { + return Ok(Arc::new(key) as _); + } + #[cfg(all(feature = "der", feature = "p384"))] + if let Ok(key) = EcdsaSigningKeyP384::try_from(der) { + return Ok(Arc::new(key) as _); + } + + Err(rustls::Error::General("not supported".into())) } /// Extract any supported EDDSA key from the given DER input. @@ -95,11 +121,20 @@ pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, ru /// # Errors /// /// Returns an error if the key couldn't be decoded. +#[allow(unused_variables)] pub fn any_eddsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { // TODO: Add support for Ed448 - Ed25519SigningKey::try_from(der).map(|x| Arc::new(x) as _) + #[cfg(feature = "ed25519")] + if let Ok(key) = Ed25519SigningKey::try_from(der) { + return Ok(Arc::new(key) as _); + } + + Err(rustls::Error::General("not supported".into())) } +#[cfg(feature = "ecdsa")] pub mod ecdsa; +#[cfg(feature = "eddsa")] pub mod eddsa; +#[cfg(feature = "rsa")] pub mod rsa; diff --git a/src/sign/ecdsa.rs b/src/sign/ecdsa.rs index a6db7e6..9e8a797 100644 --- a/src/sign/ecdsa.rs +++ b/src/sign/ecdsa.rs @@ -1 +1,2 @@ +#[cfg(feature = "nist")] pub mod nist; diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs index 4a70551..b647a3e 100644 --- a/src/sign/ecdsa/nist.rs +++ b/src/sign/ecdsa/nist.rs @@ -4,11 +4,11 @@ use core::marker::PhantomData; use crate::sign::GenericRandomizedSigner; use paste::paste; -use pkcs8::DecodePrivateKey; + +#[cfg(feature = "der")] use pki_types::PrivateKeyDer; use rustls::sign::SigningKey; use rustls::{SignatureAlgorithm, SignatureScheme}; -use sec1::DecodeEcPrivateKey; macro_rules! impl_ecdsa { ($name: ident, $scheme: expr, $signing_key: ty, $signature: ty) => { @@ -19,15 +19,20 @@ macro_rules! impl_ecdsa { scheme: SignatureScheme, } + #[cfg(feature = "der")] impl TryFrom<&PrivateKeyDer<'_>> for [] { type Error = rustls::Error; fn try_from(value: &PrivateKeyDer<'_>) -> Result { let pkey = match value { + #[cfg(feature = "pkcs8")] PrivateKeyDer::Pkcs8(der) => { + use pkcs8::DecodePrivateKey; $signing_key::from_pkcs8_der(der.secret_pkcs8_der()).map_err(|e| format!("failed to decrypt private key: {e}")) }, + #[cfg(feature = "sec1")] PrivateKeyDer::Sec1(sec1) => { + use sec1::DecodeEcPrivateKey; $signing_key::from_sec1_der(sec1.secret_sec1_der()).map_err(|e| format!("failed to decrypt private key: {e}")) }, PrivateKeyDer::Pkcs1(_) => Err(format!("ECDSA does not support PKCS#1 key")), @@ -63,5 +68,8 @@ macro_rules! impl_ecdsa { }; } +#[cfg(feature = "p256")] impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, ::p256::ecdsa::SigningKey, ::p256::ecdsa::DerSignature} + +#[cfg(feature = "p256")] impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, ::p384::ecdsa::SigningKey, ::p384::ecdsa::DerSignature} diff --git a/src/sign/eddsa.rs b/src/sign/eddsa.rs index 58845d3..5141d74 100644 --- a/src/sign/eddsa.rs +++ b/src/sign/eddsa.rs @@ -1 +1,2 @@ +#[cfg(feature = "ed25519")] pub mod ed25519; diff --git a/src/sign/eddsa/ed25519.rs b/src/sign/eddsa/ed25519.rs index 2d1d1ea..43a1a28 100644 --- a/src/sign/eddsa/ed25519.rs +++ b/src/sign/eddsa/ed25519.rs @@ -1,27 +1,31 @@ +use crate::sign::GenericSigner; #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, string::ToString, sync::Arc}; use core::marker::PhantomData; use ed25519_dalek::SigningKey; -use rustls::{sign::Signer, SignatureAlgorithm, SignatureScheme}; - -use pkcs8::DecodePrivateKey; use pki_types::PrivateKeyDer; -use sec1::DecodeEcPrivateKey; - -use crate::sign::GenericSigner; - +use rustls::{sign::Signer, SignatureAlgorithm, SignatureScheme}; #[derive(Debug)] pub struct Ed25519SigningKey(Arc); +#[cfg(feature = "der")] impl TryFrom<&PrivateKeyDer<'_>> for Ed25519SigningKey { type Error = rustls::Error; fn try_from(value: &PrivateKeyDer<'_>) -> Result { let pkey = match value { - PrivateKeyDer::Pkcs8(der) => SigningKey::from_pkcs8_der(der.secret_pkcs8_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")), - PrivateKeyDer::Sec1(sec1) => SigningKey::from_sec1_der(sec1.secret_sec1_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")), + #[cfg(feature = "pkcs8")] + PrivateKeyDer::Pkcs8(der) => { + use pkcs8::DecodePrivateKey; + SigningKey::from_pkcs8_der(der.secret_pkcs8_der()) + .map_err(|e| format!("failed to decrypt private key: {e}")) + } + #[cfg(all(feature = "pkcs8", feature = "sec1"))] + PrivateKeyDer::Sec1(sec1) => { + use sec1::DecodeEcPrivateKey; + SigningKey::from_sec1_der(sec1.secret_sec1_der()) + .map_err(|e| format!("failed to decrypt private key: {e}")) + } PrivateKeyDer::Pkcs1(_) => Err("ED25519 does not support PKCS#1 key".to_string()), _ => Err("not supported".into()), }; diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index bfaf6c9..459e084 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -1,9 +1,8 @@ #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, string::ToString, sync::Arc}; -use pkcs8::DecodePrivateKey; use pki_types::PrivateKeyDer; -use rsa::pkcs1::DecodeRsaPrivateKey; + use rsa::RsaPrivateKey; use rustls::sign::{Signer, SigningKey}; use rustls::{SignatureAlgorithm, SignatureScheme}; @@ -21,15 +20,24 @@ const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ #[derive(Debug, Clone)] pub struct RsaSigningKey(RsaPrivateKey); +#[cfg(feature = "der")] impl TryFrom<&PrivateKeyDer<'_>> for RsaSigningKey { type Error = rustls::Error; fn try_from(value: &PrivateKeyDer<'_>) -> Result { let pkey = match value { - PrivateKeyDer::Pkcs8(der) => RsaPrivateKey::from_pkcs8_der(der.secret_pkcs8_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")), - PrivateKeyDer::Pkcs1(der) => RsaPrivateKey::from_pkcs1_der(der.secret_pkcs1_der()) - .map_err(|e| format!("failed to decrypt private key: {e}")), + #[cfg(feature = "pkcs8")] + PrivateKeyDer::Pkcs8(der) => { + use pkcs8::DecodePrivateKey; + RsaPrivateKey::from_pkcs8_der(der.secret_pkcs8_der()) + .map_err(|e| format!("failed to decrypt private key: {e}")) + } + #[cfg(feature = "pkcs1")] + PrivateKeyDer::Pkcs1(der) => { + use pkcs1::DecodeRsaPrivateKey; + RsaPrivateKey::from_pkcs1_der(der.secret_pkcs1_der()) + .map_err(|e| format!("failed to decrypt private key: {e}")) + } PrivateKeyDer::Sec1(_) => Err("RSA does not support SEC-1 key".to_string()), _ => Err("not supported".into()), }; @@ -57,7 +65,7 @@ impl SigningKey for RsaSigningKey { match scheme { SignatureScheme::RSA_PSS_SHA512 => signer! {::rsa::pss::SigningKey::}, SignatureScheme::RSA_PSS_SHA384 => signer! {::rsa::pss::SigningKey::}, - SignatureScheme::RSA_PSS_SHA256 => signer! {rsa::pss::SigningKey::}, + SignatureScheme::RSA_PSS_SHA256 => signer! {::rsa::pss::SigningKey::}, SignatureScheme::RSA_PKCS1_SHA512 => { signer! {::rsa::pkcs1v15::SigningKey::} } diff --git a/src/tls12/aead.rs b/src/tls12/aead.rs index be14f13..eca37fa 100644 --- a/src/tls12/aead.rs +++ b/src/tls12/aead.rs @@ -1,2 +1,5 @@ +#[cfg(feature = "chacha20poly1305")] pub mod chacha20; + +#[cfg(feature = "aes-gcm")] pub mod gcm; diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs index dbc18d3..59b8ad9 100644 --- a/src/tls12/aead/gcm.rs +++ b/src/tls12/aead/gcm.rs @@ -13,9 +13,8 @@ use rustls::crypto::cipher::{ }; use rustls::ConnectionTrafficSecrets; -const TLS12_GCM_EXPLICIT_NONCE_LEN: usize = 8; - -const TLS12_GCM_OVERHEAD: usize = TLS12_GCM_EXPLICIT_NONCE_LEN + 16; +const EXPLICIT_NONCE_LEN: usize = 8; +const OVERHEAD: usize = EXPLICIT_NONCE_LEN + 16; macro_rules! impl_gcm { ($name: ident, $aead: ty, $nonce_pos: expr, $overhead: expr) => { @@ -131,5 +130,5 @@ macro_rules! impl_gcm { }; } -impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} -impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, TLS12_GCM_EXPLICIT_NONCE_LEN, TLS12_GCM_OVERHEAD} +impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, EXPLICIT_NONCE_LEN, OVERHEAD} +impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, EXPLICIT_NONCE_LEN, OVERHEAD} diff --git a/src/tls12/suites.rs b/src/tls12/suites.rs index e8b8188..41dfac4 100644 --- a/src/tls12/suites.rs +++ b/src/tls12/suites.rs @@ -1,14 +1,34 @@ use crate::misc::const_concat_slices; -use ecdsa::TLS_ECDHE_ECDSA_SUITES; -use rsa::TLS_ECDHE_RSA_SUITES; use rustls::SupportedCipherSuite; pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( SupportedCipherSuite, - TLS_ECDHE_ECDSA_SUITES, - TLS_ECDHE_RSA_SUITES + { + #[cfg(feature = "ecdsa")] + { + ecdsa::TLS_ECDHE_ECDSA_SUITES + } + + #[cfg(not(feature = "ecdsa"))] + { + &[] + } + }, + { + #[cfg(feature = "rsa")] + { + rsa::TLS_ECDHE_RSA_SUITES + } + + #[cfg(not(feature = "rsa"))] + { + &[] + } + } ); +#[cfg(feature = "ecdsa")] pub mod ecdsa; +#[cfg(feature = "rsa")] pub mod rsa; pub mod schemes; diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs index 8d14f40..d5fc5d4 100644 --- a/src/tls12/suites/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -1,51 +1,65 @@ -use crate::aead::{Aes128Gcm, Aes256Gcm, ChaCha20Poly1305}; +use rustls::SupportedCipherSuite; + +#[cfg(feature = "aead")] use crate::{hash, hmac}; +#[cfg(feature = "aead")] use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorithm}; -use rustls::{CipherSuite, SupportedCipherSuite, Tls12CipherSuite}; - -use super::schemes::TLS12_ECDSA_SCHEMES; - -pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - aead_alg: &Aes128Gcm, - prf_provider: &PrfUsingHmac(hmac::SHA256), - }); - -pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - kx: KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - prf_provider: &PrfUsingHmac(hmac::SHA384), - aead_alg: &Aes256Gcm, - }); - -pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - prf_provider: &PrfUsingHmac(hmac::SHA256), - kx: KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_ECDSA_SCHEMES, - aead_alg: &ChaCha20Poly1305, - }); +#[cfg(feature = "aead")] +use rustls::{CipherSuite, Tls12CipherSuite}; + +#[cfg(feature = "aes-gcm")] +use crate::aead::{Aes128Gcm, Aes256Gcm}; + +#[cfg(feature = "chacha20poly1305")] +use crate::aead::ChaCha20Poly1305; + +#[cfg(feature = "aead")] +use crate::tls12::suites::schemes::TLS12_ECDSA_SCHEMES; + +#[cfg(feature = "aes-gcm")] +pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + aead_alg: &Aes128Gcm, + prf_provider: &PrfUsingHmac(hmac::SHA256), +}; + +#[cfg(feature = "aes-gcm")] +pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + hash_provider: hash::SHA384, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + prf_provider: &PrfUsingHmac(hmac::SHA384), + aead_alg: &Aes256Gcm, +}; + +#[cfg(feature = "chacha20poly1305")] +pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + prf_provider: &PrfUsingHmac(hmac::SHA256), + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + aead_alg: &ChaCha20Poly1305, +}; pub const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + #[cfg(feature = "aes-gcm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), + #[cfg(feature = "aes-gcm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + #[cfg(feature = "chacha20poly1305")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), ]; diff --git a/src/tls12/suites/rsa.rs b/src/tls12/suites/rsa.rs index b1c6997..364b48e 100644 --- a/src/tls12/suites/rsa.rs +++ b/src/tls12/suites/rsa.rs @@ -1,51 +1,65 @@ -use crate::aead::{Aes128Gcm, Aes256Gcm, ChaCha20Poly1305}; +use rustls::SupportedCipherSuite; + +#[cfg(feature = "aead")] use crate::{hash, hmac}; +#[cfg(feature = "aead")] use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorithm}; -use rustls::{CipherSuite, SupportedCipherSuite, Tls12CipherSuite}; - -use super::schemes::TLS12_RSA_SCHEMES; - -pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - aead_alg: &Aes128Gcm, - prf_provider: &PrfUsingHmac(hmac::SHA256), - }); - -pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - hash_provider: hash::SHA384, - confidentiality_limit: u64::MAX, - }, - kx: KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - prf_provider: &PrfUsingHmac(hmac::SHA384), - aead_alg: &Aes256Gcm, - }); - -pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = - SupportedCipherSuite::Tls12(&Tls12CipherSuite { - common: CipherSuiteCommon { - suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - hash_provider: hash::SHA256, - confidentiality_limit: u64::MAX, - }, - kx: KeyExchangeAlgorithm::ECDHE, - sign: &TLS12_RSA_SCHEMES, - prf_provider: &PrfUsingHmac(hmac::SHA256), - aead_alg: &ChaCha20Poly1305, - }); +#[cfg(feature = "aead")] +use rustls::{CipherSuite, Tls12CipherSuite}; + +#[cfg(feature = "aes-gcm")] +use crate::aead::{Aes128Gcm, Aes256Gcm}; + +#[cfg(feature = "chacha20poly1305")] +use crate::aead::ChaCha20Poly1305; + +#[cfg(feature = "aead")] +use crate::tls12::suites::schemes::TLS12_RSA_SCHEMES; + +#[cfg(feature = "aes-gcm")] +pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_RSA_SCHEMES, + aead_alg: &Aes128Gcm, + prf_provider: &PrfUsingHmac(hmac::SHA256), +}; + +#[cfg(feature = "aes-gcm")] +pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + hash_provider: hash::SHA384, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_RSA_SCHEMES, + prf_provider: &PrfUsingHmac(hmac::SHA384), + aead_alg: &Aes256Gcm, +}; + +#[cfg(feature = "chacha20poly1305")] +pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_RSA_SCHEMES, + prf_provider: &PrfUsingHmac(hmac::SHA256), + aead_alg: &ChaCha20Poly1305, +}; pub const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + #[cfg(feature = "aes-gcm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), + #[cfg(feature = "aes-gcm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), + #[cfg(feature = "chacha20poly1305")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), ]; diff --git a/src/tls12/suites/schemes.rs b/src/tls12/suites/schemes.rs index a850e3c..24c1705 100644 --- a/src/tls12/suites/schemes.rs +++ b/src/tls12/suites/schemes.rs @@ -1,16 +1,30 @@ +#[cfg(any(feature = "ecdsa", feature = "rsa"))] use rustls::SignatureScheme; -pub const TLS12_ECDSA_SCHEMES: [SignatureScheme; 4] = [ +#[cfg(feature = "ecdsa")] +pub const TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[ + #[cfg(feature = "p256")] SignatureScheme::ECDSA_NISTP256_SHA256, + #[cfg(feature = "p384")] SignatureScheme::ECDSA_NISTP384_SHA384, + #[cfg(feature = "p521")] SignatureScheme::ECDSA_NISTP521_SHA512, + #[cfg(feature = "ed25519")] SignatureScheme::ED25519, ]; -pub const TLS12_RSA_SCHEMES: [SignatureScheme; 6] = [ + +#[cfg(feature = "rsa")] +pub const TLS12_RSA_SCHEMES: &[SignatureScheme] = &[ + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA256, + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA384, + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA512, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA256, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA384, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA512, ]; diff --git a/src/tls13/aead.rs b/src/tls13/aead.rs index be14f13..eca37fa 100644 --- a/src/tls13/aead.rs +++ b/src/tls13/aead.rs @@ -1,2 +1,5 @@ +#[cfg(feature = "chacha20poly1305")] pub mod chacha20; + +#[cfg(feature = "aes-gcm")] pub mod gcm; diff --git a/src/tls13/suites.rs b/src/tls13/suites.rs index 299dfe2..1ace1b6 100644 --- a/src/tls13/suites.rs +++ b/src/tls13/suites.rs @@ -1,13 +1,35 @@ use crate::const_concat_slices; -use aes::TLS13_AES_SUITES; -use chacha20::TLS13_CHACHA20_POLY1305_SHA256; use rustls::SupportedCipherSuite; pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( SupportedCipherSuite, - TLS13_AES_SUITES, - &[TLS13_CHACHA20_POLY1305_SHA256] + { + #[cfg(feature = "aes-gcm")] + { + aes::TLS13_AES_SUITES + } + + #[cfg(not(feature = "aes-gcm"))] + { + &[] + } + }, + { + #[cfg(feature = "chacha20poly1305")] + { + &[chacha20::TLS13_CHACHA20_POLY1305_SHA256] + } + + #[cfg(not(feature = "chacha20poly1305"))] + { + &[] + } + }, + &[] ); +#[cfg(feature = "aes-gcm")] pub mod aes; + +#[cfg(feature = "chacha20poly1305")] pub mod chacha20; diff --git a/src/verify.rs b/src/verify.rs index 61c6d2d..4de3590 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,20 +1,17 @@ use core::array::TryFromSliceError; -use self::ecdsa::nist::{ - ECDSA_P256_SHA256, ECDSA_P256_SHA384, ECDSA_P384_SHA256, ECDSA_P384_SHA384, -}; -use self::eddsa::ed25519::ED25519; -use self::rsa::{ - RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384, - RSA_PSS_SHA512, -}; +use crate::const_concat_slices; + +use pki_types::SignatureVerificationAlgorithm; use rustls::crypto::WebPkiSupportedAlgorithms; use rustls::SignatureScheme; pub(crate) enum Error { Signature, TryFromSlice, + #[cfg(feature = "der")] Der, + #[cfg(feature = "pkcs1")] Pkcs1, } @@ -24,12 +21,14 @@ impl From for Error { } } +#[cfg(feature = "der")] impl From for Error { fn from(_: der::Error) -> Self { Self::Der } } +#[cfg(feature = "pkcs1")] impl From for Error { fn from(_: pkcs1::Error) -> Self { Self::Pkcs1 @@ -42,39 +41,173 @@ impl From for Error { } } -pub static ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { - all: &[ - ECDSA_P256_SHA256, - ECDSA_P256_SHA384, - ECDSA_P384_SHA256, - ECDSA_P384_SHA384, - ED25519, - RSA_PKCS1_SHA256, - RSA_PKCS1_SHA384, - RSA_PKCS1_SHA512, - RSA_PSS_SHA256, - RSA_PSS_SHA384, - RSA_PSS_SHA512, - ], - mapping: &[ - ( - SignatureScheme::ECDSA_NISTP384_SHA384, - &[ECDSA_P384_SHA384, ECDSA_P256_SHA384], - ), +pub const ALL: &'static [&'static dyn SignatureVerificationAlgorithm] = const_concat_slices!( + &'static dyn SignatureVerificationAlgorithm, + { + #[cfg(feature = "ecdsa")] + { + &[ + #[cfg(feature = "p256")] + ecdsa::nist::ECDSA_P256_SHA256, + #[cfg(feature = "p256")] + ecdsa::nist::ECDSA_P256_SHA384, + #[cfg(feature = "p384")] + ecdsa::nist::ECDSA_P384_SHA256, + #[cfg(feature = "p384")] + ecdsa::nist::ECDSA_P384_SHA384, + ] + } + + #[cfg(not(feature = "ecdsa"))] + { + &[] + } + }, + { + #[cfg(feature = "rsa-pkcs1")] + { + &[ + rsa::RSA_PKCS1_SHA256, + rsa::RSA_PKCS1_SHA384, + rsa::RSA_PKCS1_SHA512, + ] + } + + #[cfg(not(feature = "rsa-pkcs1"))] + { + &[] + } + }, + { + #[cfg(feature = "rsa-pss")] + { + &[ + rsa::RSA_PSS_SHA256, + rsa::RSA_PSS_SHA384, + rsa::RSA_PSS_SHA512, + ] + } + + #[cfg(not(feature = "rsa-pss"))] + { + &[] + } + }, +); + +pub const MAPPING: &'static [( + SignatureScheme, + &'static [&'static dyn SignatureVerificationAlgorithm], +)] = const_concat_slices!( + ( + SignatureScheme, + &'static [&'static dyn SignatureVerificationAlgorithm], + ), + { + #[cfg(feature = "ecdsa")] + { + &[ + #[cfg(feature = "p384")] + ( + SignatureScheme::ECDSA_NISTP384_SHA384, + &[ + ecdsa::nist::ECDSA_P384_SHA384, + #[cfg(feature = "p256")] + ecdsa::nist::ECDSA_P256_SHA384, + ], + ), + ( + #[cfg(feature = "p256")] + SignatureScheme::ECDSA_NISTP256_SHA256, + &[ + ecdsa::nist::ECDSA_P256_SHA256, + #[cfg(feature = "p384")] + ecdsa::nist::ECDSA_P384_SHA256, + ], + ), + ] + } + + #[cfg(not(feature = "ecdsa"))] + { + &[] + } + }, + { + #[cfg(feature = "rsa-pkcs1")] + { + &[ + (SignatureScheme::RSA_PKCS1_SHA256, &[rsa::RSA_PKCS1_SHA256]), + (SignatureScheme::RSA_PKCS1_SHA384, &[rsa::RSA_PKCS1_SHA384]), + (SignatureScheme::RSA_PKCS1_SHA512, &[rsa::RSA_PKCS1_SHA512]), + ] + } + + #[cfg(not(feature = "rsa-pkcs1"))] + { + &[] + } + }, + { + #[cfg(feature = "rsa-pss")] + { + &[ + (SignatureScheme::RSA_PSS_SHA256, &[rsa::RSA_PSS_SHA256]), + (SignatureScheme::RSA_PSS_SHA384, &[rsa::RSA_PSS_SHA384]), + (SignatureScheme::RSA_PSS_SHA512, &[rsa::RSA_PSS_SHA512]), + ] + } + + #[cfg(not(feature = "rsa-pss"))] + { + &[] + } + }, +); + +pub const ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { + all: const_concat_slices!(&'static dyn SignatureVerificationAlgorithm, ALL, { + #[cfg(feature = "eddsa")] + { + &[ + #[cfg(feature = "ed25519")] + eddsa::ed25519::ED25519, + ] + } + + #[cfg(not(feature = "eddsa"))] + { + &[] + } + }), + mapping: const_concat_slices!( ( - SignatureScheme::ECDSA_NISTP256_SHA256, - &[ECDSA_P256_SHA256, ECDSA_P384_SHA256], + SignatureScheme, + &'static [&'static dyn SignatureVerificationAlgorithm], ), - (SignatureScheme::ED25519, &[ED25519]), - (SignatureScheme::RSA_PKCS1_SHA256, &[RSA_PKCS1_SHA256]), - (SignatureScheme::RSA_PKCS1_SHA384, &[RSA_PKCS1_SHA384]), - (SignatureScheme::RSA_PKCS1_SHA512, &[RSA_PKCS1_SHA512]), - (SignatureScheme::RSA_PSS_SHA256, &[RSA_PSS_SHA256]), - (SignatureScheme::RSA_PSS_SHA384, &[RSA_PSS_SHA384]), - (SignatureScheme::RSA_PSS_SHA512, &[RSA_PSS_SHA512]), - ], + MAPPING, + { + #[cfg(feature = "eddsa")] + { + &[ + #[cfg(feature = "ed25519")] + (SignatureScheme::ED25519, &[eddsa::ed25519::ED25519]), + ] + } + + #[cfg(not(feature = "eddsa"))] + { + &[] + } + }, + ), }; +#[cfg(feature = "ecdsa")] pub mod ecdsa; + +#[cfg(feature = "eddsa")] pub mod eddsa; + +#[cfg(feature = "rsa")] pub mod rsa; diff --git a/src/verify/ecdsa.rs b/src/verify/ecdsa.rs index a6db7e6..9e8a797 100644 --- a/src/verify/ecdsa.rs +++ b/src/verify/ecdsa.rs @@ -1 +1,2 @@ +#[cfg(feature = "nist")] pub mod nist; diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs index 7155990..8caca5f 100644 --- a/src/verify/ecdsa/nist.rs +++ b/src/verify/ecdsa/nist.rs @@ -1,4 +1,3 @@ -use der::Decode; use digest::Digest; use paste::paste; use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; @@ -21,6 +20,8 @@ macro_rules! impl_generic_ecdsa_verifer { impl [] { fn verify_inner(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result<(), crate::verify::Error> { + use der::Decode; + let signature = <$signature>::from_der(signature)?; let verifying_key = <$verifying_key>::from_sec1_bytes(public_key)?; let digest = &<$hash>::digest(&message); @@ -53,7 +54,11 @@ macro_rules! impl_generic_ecdsa_verifer { }; } +#[cfg(all(feature = "ecdsa", feature = "p256"))] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha256} +#[cfg(all(feature = "ecdsa", feature = "p256"))] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha384} +#[cfg(all(feature = "ecdsa", feature = "p384"))] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha256} +#[cfg(all(feature = "ecdsa", feature = "p384"))] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha384} diff --git a/src/verify/rsa.rs b/src/verify/rsa.rs index 1b46362..6cb265a 100644 --- a/src/verify/rsa.rs +++ b/src/verify/rsa.rs @@ -1,7 +1,5 @@ use paste::paste; use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use rsa::pkcs1::DecodeRsaPublicKey; -use rsa::{pkcs1v15, pss, RsaPublicKey}; use sha2::{Sha256, Sha384, Sha512}; use signature::Verifier; use webpki::alg_id; @@ -25,6 +23,9 @@ macro_rules! impl_generic_rsa_verifer { message: &[u8], signature: &[u8], ) -> Result<(), crate::verify::Error> { + use rsa::RsaPublicKey; + use rsa::pkcs1::DecodeRsaPublicKey; + let public_key = RsaPublicKey::from_pkcs1_der(public_key)?; let signature = <$signature>::try_from(signature)?; <$verifying_key>::new(public_key).verify(message, &signature)?; @@ -56,46 +57,54 @@ macro_rules! impl_generic_rsa_verifer { }; } +#[cfg(feature = "rsa-pkcs1")] impl_generic_rsa_verifer!( RSA_PKCS1_SHA256, alg_id::RSA_ENCRYPTION, alg_id::RSA_PKCS1_SHA256, - pkcs1v15::VerifyingKey, - pkcs1v15::Signature + ::rsa::pkcs1v15::VerifyingKey, + ::rsa::pkcs1v15::Signature ); + +#[cfg(feature = "rsa-pkcs1")] impl_generic_rsa_verifer!( RSA_PKCS1_SHA384, alg_id::RSA_ENCRYPTION, alg_id::RSA_PKCS1_SHA384, - pkcs1v15::VerifyingKey, - pkcs1v15::Signature + ::rsa::pkcs1v15::VerifyingKey, + ::rsa::pkcs1v15::Signature ); + +#[cfg(feature = "rsa-pkcs1")] impl_generic_rsa_verifer!( RSA_PKCS1_SHA512, alg_id::RSA_ENCRYPTION, alg_id::RSA_PKCS1_SHA512, - pkcs1v15::VerifyingKey, - pkcs1v15::Signature + ::rsa::pkcs1v15::VerifyingKey, + ::rsa::pkcs1v15::Signature ); +#[cfg(feature = "rsa-pss")] impl_generic_rsa_verifer!( RSA_PSS_SHA256, alg_id::RSA_ENCRYPTION, alg_id::RSA_PSS_SHA256, - pss::VerifyingKey, - pss::Signature + ::rsa::pss::VerifyingKey, + ::rsa::pss::Signature ); +#[cfg(feature = "rsa-pss")] impl_generic_rsa_verifer!( RSA_PSS_SHA384, alg_id::RSA_ENCRYPTION, alg_id::RSA_PSS_SHA384, - pss::VerifyingKey, - pss::Signature + ::rsa::pss::VerifyingKey, + ::rsa::pss::Signature ); +#[cfg(feature = "rsa-pss")] impl_generic_rsa_verifer!( RSA_PSS_SHA512, alg_id::RSA_ENCRYPTION, alg_id::RSA_PSS_SHA512, - pss::VerifyingKey, - pss::Signature + ::rsa::pss::VerifyingKey, + ::rsa::pss::Signature ); From 01323664e5c77f6575bb78a188c77fd9b95d16bd Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:17:59 +0800 Subject: [PATCH 05/38] remove useless code --- examples-external/client.rs | 47 - examples-external/server.rs | 126 --- examples-xsmall/.cargo/config.toml | 3 - examples-xsmall/Cargo.lock | 1597 ---------------------------- examples-xsmall/Cargo.toml | 30 - examples-xsmall/README.md | 3 - examples-xsmall/examples/client.rs | 97 -- examples-xsmall/examples/server.rs | 97 -- src/lib.rs | 5 - tests-external/badssl.rs | 53 - tests-external/client.rs | 37 - tests-external/generic.rs | 30 - 12 files changed, 2125 deletions(-) delete mode 100644 examples-external/client.rs delete mode 100644 examples-external/server.rs delete mode 100644 examples-xsmall/.cargo/config.toml delete mode 100644 examples-xsmall/Cargo.lock delete mode 100644 examples-xsmall/Cargo.toml delete mode 100644 examples-xsmall/README.md delete mode 100644 examples-xsmall/examples/client.rs delete mode 100644 examples-xsmall/examples/server.rs delete mode 100644 tests-external/badssl.rs delete mode 100644 tests-external/client.rs delete mode 100644 tests-external/generic.rs diff --git a/examples-external/client.rs b/examples-external/client.rs deleted file mode 100644 index 2493c61..0000000 --- a/examples-external/client.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::str::FromStr; - -use anyhow::anyhow; -use http_body_util::{BodyExt, Empty}; -use hyper::{body::Bytes, Uri}; -use hyper_util::{client::legacy::Client, rt::TokioExecutor}; -use rustls_rustcrypto::provider; - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - env_logger::init(); - - // Prepare the HTTPS connector - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_webpki_roots(provider())? - .https_or_http() - .enable_all_versions() - .build(); - - // Build the hyper client from the HTTPS connector. - let client: Client<_, Empty> = Client::builder(TokioExecutor::new()).build(https); - - // Prepare a chain of futures which sends a GET request, inspects - // the returned headers, collects the whole body and prints it to - // stdout. - let fut = async move { - let res = client - .get(Uri::from_str("https://ecc256.badssl.com/")?) - .await - .map_err(|e| anyhow!("Could not get: {:?}", e))?; - println!("Status:\n{}", res.status()); - println!("Headers:\n{:#?}", res.headers()); - - let body = res - .into_body() - .collect() - .await - .map_err(|e| anyhow!("Could not get body: {:?}", e))? - .to_bytes(); - - println!("Body:\n{}", String::from_utf8_lossy(&body)); - - Ok(()) - }; - - fut.await -} diff --git a/examples-external/server.rs b/examples-external/server.rs deleted file mode 100644 index d31745b..0000000 --- a/examples-external/server.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::{net::ToSocketAddrs, sync::Arc}; - -use futures_util::StreamExt; -use http_body_util::{BodyExt, Full}; -use hyper::{ - body::{Bytes, Incoming}, - service::service_fn, - Method, Request, Response, StatusCode, -}; -use hyper_util::{ - rt::{TokioExecutor, TokioIo}, - server::conn::auto::Builder, -}; -use pki_types::PrivateKeyDer; -use rustls::ServerConfig; -use rustls_rustcrypto::provider; -use tls_listener::{SpawningHandshakes, TlsListener}; -use tokio::{net::TcpListener, signal::ctrl_c}; -use tokio_rustls::TlsAcceptor; -struct TestPki { - server_cert_der: Vec, - server_key_der: Vec, -} - -impl TestPki { - fn new() -> Self { - let alg = &rcgen::PKCS_ECDSA_P384_SHA384; - let mut ca_params = rcgen::CertificateParams::new(Vec::new()); - ca_params - .distinguished_name - .push(rcgen::DnType::OrganizationName, "Rustls Server Acceptor"); - ca_params - .distinguished_name - .push(rcgen::DnType::CommonName, "Example CA"); - ca_params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - ca_params.key_usages = vec![ - rcgen::KeyUsagePurpose::KeyCertSign, - rcgen::KeyUsagePurpose::DigitalSignature, - rcgen::KeyUsagePurpose::CrlSign, - ]; - ca_params.alg = alg; - let ca_cert = rcgen::Certificate::from_params(ca_params).unwrap(); - - // Create a server end entity cert issued by the CA. - let mut server_ee_params = rcgen::CertificateParams::new(vec!["localhost".to_string()]); - server_ee_params.is_ca = rcgen::IsCa::NoCa; - server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth]; - server_ee_params.alg = alg; - let server_cert = rcgen::Certificate::from_params(server_ee_params).unwrap(); - let server_cert_der = server_cert.serialize_der_with_signer(&ca_cert).unwrap(); - let server_key_der = server_cert.serialize_private_key_der(); - Self { - server_cert_der, - server_key_der, - } - } -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - env_logger::init(); - - let pki = TestPki::new(); - let addr = "0.0.0.0:4443" - .to_socket_addrs()? - .next() - .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::AddrNotAvailable))?; - - let incoming = TcpListener::bind(&addr).await?; - - let mut server_config = ServerConfig::builder_with_provider(Arc::new(provider())) - .with_safe_default_protocol_versions()? - .with_no_client_auth() - .with_single_cert( - vec![pki.server_cert_der.clone().into()], - PrivateKeyDer::Pkcs8(pki.server_key_der.clone().into()), - )?; - server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; - let tls_acceptor = TlsAcceptor::from(Arc::new(server_config)); - let service = service_fn(echo); - - println!("Starting to serve on https://{}.", addr); - - TlsListener::new(SpawningHandshakes(tls_acceptor), incoming) - .take_until(ctrl_c()) - .for_each_concurrent(None, |s| async { - match s { - Ok((stream, remote_addr)) => { - println!("accepted client from {}", remote_addr); - if let Err(err) = Builder::new(TokioExecutor::new()) - .serve_connection(TokioIo::new(stream), service) - .await - { - eprintln!("failed to serve connection: {err:#}"); - } - } - Err(e) => { - eprintln!("failed to perform tls handshake: {:?}", e); - } - } - }) - .await; - - Ok(()) -} - -// Custom echo service, handling two different routes and a -// catch-all 404 responder. -async fn echo(req: Request) -> Result>, hyper::Error> { - let mut response = Response::new(Full::default()); - match (req.method(), req.uri().path()) { - // Help route. - (&Method::GET, "/") => { - *response.body_mut() = Full::from("Try POST /echo\n"); - } - // Echo service route. - (&Method::POST, "/echo") => { - *response.body_mut() = Full::from(req.into_body().collect().await?.to_bytes()); - } - // Catch-all 404. - _ => { - *response.status_mut() = StatusCode::NOT_FOUND; - } - }; - Ok(response) -} diff --git a/examples-xsmall/.cargo/config.toml b/examples-xsmall/.cargo/config.toml deleted file mode 100644 index 9203efd..0000000 --- a/examples-xsmall/.cargo/config.toml +++ /dev/null @@ -1,3 +0,0 @@ -[unstable] -build-std = ["core", "alloc", "std", "compiler_builtins"] -build-std-features = ["compiler-builtins-mem"] diff --git a/examples-xsmall/Cargo.lock b/examples-xsmall/Cargo.lock deleted file mode 100644 index 331859c..0000000 --- a/examples-xsmall/Cargo.lock +++ /dev/null @@ -1,1597 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "ccm" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" -dependencies = [ - "aead", - "cipher", - "ctr", - "subtle", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "const-oid" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" - -[[package]] -name = "constcat" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f272d0c4cf831b4fa80ee529c7707f76585986e910e1fbce1d7921970bc1a241" - -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-bigint" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740fe28e594155f10cfc383984cbefd529d7396050557148f79cb0f621204124" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core", - "typenum", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622178105f911d937a42cdb140730ba4a3ed2becd8ae6ce39c7d28b5d75d4588" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "platforms", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fdaf97f4804dcebfa5862639bc9ce4121e82140bec2a987ac5140294865b5b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "der" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "const-oid", - "crypto-common", - "subtle", -] - -[[package]] -name = "ecdsa" -version = "0.16.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60f6d271ca33075c88028be6f04d502853d63a5ece419d269c15315d4fc1cf1d" -dependencies = [ - "pkcs8", - "signature", -] - -[[package]] -name = "ed25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" -dependencies = [ - "curve25519-dalek", - "ed25519", - "serde", - "sha2", - "zeroize", -] - -[[package]] -name = "elliptic-curve" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "examples-xsmall" -version = "0.1.0" -dependencies = [ - "anyhow", - "hyper", - "hyper-rustls", - "rcgen", - "rustls", - "rustls-pki-types", - "rustls-provider-rustcrypto", - "tokio", - "vc-ltl", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0870c84016d4b481be5c9f323c24f65e31e901ae618f0e80f4308fb00de1d2d" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "ghash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.25.0-alpha.1" -source = "git+https://github.com/stevefan1999-personal/hyper-rustls#f0bb1651fc010d9e993687006d92b10dcdd99c2d" -dependencies = [ - "futures-util", - "http", - "hyper", - "log", - "rustls", - "rustls-native-certs", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "webpki-roots", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin 0.5.2", -] - -[[package]] -name = "libc" -version = "0.2.148" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" - -[[package]] -name = "libm" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memchr" -version = "2.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "num-bigint-dig" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" -dependencies = [ - "byteorder", - "lazy_static", - "libm", - "num-integer", - "num-iter", - "num-traits", - "rand", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p384" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - -[[package]] -name = "p521" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2808cdb09072e3b966f5da8280cd29b252988afb898f688074d8dd1d26c0db" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pem" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" -dependencies = [ - "base64", - "serde", -] - -[[package]] -name = "pem-rfc7468" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" -dependencies = [ - "base64ct", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs1" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" -dependencies = [ - "der", - "pkcs8", - "spki", -] - -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "pkcs5", - "spki", -] - -[[package]] -name = "platforms" -version = "3.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8" - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primeorder" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2fcef82c0ec6eefcc179b978446c399b3cdf73c392c35604e399eee6df1ee3" -dependencies = [ - "elliptic-curve", -] - -[[package]] -name = "proc-macro2" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rcgen" -version = "0.11.3" -source = "git+https://github.com/rustls/rcgen#0318d2f0a4bb9e65c84d284acff8587bd418d837" -dependencies = [ - "pem", - "ring", - "time", - "yasna", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "ring" -version = "0.17.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin 0.9.8", - "untrusted", - "windows-sys", -] - -[[package]] -name = "rsa" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" -dependencies = [ - "byteorder", - "const-oid", - "digest", - "num-bigint-dig", - "num-integer", - "num-iter", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core", - "sha2", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustls" -version = "0.22.0-alpha.4" -source = "git+https://github.com/rustls/rustls#b7a6091ab458467a554d62a57c4ff9cf48a552af" -dependencies = [ - "log", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26f84fefc2b087ffd1677ed5910ec4b2650b1eb45ed083d38630304f48496b69" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.0.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aaa4fe93b39faddb6a8f99568c3e5880680156da0d46818e884a071381f67fe" -dependencies = [ - "base64", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47003264dea418db67060fa420ad16d0d2f8f0a0360d825c00e177ac52cb5d8" - -[[package]] -name = "rustls-provider-rustcrypto" -version = "0.0.2" -dependencies = [ - "aead", - "aes-gcm", - "block-buffer", - "ccm", - "chacha20poly1305", - "constcat", - "crypto-common", - "der", - "digest", - "ecdsa", - "ed25519-dalek", - "elliptic-curve", - "generic-array", - "hmac", - "p256", - "p384", - "p521", - "paste", - "pkcs8", - "rand_core", - "rsa", - "rustls", - "rustls-pki-types", - "rustls-webpki", - "sec1", - "sha2", - "signature", - "subtle", - "typenum", - "x25519-dalek", -] - -[[package]] -name = "rustls-webpki" -version = "0.102.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d9ed3a8267782ba32d257ff5b197b63eef19a467dbd1be011caaae35ee416e" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "sec1" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" - -[[package]] -name = "serde" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.188" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "sha2" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "signature" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" -dependencies = [ - "digest", - "rand_core", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" -dependencies = [ - "libc", - "windows-sys", -] - -[[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.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "syn" -version = "2.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "time" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" -dependencies = [ - "deranged", - "serde", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "tokio" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "pin-project-lite", - "socket2 0.5.4", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-rustls" -version = "0.25.0-alpha.2" -source = "git+https://github.com/rustls/tokio-rustls#82d32c410f2364332c5df656717193f278769e1c" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "vc-ltl" -version = "5.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e98ae3481f41a314867586b0bfbd20eabf5b196a420b1750a69d1a37b80d25" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "webpki-roots" -version = "0.26.0-alpha.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42157929d7ca9c353222a4d1763c52ef86d25d0fd2eca66076df5975fd4e25ed" -dependencies = [ - "rustls-pki-types", -] - -[[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.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "x25519-dalek" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" -dependencies = [ - "curve25519-dalek", - "rand_core", - "serde", - "zeroize", -] - -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/examples-xsmall/Cargo.toml b/examples-xsmall/Cargo.toml deleted file mode 100644 index eaaa4f1..0000000 --- a/examples-xsmall/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "examples-xsmall" -version = "0.1.0" -edition = "2021" - -[dev-dependencies] -anyhow = "1.0.75" -hyper = "0.14.27" -hyper-rustls = { version = "=0.25.0-alpha.1", features = ["http2", "webpki-roots"] } -pki-types = { package = "rustls-pki-types", version = "0.2.1", default-features = false } -rcgen = "0.11.1" -rustls = { version = "=0.22.0-alpha.4", default-features = false } -rustls-provider-rustcrypto = { path = "../" } -tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros", "io-std", "io-util", "net"] } -vc-ltl = "5.0.8" - -[features] -tls12 = ["rustls-provider-rustcrypto/tls12"] - -[profile.release] -strip = true -opt-level = "s" -lto = true -codegen-units = 1 - -[patch.crates-io] -rustls = { git = 'https://github.com/rustls/rustls' } -tokio-rustls = { git = 'https://github.com/rustls/tokio-rustls' } -hyper-rustls = { git = "https://github.com/stevefan1999-personal/hyper-rustls" } -rcgen = { git = "https://github.com/rustls/rcgen" } \ No newline at end of file diff --git a/examples-xsmall/README.md b/examples-xsmall/README.md deleted file mode 100644 index 8704344..0000000 --- a/examples-xsmall/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# examples-xsmall - -This is identical to the examples one level above, except it is using some Rust techniques known to man to generate small binaries as a mean to test the compactness of RustTLS \ No newline at end of file diff --git a/examples-xsmall/examples/client.rs b/examples-xsmall/examples/client.rs deleted file mode 100644 index d396acd..0000000 --- a/examples-xsmall/examples/client.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::str::FromStr; - -use anyhow::anyhow; -use hyper::{body::to_bytes, client, Body, Uri}; -use pki_types::CertificateDer; -use rustls::{ - client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, - DigitallySignedStruct, ServerName, SignatureScheme, -}; -use rustls_provider_rustcrypto::Provider; - -#[derive(Debug)] -struct NoopServerVerifier; - -impl ServerCertVerifier for NoopServerVerifier { - fn verify_server_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _server_name: &ServerName, - _ocsp_response: &[u8], - _now: pki_types::UnixTime, - ) -> Result { - Ok(ServerCertVerified::assertion()) - } - - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - ] - } -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - // Prepare the HTTPS connector - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_webpki_roots(&Provider) - .https_or_http() - .enable_all_versions() - .build(); - - // Build the hyper client from the HTTPS connector. - let client: client::Client<_, hyper::Body> = client::Client::builder().build(https); - - // Prepare a chain of futures which sends a GET request, inspects - // the returned headers, collects the whole body and prints it to - // stdout. - let fut = async move { - let res = client - .get(Uri::from_str("https://ecc256.badssl.com/")?) - .await - .map_err(|e| anyhow!("Could not get: {:?}", e))?; - println!("Status:\n{}", res.status()); - println!("Headers:\n{:#?}", res.headers()); - - let body: Body = res.into_body(); - let body = to_bytes(body) - .await - .map_err(|e| anyhow!("Could not get body: {:?}", e))?; - println!("Body:\n{}", String::from_utf8_lossy(&body)); - - Ok(()) - }; - - fut.await -} diff --git a/examples-xsmall/examples/server.rs b/examples-xsmall/examples/server.rs deleted file mode 100644 index 93c504f..0000000 --- a/examples-xsmall/examples/server.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::{ - io::{self}, - net::ToSocketAddrs, -}; - -use hyper::{ - server::conn::AddrIncoming, - service::{make_service_fn, service_fn}, - Body, Method, Request, Response, Server, StatusCode, -}; -use hyper_rustls::TlsAcceptor; -use pki_types::PrivateKeyDer; -use rustls_provider_rustcrypto::Provider; -struct TestPki { - server_cert_der: Vec, - server_key_der: Vec, -} - -impl TestPki { - fn new() -> Self { - let alg = &rcgen::PKCS_ECDSA_P256_SHA256; - let mut ca_params = rcgen::CertificateParams::new(Vec::new()); - ca_params - .distinguished_name - .push(rcgen::DnType::OrganizationName, "Rustls Server Acceptor"); - ca_params - .distinguished_name - .push(rcgen::DnType::CommonName, "Example CA"); - ca_params.is_ca = rcgen::IsCa::Ca(rcgen::BasicConstraints::Unconstrained); - ca_params.key_usages = vec![ - rcgen::KeyUsagePurpose::KeyCertSign, - rcgen::KeyUsagePurpose::DigitalSignature, - rcgen::KeyUsagePurpose::CrlSign, - ]; - ca_params.alg = alg; - let ca_cert = rcgen::Certificate::from_params(ca_params).unwrap(); - - // Create a server end entity cert issued by the CA. - let mut server_ee_params = rcgen::CertificateParams::new(vec!["localhost".to_string()]); - server_ee_params.is_ca = rcgen::IsCa::NoCa; - server_ee_params.extended_key_usages = vec![rcgen::ExtendedKeyUsagePurpose::ServerAuth]; - server_ee_params.alg = alg; - let server_cert = rcgen::Certificate::from_params(server_ee_params).unwrap(); - let server_cert_der = server_cert.serialize_der_with_signer(&ca_cert).unwrap(); - let server_key_der = server_cert.serialize_private_key_der(); - Self { - server_cert_der, - server_key_der, - } - } -} - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let pki = TestPki::new(); - let addr = "0.0.0.0:4443" - .to_socket_addrs()? - .next() - .ok_or_else(|| std::io::Error::from(std::io::ErrorKind::AddrNotAvailable))?; - let incoming = AddrIncoming::bind(&addr)?; - let acceptor = TlsAcceptor::builder() - .with_provider_and_single_cert( - &Provider, - vec![pki.server_cert_der.clone().into()], - PrivateKeyDer::Pkcs8(pki.server_key_der.clone().into()), - )? - .with_all_versions_alpn() - .with_incoming(incoming); - let service = make_service_fn(|_| async { Ok::<_, io::Error>(service_fn(echo)) }); - let server = Server::builder(acceptor).serve(service); - - // Run the future, keep going until an error occurs. - println!("Starting to serve on https://{}.", addr); - server.await?; - Ok(()) -} - -// Custom echo service, handling two different routes and a -// catch-all 404 responder. -async fn echo(req: Request) -> Result, hyper::Error> { - let mut response = Response::new(Body::empty()); - match (req.method(), req.uri().path()) { - // Help route. - (&Method::GET, "/") => { - *response.body_mut() = Body::from("Try POST /echo\n"); - } - // Echo service route. - (&Method::POST, "/echo") => { - *response.body_mut() = req.into_body(); - } - // Catch-all 404. - _ => { - *response.status_mut() = StatusCode::NOT_FOUND; - } - }; - Ok(response) -} diff --git a/src/lib.rs b/src/lib.rs index 6be60ad..9187f00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,11 +27,6 @@ unused_lifetimes )] -//! # Usage -//! -//! See [`examples-xsmall`](https://github.com/RustCrypto/rustls-rustcrypto/tree/master/examples-xsmall) -//! for a usage example. - #[cfg(not(feature = "alloc"))] compile_error!("Rustls currently does not support alloc-less environments"); diff --git a/tests-external/badssl.rs b/tests-external/badssl.rs deleted file mode 100644 index 7da3a4d..0000000 --- a/tests-external/badssl.rs +++ /dev/null @@ -1,53 +0,0 @@ -use claim::{assert_err, assert_ok}; -use test_case::test_case; - -// For the available tests check out here: https://badssl.com/dashboard/ - -#[cfg(feature = "tls12")] -#[test_case("https://ecc256.badssl.com/", Ok(()); "test ECC256 verification")] -#[test_case("https://ecc384.badssl.com/", Ok(()); "test ECC384 verification")] -#[test_case("https://rsa2048.badssl.com/", Ok(()); "test RSA-2048 verification")] -#[test_case("https://rsa4096.badssl.com/", Ok(()); "test RSA-4096 verification")] -#[cfg_attr(TODO, test_case("https://rsa8192.badssl.com/", Err(()); "test RSA-8192 verification"))] -#[test_case("https://sha256.badssl.com/", Ok(()); "test SHA-256 hash")] -#[test_case("https://sha384.badssl.com/", Err(()); "test SHA-384 hash (but expired)")] -#[test_case("https://sha512.badssl.com/", Err(()); "test SHA-512 hash (but expired)")] -#[test_case("https://tls-v1-2.badssl.com/", Ok(()); "test general TLS1.2 verification")] -#[test_case("https://mozilla-intermediate.badssl.com/", Ok(()); "test Mozilla intermediate compatibility (TLS 1.2 only)")] -#[test_case("https://long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com/", Ok(()); "test long name with dashes")] -#[test_case("https://longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com/", Ok(()); "test long name")] -#[tokio::test] -async fn test_badssl_tls12(uri: &str, expected: Result<(), ()>) { - if expected.is_ok() { - assert_ok!(client::run_request(uri).await); - } else { - assert_err!(client::run_request(uri).await); - } -} - -#[test_case("https://hsts.badssl.com/", Ok(()); "test HSTS (TODO)")] -#[test_case("https://mozilla-intermediate.badssl.com/", Ok(()); "test Mozilla intermediate compatibility (TLS 1.3 preferred)")] -#[test_case("https://mozilla-modern.badssl.com/", Ok(()); "test Mozilla modern compatibility (TLS 1.3 required)")] -#[test_case("https://upgrade.badssl.com/", Ok(()); "test upgrade-insecure-requests")] -#[test_case("https://1000-sans.badssl.com/", Err(()); "test 1000-sans")] -#[test_case("https://10000-sans.badssl.com/", Err(()); "test 10000-sans")] -#[test_case("https://expired.badssl.com/", Err(()); "test expired")] -#[test_case("https://incomplete-chain.badssl.com/", Err(()); "test incomplete chain")] -#[test_case("https://no-common-name.badssl.com/", Err(()); "test no common name")] -#[test_case("https://no-subject.badssl.com/", Err(()); "test no subject")] -#[test_case("https://revoked.badssl.com/", Err(()); "test revoked")] -#[test_case("https://self-signed.badssl.com/", Err(()); "test self signed")] -#[test_case("https://untrusted-root.badssl.com/", Err(()); "test untrusted root")] -#[test_case("https://wrong.host.badssl.com/", Err(()); "test wrong host")] -#[test_case("https://no-sct.badssl.com/", Err(()); "test Signed Certificate Timestamp")] // NET::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED -#[cfg_attr(TODO, test_case("https://pinning-test.badssl.com/", Err(()); "test pinning test"))] // NET::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN -#[tokio::test] -async fn test_badssl(uri: &str, expected: Result<(), ()>) { - if expected.is_ok() { - assert_ok!(client::run_request(uri).await); - } else { - assert_err!(client::run_request(uri).await); - } -} - -mod client; diff --git a/tests-external/client.rs b/tests-external/client.rs deleted file mode 100644 index addae02..0000000 --- a/tests-external/client.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::str::FromStr; - -use http_body_util::{BodyExt, Empty}; -use hyper::{body::Bytes, Uri}; -use hyper_rustls::HttpsConnector; -use hyper_util::{ - client::legacy::{connect::HttpConnector, Client}, - rt::TokioExecutor, -}; -use rustls_rustcrypto::provider; - -pub fn build_hyper_client() -> anyhow::Result, Empty>> { - let https = hyper_rustls::HttpsConnectorBuilder::new() - .with_provider_and_webpki_roots(provider())? - .https_or_http() - .enable_all_versions() - .build(); - let client: Client<_, Empty> = Client::builder(TokioExecutor::new()).build(https); - - Ok(client) -} - -// I'm not sure how to exactly extract the hyper TLS error result to pinpoint -// what error it should match For now treating it as a grand result is alright -pub async fn run_request(uri: &str) -> anyhow::Result<()> { - let client = build_hyper_client()?; - let uri = Uri::from_str(uri)?; - let res = client.get(uri).await?; - - // We could definite check whether this is a HTML, but for now we don't really - // care about the body content - let bytes = res.into_body().collect().await?.to_bytes(); - - println!("{:?}", bytes); - - Ok(()) -} diff --git a/tests-external/generic.rs b/tests-external/generic.rs deleted file mode 100644 index 28f23da..0000000 --- a/tests-external/generic.rs +++ /dev/null @@ -1,30 +0,0 @@ -use claim::{assert_err, assert_ok}; -use test_case::test_case; - -// For the available tests check out here: https://badssl.com/dashboard/ - -#[test_case("https://codeforces.com/", Ok(()))] -#[test_case("https://crates.io/", Ok(()))] -#[test_case("https://doc.rust-lang.org/", Ok(()))] -#[test_case("https://github.com/", Ok(()))] -#[test_case("https://twitter.com/", Ok(()))] -#[test_case("https://wikipedia.org/", Ok(()))] -#[test_case("https://www.facebook.com/", Ok(()))] -#[test_case("https://www.google.com/", Ok(()))] -#[test_case("https://www.hackerrank.com/", Ok(()))] -#[test_case("https://www.instagram.com/", Ok(()))] -#[test_case("https://www.reddit.com/", Ok(()))] -#[test_case("https://stackoverflow.com/", Ok(()))] -#[test_case("https://www.youtube.com/", Ok(()))] -#[test_case("https://leetcode.com/", Ok(()))] -#[cfg_attr(feature = "tls12", test_case("https://www.topcoder.com/", Ok(())))] -#[tokio::test] -async fn test_generic_sites(uri: &str, expected: Result<(), ()>) { - if expected.is_ok() { - assert_ok!(client::run_request(uri).await); - } else { - assert_err!(client::run_request(uri).await); - } -} - -mod client; From cff0bff625c6ee3f41345367fad3e6b13812b90c Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:18:24 +0800 Subject: [PATCH 06/38] enhance feature selection --- Cargo.lock | 3 +++ Cargo.toml | 54 ++++++++++++++++++++++------------------ src/kx.rs | 4 +-- src/kx/nist.rs | 4 +-- src/verify.rs | 6 ++--- src/verify/ecdsa/nist.rs | 8 +++--- src/verify/eddsa.rs | 1 + 7 files changed, 45 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02fd241..41dd6ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -478,7 +478,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" dependencies = [ "base16ct", + "ecdsa", "elliptic-curve", + "primeorder", + "sha2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 50127fa..c4a28fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ aes-gcm = { version = "0.10.3", default-features = false, features = [ ], optional = true } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } -der = { version = "0.7.9", default-features = false, optional = true } +der = { version = "0.7.9", default-features = false } digest = { version = "0.10.7", default-features = false } ecdsa = { version = "0.16.9", default-features = false, optional = true } ed25519-dalek = { version = "2", default-features = false, optional = true } @@ -63,20 +63,14 @@ getrandom = { version = "0.2", features = [ [features] default = ["std", "tls12", "zeroize", "full"] full = [ - "aes-gcm", - "chacha20poly1305", - "ed25519", - "p256", - "p384", - "pem", - "pkcs1", - "pkcs8", - "rsa-pkcs1", - "rsa-pss", - "sec1", - "x25519", - "der", + "aead-full", + "ecdsa-full", + "eddsa-full", + "kx-full", + "rsa-full", + "format", ] +format = ["pem", "pkcs1", "pkcs8", "sec1", "der"] logging = ["rustls/logging"] tls12 = ["rustls/tls12"] @@ -92,17 +86,17 @@ std = [ "ed25519-dalek?/std", "pkcs1?/std", ] - alloc = ["webpki/alloc", "ecdsa?/alloc", "signature/alloc"] zeroize = ["ed25519-dalek?/zeroize", "x25519-dalek?/zeroize"] nist = [] -p256 = ["dep:p256", "nist", "kx", "ecdsa"] -p384 = ["dep:p384", "nist", "kx", "ecdsa"] -p521 = ["dep:p521", "nist", "kx", "ecdsa"] +p256 = ["dep:p256", "nist"] +p384 = ["dep:p384", "nist"] +p521 = ["dep:p521", "nist"] +ed25519 = ["dep:ed25519-dalek"] sec1 = ["dep:sec1"] -pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem"] +pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem", "p521?/pem"] pkcs1 = ["dep:pkcs1"] pkcs8 = [ @@ -111,22 +105,34 @@ pkcs8 = [ "sec1?/pkcs8", "p256?/pkcs8", "p384?/pkcs8", + "p521?/pkcs8", ] -ecdsa = ["dep:ecdsa", "p256?/ecdsa", "p384?/ecdsa"] +ecdsa = ["dep:ecdsa"] +ecdsa-p256 = ["p256", "p256/ecdsa", "ecdsa"] +ecdsa-p384 = ["p384", "p384/ecdsa", "ecdsa"] +ecdsa-p521 = ["p521", "p521/ecdsa", "ecdsa"] +ecdsa-full = ["ecdsa-p256", "ecdsa-p384", "ecdsa-p521"] eddsa = [] -ed25519 = ["dep:ed25519-dalek", "eddsa"] +eddsa-ed25519 = ["ed25519", "eddsa"] +eddsa-full = ["eddsa-ed25519"] -kx = ["p256?/ecdh", "p384?/ecdh"] -x25519 = ["dep:x25519-dalek", "kx"] +kx = [] +kx-x25519 = ["dep:x25519-dalek", "kx"] +kx-p256 = ["p256", "p256/ecdh", "kx"] +kx-p384 = ["p384", "p384/ecdh", "kx"] +kx-p521 = ["p521", "p521/ecdh", "kx"] +kx-full = ["kx-x25519", "kx-p256", "kx-p384", "kx-p521"] rsa = ["dep:rsa"] rsa-pkcs1 = ["rsa", "pkcs1"] rsa-pss = ["rsa"] +rsa-full = ["rsa-pkcs1", "rsa-pss"] aead = ["dep:aead"] aes-gcm = ["dep:aes-gcm", "aead"] chacha20poly1305 = ["dep:chacha20poly1305", "aead"] +aead-full = ["aes-gcm", "chacha20poly1305"] -der = ["dep:der"] +der = [] diff --git a/src/kx.rs b/src/kx.rs index a9bdd05..b616eb3 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -1,7 +1,7 @@ use rustls::crypto::SupportedKxGroup; pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ - #[cfg(feature = "x25519")] + #[cfg(feature = "kx-x25519")] &x25519::X25519, #[cfg(feature = "p256")] &nist::SecP256R1, @@ -12,5 +12,5 @@ pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ #[cfg(feature = "nist")] pub mod nist; -#[cfg(feature = "x25519")] +#[cfg(feature = "kx-x25519")] pub mod x25519; diff --git a/src/kx/nist.rs b/src/kx/nist.rs index c817b43..24bce77 100644 --- a/src/kx/nist.rs +++ b/src/kx/nist.rs @@ -60,8 +60,8 @@ macro_rules! impl_kx { }; } -#[cfg(feature = "p256")] +#[cfg(feature = "kx-p256")] impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, ::p256::ecdh::EphemeralSecret, ::p256::PublicKey} -#[cfg(feature = "p384")] +#[cfg(feature = "kx-p384")] impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, ::p384::ecdh::EphemeralSecret, ::p384::PublicKey} diff --git a/src/verify.rs b/src/verify.rs index 4de3590..6721480 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -41,7 +41,7 @@ impl From for Error { } } -pub const ALL: &'static [&'static dyn SignatureVerificationAlgorithm] = const_concat_slices!( +pub const ALL: &[&'static dyn SignatureVerificationAlgorithm] = const_concat_slices!( &'static dyn SignatureVerificationAlgorithm, { #[cfg(feature = "ecdsa")] @@ -95,9 +95,9 @@ pub const ALL: &'static [&'static dyn SignatureVerificationAlgorithm] = const_co }, ); -pub const MAPPING: &'static [( +pub const MAPPING: &[( SignatureScheme, - &'static [&'static dyn SignatureVerificationAlgorithm], + &[&'static dyn SignatureVerificationAlgorithm], )] = const_concat_slices!( ( SignatureScheme, diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs index 8caca5f..fa9c2fe 100644 --- a/src/verify/ecdsa/nist.rs +++ b/src/verify/ecdsa/nist.rs @@ -54,11 +54,11 @@ macro_rules! impl_generic_ecdsa_verifer { }; } -#[cfg(all(feature = "ecdsa", feature = "p256"))] +#[cfg(feature = "p256")] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha256} -#[cfg(all(feature = "ecdsa", feature = "p256"))] +#[cfg(feature = "p256")] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha384} -#[cfg(all(feature = "ecdsa", feature = "p384"))] +#[cfg(feature = "p384")] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha256} -#[cfg(all(feature = "ecdsa", feature = "p384"))] +#[cfg(feature = "p384")] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha384} diff --git a/src/verify/eddsa.rs b/src/verify/eddsa.rs index 58845d3..5141d74 100644 --- a/src/verify/eddsa.rs +++ b/src/verify/eddsa.rs @@ -1 +1,2 @@ +#[cfg(feature = "ed25519")] pub mod ed25519; From 5f49b10d76f119f2379ea0634e99a5036361e4a0 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:39:09 +0800 Subject: [PATCH 07/38] fix references --- src/hash.rs | 19 +++++++++---------- src/hmac.rs | 30 +++++++++++++++--------------- src/sign/ecdsa/nist.rs | 6 ++---- src/sign/rsa.rs | 12 ++++++++++++ src/tls12/suites/ecdsa.rs | 5 ++--- src/tls12/suites/rsa.rs | 5 ++--- src/tls12/suites/schemes.rs | 8 ++++---- 7 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index c15a65e..c8b93ad 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -4,17 +4,16 @@ use alloc::boxed::Box; use digest::{Digest, OutputSizeUser}; use paste::paste; use rustls::crypto::{self, hash}; -use sha2::{Sha256, Sha384}; macro_rules! impl_hash { ($name:ident, $ty:ty, $algo:ty) => { paste! { #[allow(non_camel_case_types)] - pub struct []; + pub struct []; - impl hash::Hash for [] { + impl hash::Hash for [] { fn start(&self) -> Box { - Box::new([]($ty::new())) + Box::new([]($ty::new())) } fn hash(&self, data: &[u8]) -> hash::Output { @@ -31,15 +30,15 @@ macro_rules! impl_hash { } #[allow(non_camel_case_types)] - pub struct []($ty); + pub struct []($ty); - impl hash::Context for [] { + impl hash::Context for [] { fn fork_finish(&self) -> hash::Output { hash::Output::new(&self.0.clone().finalize()[..]) } fn fork(&self) -> Box { - Box::new([](self.0.clone())) + Box::new([](self.0.clone())) } fn finish(self: Box) -> hash::Output { @@ -51,12 +50,12 @@ macro_rules! impl_hash { } } - pub const $name: &dyn crypto::hash::Hash = &[]; + pub const $name: &dyn crypto::hash::Hash = &[]; } }; } // impl_hash! {SHA224, Sha224, hash::HashAlgorithm::SHA224} -impl_hash! {SHA256, Sha256, hash::HashAlgorithm::SHA256} -impl_hash! {SHA384, Sha384, hash::HashAlgorithm::SHA384} +impl_hash! {SHA256, ::sha2::Sha256, hash::HashAlgorithm::SHA256} +impl_hash! {SHA384, ::sha2::Sha384, hash::HashAlgorithm::SHA384} // impl_hash! {SHA512, Sha512, hash::HashAlgorithm::SHA512} diff --git a/src/hmac.rs b/src/hmac.rs index a99d81d..e7e671f 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -2,10 +2,8 @@ use alloc::boxed::Box; use crypto_common::OutputSizeUser; -use hmac::Mac; use paste::paste; -use rustls::crypto; -use sha2::{Sha256, Sha384}; +use rustls::crypto::hmac::{Hmac, Key, Tag}; macro_rules! impl_hmac { ( @@ -14,12 +12,13 @@ macro_rules! impl_hmac { ) => { paste! { #[allow(non_camel_case_types)] - pub struct []; + pub struct []; - impl crypto::hmac::Hmac for [] { - fn with_key(&self, key: &[u8]) -> Box { - Box::new([]( - hmac::Hmac::<$ty>::new_from_slice(key).unwrap(), + impl Hmac for [] { + fn with_key(&self, key: &[u8]) -> Box { + use ::hmac::Mac; + Box::new([]( + ::hmac::Hmac::<$ty>::new_from_slice(key).unwrap(), )) } @@ -29,28 +28,29 @@ macro_rules! impl_hmac { } #[allow(non_camel_case_types)] - pub struct [](hmac::Hmac<$ty>); + pub struct [](::hmac::Hmac<$ty>); - impl crypto::hmac::Key for [] { - fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> crypto::hmac::Tag { + impl Key for [] { + fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> Tag { + use ::hmac::Mac; let mut ctx = self.0.clone(); ctx.update(first); for m in middle { ctx.update(m); } ctx.update(last); - crypto::hmac::Tag::new(&ctx.finalize().into_bytes()[..]) + Tag::new(&ctx.finalize().into_bytes()[..]) } fn tag_len(&self) -> usize { $ty::output_size() } } - pub const $name: &dyn crypto::hmac::Hmac = &[]; + pub const $name: &dyn Hmac = &[]; } }; } -impl_hmac! {SHA256, Sha256} -impl_hmac! {SHA384, Sha384} +impl_hmac! {SHA256, ::sha2::Sha256} +impl_hmac! {SHA384, ::sha2::Sha384} // impl_hmac! {SHA512, Sha512} diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs index b647a3e..957df3f 100644 --- a/src/sign/ecdsa/nist.rs +++ b/src/sign/ecdsa/nist.rs @@ -1,10 +1,8 @@ +use crate::sign::GenericRandomizedSigner; #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, sync::Arc}; use core::marker::PhantomData; - -use crate::sign::GenericRandomizedSigner; use paste::paste; - #[cfg(feature = "der")] use pki_types::PrivateKeyDer; use rustls::sign::SigningKey; @@ -71,5 +69,5 @@ macro_rules! impl_ecdsa { #[cfg(feature = "p256")] impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, ::p256::ecdsa::SigningKey, ::p256::ecdsa::DerSignature} -#[cfg(feature = "p256")] +#[cfg(feature = "p384")] impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, ::p384::ecdsa::SigningKey, ::p384::ecdsa::DerSignature} diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index 459e084..336c67d 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -9,11 +9,17 @@ use rustls::{SignatureAlgorithm, SignatureScheme}; use sha2::{Sha256, Sha384, Sha512}; const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA512, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA384, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA256, + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA512, + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA384, + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA256, ]; @@ -63,15 +69,21 @@ impl SigningKey for RsaSigningKey { } match scheme { + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA512 => signer! {::rsa::pss::SigningKey::}, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA384 => signer! {::rsa::pss::SigningKey::}, + #[cfg(feature = "rsa-pss")] SignatureScheme::RSA_PSS_SHA256 => signer! {::rsa::pss::SigningKey::}, + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA512 => { signer! {::rsa::pkcs1v15::SigningKey::} } + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA384 => { signer! {::rsa::pkcs1v15::SigningKey::} } + #[cfg(feature = "rsa-pkcs1")] SignatureScheme::RSA_PKCS1_SHA256 => { signer! {::rsa::pkcs1v15::SigningKey::} } diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs index d5fc5d4..f0f874b 100644 --- a/src/tls12/suites/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -1,5 +1,7 @@ use rustls::SupportedCipherSuite; +#[cfg(feature = "aead")] +use crate::tls12::suites::schemes::TLS12_ECDSA_SCHEMES; #[cfg(feature = "aead")] use crate::{hash, hmac}; #[cfg(feature = "aead")] @@ -13,9 +15,6 @@ use crate::aead::{Aes128Gcm, Aes256Gcm}; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; -#[cfg(feature = "aead")] -use crate::tls12::suites::schemes::TLS12_ECDSA_SCHEMES; - #[cfg(feature = "aes-gcm")] pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { diff --git a/src/tls12/suites/rsa.rs b/src/tls12/suites/rsa.rs index 364b48e..d395dba 100644 --- a/src/tls12/suites/rsa.rs +++ b/src/tls12/suites/rsa.rs @@ -1,5 +1,7 @@ use rustls::SupportedCipherSuite; +#[cfg(feature = "aead")] +use crate::tls12::suites::schemes::TLS12_RSA_SCHEMES; #[cfg(feature = "aead")] use crate::{hash, hmac}; #[cfg(feature = "aead")] @@ -13,9 +15,6 @@ use crate::aead::{Aes128Gcm, Aes256Gcm}; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; -#[cfg(feature = "aead")] -use crate::tls12::suites::schemes::TLS12_RSA_SCHEMES; - #[cfg(feature = "aes-gcm")] pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { diff --git a/src/tls12/suites/schemes.rs b/src/tls12/suites/schemes.rs index 24c1705..2b3deb9 100644 --- a/src/tls12/suites/schemes.rs +++ b/src/tls12/suites/schemes.rs @@ -3,13 +3,13 @@ use rustls::SignatureScheme; #[cfg(feature = "ecdsa")] pub const TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[ - #[cfg(feature = "p256")] + #[cfg(feature = "ecdsa-p256")] SignatureScheme::ECDSA_NISTP256_SHA256, - #[cfg(feature = "p384")] + #[cfg(feature = "ecdsa-p384")] SignatureScheme::ECDSA_NISTP384_SHA384, - #[cfg(feature = "p521")] + #[cfg(feature = "ecdsa-p521")] SignatureScheme::ECDSA_NISTP521_SHA512, - #[cfg(feature = "ed25519")] + #[cfg(feature = "eddsa-ed25519")] SignatureScheme::ED25519, ]; From 66478deb4517c8e050c6f431dc074a07cf8af57a Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:39:22 +0800 Subject: [PATCH 08/38] spread der feature to various format --- Cargo.toml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c4a28fa..dfcdf49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,7 @@ full = [ "rsa-full", "format", ] -format = ["pem", "pkcs1", "pkcs8", "sec1", "der"] +format = ["pem", "pkcs1", "pkcs8", "sec1"] logging = ["rustls/logging"] tls12 = ["rustls/tls12"] @@ -95,10 +95,10 @@ p384 = ["dep:p384", "nist"] p521 = ["dep:p521", "nist"] ed25519 = ["dep:ed25519-dalek"] -sec1 = ["dep:sec1"] -pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem", "p521?/pem"] +sec1 = ["dep:sec1", "der"] +pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem", "p521?/pem", "der"] -pkcs1 = ["dep:pkcs1"] +pkcs1 = ["dep:pkcs1", "der"] pkcs8 = [ "dep:pkcs8", "ed25519-dalek?/pkcs8", @@ -106,6 +106,7 @@ pkcs8 = [ "p256?/pkcs8", "p384?/pkcs8", "p521?/pkcs8", + "der" ] ecdsa = ["dep:ecdsa"] From c952b8fbc0148a06630e63853cf291ada5de6912 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 28 Sep 2024 03:37:39 +0800 Subject: [PATCH 09/38] make sure more features are correctly separated --- Cargo.toml | 63 ++++++++++++++++++++++----------------- src/aead.rs | 5 ++++ src/kx.rs | 4 +-- src/kx/nist.rs | 8 ++++- src/lib.rs | 31 ++++++++++++++----- src/sign.rs | 60 ++++++++----------------------------- src/sign/ecdsa/nist.rs | 8 +++-- src/sign/eddsa/ed25519.rs | 4 ++- src/sign/rand.rs | 35 ++++++++++++++++++++++ src/sign/rsa.rs | 2 +- src/tls12.rs | 1 + src/tls12/aead/gcm.rs | 2 +- src/tls13.rs | 1 + src/verify.rs | 20 +++++++------ 14 files changed, 144 insertions(+), 100 deletions(-) create mode 100644 src/sign/rand.rs diff --git a/Cargo.toml b/Cargo.toml index dfcdf49..0f98cfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,13 +24,14 @@ aes-gcm = { version = "0.10.3", default-features = false, features = [ ], optional = true } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } -der = { version = "0.7.9", default-features = false } +der = { version = "0.7.9", default-features = false, optional = true } digest = { version = "0.10.7", default-features = false } ecdsa = { version = "0.16.9", default-features = false, optional = true } ed25519-dalek = { version = "2", default-features = false, optional = true } hmac = { version = "0.12.1", default-features = false } p256 = { version = "0.13.2", default-features = false, optional = true } p384 = { version = "0.13.0", default-features = false, optional = true } +p521 = { version = "0.13.3", default-features = false, optional = true } pkcs1 = { version = "0.7.5", default-features = false, optional = true } pkcs8 = { version = "0.10.2", default-features = false, features = [ "pkcs5", @@ -40,19 +41,16 @@ rsa = { version = "0.9.6", default-features = false, features = [ ], optional = true } sec1 = { version = "0.7.3", default-features = false, optional = true } sha2 = { version = "0.10.8", default-features = false } -signature = { version = "2.2.0", features = [ - "rand_core", -], default-features = false } +signature = { version = "2.2.0", default-features = false, optional = true } x25519-dalek = { version = "2", default-features = false, optional = true } paste = { version = "1.0.15", default-features = false } pki-types = { package = "rustls-pki-types", version = "1.8.0", default-features = false } rand_core = { version = "0.6.4", default-features = false, features = [ "getrandom", -] } +], optional = true } rustls = { version = "0.23.13", default-features = false } -webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false } -p521 = { version = "0.13.3", default-features = false, optional = true } +webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false, optional = true } [dev-dependencies] @@ -80,13 +78,13 @@ tls12 = ["rustls/tls12"] # TODO: go through all of these that what gets exposed re: std error type std = [ "alloc", - "webpki/std", + "webpki?/std", "pki-types/std", "rustls/std", "ed25519-dalek?/std", "pkcs1?/std", ] -alloc = ["webpki/alloc", "ecdsa?/alloc", "signature/alloc"] +alloc = ["webpki?/alloc", "ecdsa?/alloc", "signature?/alloc"] zeroize = ["ed25519-dalek?/zeroize", "x25519-dalek?/zeroize"] nist = [] @@ -95,38 +93,26 @@ p384 = ["dep:p384", "nist"] p521 = ["dep:p521", "nist"] ed25519 = ["dep:ed25519-dalek"] -sec1 = ["dep:sec1", "der"] -pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem", "p521?/pem", "der"] - -pkcs1 = ["dep:pkcs1", "der"] -pkcs8 = [ - "dep:pkcs8", - "ed25519-dalek?/pkcs8", - "sec1?/pkcs8", - "p256?/pkcs8", - "p384?/pkcs8", - "p521?/pkcs8", - "der" -] +verify = ["dep:webpki"] -ecdsa = ["dep:ecdsa"] +ecdsa = ["dep:ecdsa", "verify", "signature", "rand"] ecdsa-p256 = ["p256", "p256/ecdsa", "ecdsa"] ecdsa-p384 = ["p384", "p384/ecdsa", "ecdsa"] ecdsa-p521 = ["p521", "p521/ecdsa", "ecdsa"] ecdsa-full = ["ecdsa-p256", "ecdsa-p384", "ecdsa-p521"] -eddsa = [] +eddsa = ["verify", "signature"] eddsa-ed25519 = ["ed25519", "eddsa"] eddsa-full = ["eddsa-ed25519"] -kx = [] +kx = ["rand"] kx-x25519 = ["dep:x25519-dalek", "kx"] kx-p256 = ["p256", "p256/ecdh", "kx"] kx-p384 = ["p384", "p384/ecdh", "kx"] kx-p521 = ["p521", "p521/ecdh", "kx"] kx-full = ["kx-x25519", "kx-p256", "kx-p384", "kx-p521"] -rsa = ["dep:rsa"] +rsa = ["dep:rsa", "rsa/sha2"] rsa-pkcs1 = ["rsa", "pkcs1"] rsa-pss = ["rsa"] rsa-full = ["rsa-pkcs1", "rsa-pss"] @@ -136,4 +122,27 @@ aes-gcm = ["dep:aes-gcm", "aead"] chacha20poly1305 = ["dep:chacha20poly1305", "aead"] aead-full = ["aes-gcm", "chacha20poly1305"] -der = [] +# TODO +hash = [] +hash-sha256 = ["hash"] +hash-sha384 = ["hash"] +hash-sha512 = ["hash"] +hash-full = ["hash-sha256", "hash-sha384", "hash-sha512"] + +# Formats +der = ["dep:der"] +sec1 = ["dep:sec1", "der"] +pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem", "p521?/pem", "der"] +pkcs1 = ["dep:pkcs1", "der"] +pkcs8 = [ + "dep:pkcs8", + "ed25519-dalek?/pkcs8", + "sec1?/pkcs8", + "p256?/pkcs8", + "p384?/pkcs8", + "p521?/pkcs8", + "der", +] + +signature = ["dep:signature"] +rand = ["dep:rand_core", "signature?/rand_core"] diff --git a/src/aead.rs b/src/aead.rs index c2d96ab..0c8513c 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -1,10 +1,15 @@ use aead::Buffer; use rustls::crypto::cipher::{BorrowedPayload, PrefixedPayload}; +#[cfg(feature = "chacha20poly1305")] pub const CHACHAPOLY1305_OVERHEAD: usize = 16; +#[cfg(feature = "chacha20poly1305")] pub struct ChaCha20Poly1305; +#[cfg(feature = "aes-gcm")] pub struct Aes128Gcm; + +#[cfg(feature = "aes-gcm")] pub struct Aes256Gcm; pub(crate) struct EncryptBufferAdapter<'a>(pub(crate) &'a mut PrefixedPayload); diff --git a/src/kx.rs b/src/kx.rs index b616eb3..1075669 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -3,9 +3,9 @@ use rustls::crypto::SupportedKxGroup; pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ #[cfg(feature = "kx-x25519")] &x25519::X25519, - #[cfg(feature = "p256")] + #[cfg(feature = "kx-p256")] &nist::SecP256R1, - #[cfg(feature = "p384")] + #[cfg(feature = "kx-p384")] &nist::SecP384R1, ]; diff --git a/src/kx/nist.rs b/src/kx/nist.rs index 24bce77..a2c3ea4 100644 --- a/src/kx/nist.rs +++ b/src/kx/nist.rs @@ -1,10 +1,16 @@ -#[cfg(feature = "alloc")] +#[cfg(all(feature = "alloc", any(feature = "kx-p256", feature = "kx-p384")))] use alloc::boxed::Box; +#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] use crypto::{SharedSecret, SupportedKxGroup}; + +#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] use paste::paste; + +#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] use rustls::crypto; +#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] macro_rules! impl_kx { ($name:ident, $kx_name:ty, $secret:ty, $public_key:ty) => { paste! { diff --git a/src/lib.rs b/src/lib.rs index 9187f00..55d69a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,6 +36,7 @@ extern crate alloc; #[cfg(feature = "alloc")] use alloc::sync::Arc; +use pki_types::PrivateKeyDer; use rustls::crypto::{CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom}; use rustls::sign::SigningKey; use rustls::SupportedCipherSuite; @@ -54,20 +55,35 @@ pub fn provider() -> CryptoProvider { } impl SecureRandom for Provider { - fn fill(&self, bytes: &mut [u8]) -> Result<(), GetRandomFailed> { - use rand_core::RngCore; - rand_core::OsRng - .try_fill_bytes(bytes) - .map_err(|_| GetRandomFailed) + fn fill(&self, #[allow(unused_variables)] bytes: &mut [u8]) -> Result<(), GetRandomFailed> { + #[cfg(feature = "rand")] + { + use rand_core::RngCore; + rand_core::OsRng + .try_fill_bytes(bytes) + .map_err(|_| GetRandomFailed) + } + + #[cfg(not(feature = "rand"))] + { + Err(GetRandomFailed) + } } } impl KeyProvider for Provider { fn load_private_key( &self, - key_der: pki_types::PrivateKeyDer<'static>, + #[allow(unused_variables)] key_der: PrivateKeyDer<'static>, ) -> Result, rustls::Error> { - sign::any_supported_type(&key_der) + #[cfg(feature = "signature")] + { + sign::any_supported_type(&key_der) + } + #[cfg(not(feature = "signature"))] + { + Err(rustls::Error::General("not key providers supported".into())) + } } } @@ -90,6 +106,7 @@ pub mod hmac; pub mod kx; pub mod misc; +#[cfg(feature = "signature")] pub mod sign; pub mod verify; diff --git a/src/sign.rs b/src/sign.rs index b08841b..3e0132b 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -2,47 +2,10 @@ use alloc::{sync::Arc, vec::Vec}; use core::marker::PhantomData; -#[cfg(all(feature = "ecdsa", feature = "der"))] -use self::ecdsa::nist::{EcdsaSigningKeyP256, EcdsaSigningKeyP384}; - -#[cfg(all(feature = "eddsa", feature = "ed25519"))] -use self::eddsa::ed25519::Ed25519SigningKey; - -#[cfg(feature = "rsa")] -use self::rsa::RsaSigningKey; - use pki_types::PrivateKeyDer; use rustls::sign::{Signer, SigningKey}; use rustls::{Error, SignatureScheme}; -use signature::{RandomizedSigner, SignatureEncoding}; - -#[derive(Debug)] -pub struct GenericRandomizedSigner -where - S: SignatureEncoding, - T: RandomizedSigner, -{ - _marker: PhantomData, - key: Arc, - scheme: SignatureScheme, -} - -impl Signer for GenericRandomizedSigner -where - S: SignatureEncoding + Send + Sync + core::fmt::Debug, - T: RandomizedSigner + Send + Sync + core::fmt::Debug, -{ - fn sign(&self, message: &[u8]) -> Result, Error> { - self.key - .try_sign_with_rng(&mut rand_core::OsRng, message) - .map_err(|_| rustls::Error::General("signing failed".into())) - .map(|sig: S| sig.to_vec()) - } - - fn scheme(&self) -> SignatureScheme { - self.scheme - } -} +use signature::SignatureEncoding; #[derive(Debug)] pub struct GenericSigner @@ -79,17 +42,15 @@ where /// Returns an error if the key couldn't be decoded. #[allow(unused_variables)] pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - #[cfg(feature = "rsa")] - if let Ok(key) = RsaSigningKey::try_from(der) { + #[cfg(all(feature = "der", feature = "rsa"))] + if let Ok(key) = rsa::RsaSigningKey::try_from(der) { return Ok(Arc::new(key) as _); } - #[cfg(feature = "ecdsa")] if let Ok(key) = any_ecdsa_type(der) { return Ok(key); } - #[cfg(feature = "eddsa")] if let Ok(key) = any_eddsa_type(der) { return Ok(key); } @@ -104,12 +65,12 @@ pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result /// Returns an error if the key couldn't be decoded. #[allow(unused_variables)] pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - #[cfg(all(feature = "der", feature = "p256"))] - if let Ok(key) = EcdsaSigningKeyP256::try_from(der) { + #[cfg(all(feature = "der", feature = "ecdsa-p256"))] + if let Ok(key) = ecdsa::nist::EcdsaSigningKeyP256::try_from(der) { return Ok(Arc::new(key) as _); } - #[cfg(all(feature = "der", feature = "p384"))] - if let Ok(key) = EcdsaSigningKeyP384::try_from(der) { + #[cfg(all(feature = "der", feature = "ecdsa-p384"))] + if let Ok(key) = ecdsa::nist::EcdsaSigningKeyP384::try_from(der) { return Ok(Arc::new(key) as _); } @@ -124,8 +85,8 @@ pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, ru #[allow(unused_variables)] pub fn any_eddsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { // TODO: Add support for Ed448 - #[cfg(feature = "ed25519")] - if let Ok(key) = Ed25519SigningKey::try_from(der) { + #[cfg(all(feature = "der", feature = "eddsa-ed25519"))] + if let Ok(key) = eddsa::ed25519::Ed25519SigningKey::try_from(der) { return Ok(Arc::new(key) as _); } @@ -138,3 +99,6 @@ pub mod ecdsa; pub mod eddsa; #[cfg(feature = "rsa")] pub mod rsa; + +#[cfg(feature = "rand")] +pub mod rand; diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs index 957df3f..ec39cf6 100644 --- a/src/sign/ecdsa/nist.rs +++ b/src/sign/ecdsa/nist.rs @@ -1,13 +1,15 @@ -use crate::sign::GenericRandomizedSigner; #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, sync::Arc}; + +use crate::sign::rand::GenericRandomizedSigner; use core::marker::PhantomData; use paste::paste; -#[cfg(feature = "der")] -use pki_types::PrivateKeyDer; use rustls::sign::SigningKey; use rustls::{SignatureAlgorithm, SignatureScheme}; +#[cfg(feature = "der")] +use pki_types::PrivateKeyDer; + macro_rules! impl_ecdsa { ($name: ident, $scheme: expr, $signing_key: ty, $signature: ty) => { paste! { diff --git a/src/sign/eddsa/ed25519.rs b/src/sign/eddsa/ed25519.rs index 43a1a28..1651ae3 100644 --- a/src/sign/eddsa/ed25519.rs +++ b/src/sign/eddsa/ed25519.rs @@ -1,10 +1,12 @@ -use crate::sign::GenericSigner; #[cfg(feature = "alloc")] use alloc::{boxed::Box, format, string::ToString, sync::Arc}; + +use crate::sign::GenericSigner; use core::marker::PhantomData; use ed25519_dalek::SigningKey; use pki_types::PrivateKeyDer; use rustls::{sign::Signer, SignatureAlgorithm, SignatureScheme}; + #[derive(Debug)] pub struct Ed25519SigningKey(Arc); diff --git a/src/sign/rand.rs b/src/sign/rand.rs new file mode 100644 index 0000000..39ab04e --- /dev/null +++ b/src/sign/rand.rs @@ -0,0 +1,35 @@ +#[cfg(feature = "alloc")] +use alloc::{sync::Arc, vec::Vec}; +use core::marker::PhantomData; + +use rustls::sign::Signer; +use rustls::{Error, SignatureScheme}; +use signature::{RandomizedSigner, SignatureEncoding}; + +#[derive(Debug)] +pub struct GenericRandomizedSigner +where + S: SignatureEncoding, + T: RandomizedSigner, +{ + pub(crate) _marker: PhantomData, + pub(crate) key: Arc, + pub(crate) scheme: SignatureScheme, +} + +impl Signer for GenericRandomizedSigner +where + S: SignatureEncoding + Send + Sync + core::fmt::Debug, + T: RandomizedSigner + Send + Sync + core::fmt::Debug, +{ + fn sign(&self, message: &[u8]) -> Result, Error> { + self.key + .try_sign_with_rng(&mut rand_core::OsRng, message) + .map_err(|_| rustls::Error::General("signing failed".into())) + .map(|sig: S| sig.to_vec()) + } + + fn scheme(&self) -> SignatureScheme { + self.scheme + } +} diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index 336c67d..2877ab2 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -60,7 +60,7 @@ impl SigningKey for RsaSigningKey { .and_then(|&scheme| { macro_rules! signer { ($key:ty) => {{ - Some(Box::new(super::GenericRandomizedSigner { + Some(Box::new(super::rand::GenericRandomizedSigner { _marker: Default::default(), key: Arc::new(<$key>::new(self.0.clone())), scheme, diff --git a/src/tls12.rs b/src/tls12.rs index 809f0e5..3864c43 100644 --- a/src/tls12.rs +++ b/src/tls12.rs @@ -1,2 +1,3 @@ +#[cfg(feature = "aead")] pub mod aead; pub mod suites; diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs index 59b8ad9..0b0c818 100644 --- a/src/tls12/aead/gcm.rs +++ b/src/tls12/aead/gcm.rs @@ -2,7 +2,7 @@ use alloc::boxed::Box; use crate::aead::{Aes128Gcm, Aes256Gcm}; -use aead::{AeadCore, AeadInPlace}; +use ::aead::{AeadCore, AeadInPlace}; use crypto_common::typenum::Unsigned; use crypto_common::{KeyInit, KeySizeUser}; use paste::paste; diff --git a/src/tls13.rs b/src/tls13.rs index 809f0e5..3864c43 100644 --- a/src/tls13.rs +++ b/src/tls13.rs @@ -1,2 +1,3 @@ +#[cfg(feature = "aead")] pub mod aead; pub mod suites; diff --git a/src/verify.rs b/src/verify.rs index 6721480..668e879 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -7,6 +7,7 @@ use rustls::crypto::WebPkiSupportedAlgorithms; use rustls::SignatureScheme; pub(crate) enum Error { + #[cfg(feature = "signature")] Signature, TryFromSlice, #[cfg(feature = "der")] @@ -15,6 +16,7 @@ pub(crate) enum Error { Pkcs1, } +#[cfg(feature = "signature")] impl From for Error { fn from(_: signature::Error) -> Self { Self::Signature @@ -47,13 +49,13 @@ pub const ALL: &[&'static dyn SignatureVerificationAlgorithm] = const_concat_sli #[cfg(feature = "ecdsa")] { &[ - #[cfg(feature = "p256")] + #[cfg(feature = "ecdsa-p256")] ecdsa::nist::ECDSA_P256_SHA256, - #[cfg(feature = "p256")] + #[cfg(feature = "ecdsa-p256")] ecdsa::nist::ECDSA_P256_SHA384, - #[cfg(feature = "p384")] + #[cfg(feature = "ecdsa-p384")] ecdsa::nist::ECDSA_P384_SHA256, - #[cfg(feature = "p384")] + #[cfg(feature = "ecdsa-p384")] ecdsa::nist::ECDSA_P384_SHA384, ] } @@ -107,7 +109,7 @@ pub const MAPPING: &[( #[cfg(feature = "ecdsa")] { &[ - #[cfg(feature = "p384")] + #[cfg(feature = "ecdsa-p384")] ( SignatureScheme::ECDSA_NISTP384_SHA384, &[ @@ -116,12 +118,12 @@ pub const MAPPING: &[( ecdsa::nist::ECDSA_P256_SHA384, ], ), + #[cfg(feature = "ecdsa-p256")] ( - #[cfg(feature = "p256")] SignatureScheme::ECDSA_NISTP256_SHA256, &[ ecdsa::nist::ECDSA_P256_SHA256, - #[cfg(feature = "p384")] + #[cfg(feature = "ecdsa-p384")] ecdsa::nist::ECDSA_P384_SHA256, ], ), @@ -170,7 +172,7 @@ pub const ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { #[cfg(feature = "eddsa")] { &[ - #[cfg(feature = "ed25519")] + #[cfg(feature = "eddsa-ed25519")] eddsa::ed25519::ED25519, ] } @@ -190,7 +192,7 @@ pub const ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms { #[cfg(feature = "eddsa")] { &[ - #[cfg(feature = "ed25519")] + #[cfg(feature = "eddsa-ed25519")] (SignatureScheme::ED25519, &[eddsa::ed25519::ED25519]), ] } From d5ae16b9e79148f4e2d6752c9373fd807a976844 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:50:56 +0800 Subject: [PATCH 10/38] rsa: make pkcs1 independent --- Cargo.toml | 4 ++-- src/verify/rsa.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0f98cfe..c837abd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,8 +112,8 @@ kx-p384 = ["p384", "p384/ecdh", "kx"] kx-p521 = ["p521", "p521/ecdh", "kx"] kx-full = ["kx-x25519", "kx-p256", "kx-p384", "kx-p521"] -rsa = ["dep:rsa", "rsa/sha2"] -rsa-pkcs1 = ["rsa", "pkcs1"] +rsa = ["dep:rsa", "rsa/sha2", "verify", "signature", "pkcs1"] +rsa-pkcs1 = ["rsa"] rsa-pss = ["rsa"] rsa-full = ["rsa-pkcs1", "rsa-pss"] diff --git a/src/verify/rsa.rs b/src/verify/rsa.rs index 6cb265a..e125d82 100644 --- a/src/verify/rsa.rs +++ b/src/verify/rsa.rs @@ -24,7 +24,7 @@ macro_rules! impl_generic_rsa_verifer { signature: &[u8], ) -> Result<(), crate::verify::Error> { use rsa::RsaPublicKey; - use rsa::pkcs1::DecodeRsaPublicKey; + use pkcs1::DecodeRsaPublicKey; let public_key = RsaPublicKey::from_pkcs1_der(public_key)?; let signature = <$signature>::try_from(signature)?; From 65d74f96e41a5252210dc9cd84f731226deab3e7 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:51:39 +0800 Subject: [PATCH 11/38] ensure a fallback slice when tls 1.2 is disabled --- src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 55d69a6..7020455 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,8 +94,13 @@ pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices { tls12::suites::TLS12_SUITES } + + #[cfg(not(feature = "tls12"))] + { + &[] + } }, - tls13::suites::TLS13_SUITES, + tls13::suites::TLS13_SUITES ); #[cfg(feature = "aead")] From 680cbcd0addd596fa8db877d3c33177136826eb8 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:51:58 +0800 Subject: [PATCH 12/38] fixup! make sure more features are correctly separated --- src/sign/ecdsa/nist.rs | 4 ++-- src/verify/ecdsa/nist.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs index ec39cf6..664cc2d 100644 --- a/src/sign/ecdsa/nist.rs +++ b/src/sign/ecdsa/nist.rs @@ -68,8 +68,8 @@ macro_rules! impl_ecdsa { }; } -#[cfg(feature = "p256")] +#[cfg(feature = "ecdsa-p256")] impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, ::p256::ecdsa::SigningKey, ::p256::ecdsa::DerSignature} -#[cfg(feature = "p384")] +#[cfg(feature = "ecdsa-p384")] impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, ::p384::ecdsa::SigningKey, ::p384::ecdsa::DerSignature} diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs index fa9c2fe..59343c2 100644 --- a/src/verify/ecdsa/nist.rs +++ b/src/verify/ecdsa/nist.rs @@ -54,11 +54,11 @@ macro_rules! impl_generic_ecdsa_verifer { }; } -#[cfg(feature = "p256")] +#[cfg(feature = "ecdsa-p256")] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha256} -#[cfg(feature = "p256")] +#[cfg(feature = "ecdsa-p256")] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha384} -#[cfg(feature = "p384")] +#[cfg(feature = "ecdsa-p384")] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha256} -#[cfg(feature = "p384")] +#[cfg(feature = "ecdsa-p384")] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha384} From d31abc4c85f709afe3a606fb8397d675d40ffb7e Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 7 Dec 2024 14:58:41 +0800 Subject: [PATCH 13/38] upgrade dependencies --- Cargo.lock | 52 ++++++++++++++++++++++++++-------------------------- Cargo.toml | 6 +++--- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41dd6ba..8da5bcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,9 +72,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.1.22" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9540e661f81799159abee814118cc139a2004b3a3aa3ea37724a1b66530b90e0" +checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" dependencies = [ "shlex", ] @@ -128,9 +128,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -372,15 +372,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "log" @@ -437,9 +437,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" @@ -574,9 +574,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -646,9 +646,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -676,9 +676,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "log", "once_cell", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-rustcrypto" @@ -758,18 +758,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -833,9 +833,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -850,9 +850,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "universal-hash" diff --git a/Cargo.toml b/Cargo.toml index c837abd..52658fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ pkcs1 = { version = "0.7.5", default-features = false, optional = true } pkcs8 = { version = "0.10.2", default-features = false, features = [ "pkcs5", ], optional = true } -rsa = { version = "0.9.6", default-features = false, features = [ +rsa = { version = "0.9.7", default-features = false, features = [ "sha2", ], optional = true } sec1 = { version = "0.7.3", default-features = false, optional = true } @@ -45,11 +45,11 @@ signature = { version = "2.2.0", default-features = false, optional = true } x25519-dalek = { version = "2", default-features = false, optional = true } paste = { version = "1.0.15", default-features = false } -pki-types = { package = "rustls-pki-types", version = "1.8.0", default-features = false } +pki-types = { package = "rustls-pki-types", version = "1.10.0", default-features = false } rand_core = { version = "0.6.4", default-features = false, features = [ "getrandom", ], optional = true } -rustls = { version = "0.23.13", default-features = false } +rustls = { version = "0.23.19", default-features = false } webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false, optional = true } From bfa3dfb9c807619c104b4931aa7f4386dff18251 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 7 Dec 2024 15:16:58 +0800 Subject: [PATCH 14/38] require pkcs8 for pkcs1 decode in rsa --- src/sign/rsa.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index 2877ab2..34c6199 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -38,7 +38,7 @@ impl TryFrom<&PrivateKeyDer<'_>> for RsaSigningKey { RsaPrivateKey::from_pkcs8_der(der.secret_pkcs8_der()) .map_err(|e| format!("failed to decrypt private key: {e}")) } - #[cfg(feature = "pkcs1")] + #[cfg(all(feature = "pkcs8", feature = "pkcs1"))] PrivateKeyDer::Pkcs1(der) => { use pkcs1::DecodeRsaPrivateKey; RsaPrivateKey::from_pkcs1_der(der.secret_pkcs1_der()) From c8911d41886a07be7ddac4f142147deddc7bf43b Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sat, 7 Dec 2024 18:08:13 +0800 Subject: [PATCH 15/38] enable all suites when testing --- .github/workflows/rustls-rustcrypto.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rustls-rustcrypto.yml b/.github/workflows/rustls-rustcrypto.yml index 37e374a..f0056aa 100644 --- a/.github/workflows/rustls-rustcrypto.yml +++ b/.github/workflows/rustls-rustcrypto.yml @@ -63,7 +63,7 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - - run: cargo build --no-default-features --features tls12,alloc --release --target ${{ matrix.target }} + - run: cargo build --no-default-features --features tls12,full,alloc --release --target ${{ matrix.target }} test: strategy: @@ -80,7 +80,7 @@ jobs: toolchain: ${{ matrix.toolchain }} - run: cargo test --features tls12 - name: Test no_std with alloc - run: cargo test --no-default-features --features tls12,alloc + run: cargo test --no-default-features --features tls12,full,alloc cross: strategy: From 1a030615494f7ba4d40f0f65e87472f2e5116b31 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 03:52:35 +0800 Subject: [PATCH 16/38] add experimental CCM support --- Cargo.lock | 134 +++++++++++++++++++++++++++++++++++++- Cargo.toml | 12 ++-- README.md | 6 ++ src/aead.rs | 15 +++++ src/aead/aes.rs | 36 ++++++++++ src/tls12/aead.rs | 3 + src/tls12/aead/ccm.rs | 132 +++++++++++++++++++++++++++++++++++++ src/tls12/aead/gcm.rs | 4 +- src/tls12/suites/ecdsa.rs | 67 +++++++++++++++++++ src/tls13/aead.rs | 3 + src/tls13/aead/ccm.rs | 91 ++++++++++++++++++++++++++ src/tls13/aead/gcm.rs | 4 +- src/tls13/suites.rs | 6 +- src/tls13/suites/aes.rs | 60 ++++++++++++++++- 14 files changed, 558 insertions(+), 15 deletions(-) create mode 100644 src/aead/aes.rs create mode 100644 src/tls12/aead/ccm.rs create mode 100644 src/tls13/aead/ccm.rs diff --git a/Cargo.lock b/Cargo.lock index 8da5bcf..6af9c36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" + [[package]] name = "cc" version = "1.2.3" @@ -79,6 +85,18 @@ dependencies = [ "shlex", ] +[[package]] +name = "ccm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" +dependencies = [ + "aead", + "cipher", + "ctr", + "subtle", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -200,10 +218,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", +] + [[package]] name = "digest" version = "0.10.7" @@ -254,6 +285,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" @@ -291,6 +328,21 @@ 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 = "flume" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835349a364636c2aaafda82d5514c32ac7463898207ae5f97d978a82ad26b517" +dependencies = [ + "spin 0.5.2", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -361,13 +413,22 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin", + "spin 0.9.8", ] [[package]] @@ -388,6 +449,17 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "memory-socket" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d72eacb9607d926455717eb940ce0f994bbc3355867603405b50c109f43e7b81" +dependencies = [ + "bytes", + "flume", + "once_cell", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -639,7 +711,7 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin", + "spin 0.9.8", "untrusted", "windows-sys", ] @@ -699,7 +771,9 @@ name = "rustls-rustcrypto" version = "0.0.2-alpha" dependencies = [ "aead", + "aes", "aes-gcm", + "ccm", "chacha20poly1305", "crypto-common", "der", @@ -708,6 +782,8 @@ dependencies = [ "ed25519-dalek", "getrandom", "hmac", + "itertools", + "memory-socket", "p256", "p384", "p521", @@ -720,9 +796,11 @@ dependencies = [ "rustls-pki-types", "rustls-webpki", "sec1", + "sha1", "sha2", "signature", "x25519-dalek", + "x509-cert", ] [[package]] @@ -776,6 +854,17 @@ dependencies = [ "syn", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" @@ -809,6 +898,12 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[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" @@ -842,6 +937,27 @@ dependencies = [ "unicode-ident", ] +[[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", +] + [[package]] name = "typenum" version = "1.17.0" @@ -966,6 +1082,20 @@ 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", + "sha1", + "signature", + "spki", + "tls_codec", +] + [[package]] name = "zerocopy" version = "0.7.35" diff --git a/Cargo.toml b/Cargo.toml index 52658fc..8ce02a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,10 +18,12 @@ resolver = "1" # Hack to enable the `custom` feature of `getrandom` # Ensure all dependencies + feats are mapped to crate features for correct usage # default features often have std breaking no_std and potentially other unwanted [dependencies] +aes = { version = "0.8.4", default-features = false, optional = true } aead = { version = "0.5.2", default-features = false, optional = true } aes-gcm = { version = "0.10.3", default-features = false, features = [ "aes", ], optional = true } +ccm = { version = "0.5.0", optional = true, default-features = false } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } der = { version = "0.7.9", default-features = false, optional = true } @@ -84,7 +86,7 @@ std = [ "ed25519-dalek?/std", "pkcs1?/std", ] -alloc = ["webpki?/alloc", "ecdsa?/alloc", "signature?/alloc"] +alloc = ["webpki?/alloc", "ecdsa?/alloc", "signature?/alloc", "ccm?/alloc"] zeroize = ["ed25519-dalek?/zeroize", "x25519-dalek?/zeroize"] nist = [] @@ -95,7 +97,7 @@ ed25519 = ["dep:ed25519-dalek"] verify = ["dep:webpki"] -ecdsa = ["dep:ecdsa", "verify", "signature", "rand"] +ecdsa = ["dep:ecdsa", "verify", "signature", "rand", "der"] ecdsa-p256 = ["p256", "p256/ecdsa", "ecdsa"] ecdsa-p384 = ["p384", "p384/ecdsa", "ecdsa"] ecdsa-p521 = ["p521", "p521/ecdsa", "ecdsa"] @@ -118,9 +120,10 @@ rsa-pss = ["rsa"] rsa-full = ["rsa-pkcs1", "rsa-pss"] aead = ["dep:aead"] -aes-gcm = ["dep:aes-gcm", "aead"] +aes-gcm = ["aes", "dep:aes-gcm", "aead"] +aes-ccm = ["aes", "dep:ccm", "aead"] chacha20poly1305 = ["dep:chacha20poly1305", "aead"] -aead-full = ["aes-gcm", "chacha20poly1305"] +aead-full = ["aes-gcm", "aes-ccm", "chacha20poly1305"] # TODO hash = [] @@ -146,3 +149,4 @@ pkcs8 = [ signature = ["dep:signature"] rand = ["dep:rand_core", "signature?/rand_core"] +aes = ["dep:aes"] \ No newline at end of file diff --git a/README.md b/README.md index 39739a7..ec27143 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,18 @@ Note that RustCrypto performance is generally inferior than ring, but in exchang ## Supported Cipher Suites +- TLS_ECDHE_ECDSA_WITH_AES_128_CCM +- TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +- TLS_ECDHE_ECDSA_WITH_AES_256_CCM +- TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 +- TLS13_AES_128_CCM_SHA256 +- TLS13_AES_128_CCM_8_SHA256 - TLS13_AES_128_GCM_SHA256 - TLS13_AES_256_GCM_SHA384 - TLS13_CHACHA20_POLY1305_SHA256 diff --git a/src/aead.rs b/src/aead.rs index 0c8513c..ea6ed8f 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -12,6 +12,18 @@ pub struct Aes128Gcm; #[cfg(feature = "aes-gcm")] pub struct Aes256Gcm; +#[cfg(feature = "aes-ccm")] +pub struct Aes128Ccm; + +#[cfg(feature = "aes-ccm")] +pub struct Aes256Ccm; + +#[cfg(feature = "aes-ccm")] +pub struct Aes128Ccm8; + +#[cfg(feature = "aes-ccm")] +pub struct Aes256Ccm8; + pub(crate) struct EncryptBufferAdapter<'a>(pub(crate) &'a mut PrefixedPayload); impl AsRef<[u8]> for EncryptBufferAdapter<'_> { @@ -60,3 +72,6 @@ impl Buffer for DecryptBufferAdapter<'_, '_> { self.0.truncate(len) } } + +#[cfg(feature = "aes")] +pub mod aes; diff --git a/src/aead/aes.rs b/src/aead/aes.rs new file mode 100644 index 0000000..482d6ea --- /dev/null +++ b/src/aead/aes.rs @@ -0,0 +1,36 @@ +#[cfg(feature = "aes-ccm")] +use aes::{Aes128, Aes256}; +#[cfg(feature = "aes-ccm")] +use ccm::{ + consts::{U12, U16, U8}, + Ccm, +}; + +// The AEAD_AES_128_CCM authenticated encryption algorithm works as +// specified in [CCM], using AES-128 as the block cipher, by providing +// the key, nonce, associated data, and plaintext to that mode of +// operation. The formatting and counter generation function are as +// specified in Appendix A of that reference, and the values of the +// parameters identified in that appendix are as follows: +// the nonce length n is 12, +// the tag length t is 16, and +// the value of q is 3. +#[cfg(feature = "aes-ccm")] +pub type Aes128Ccm = Ccm; +#[cfg(feature = "aes-ccm")] +pub type Aes256Ccm = Ccm; + +// The AEAD_AES_128_CCM_8 authenticated encryption algorithm is +// identical to the AEAD_AES_128_CCM algorithm (see Section 5.3 of +// [RFC5116]), except that it uses 8 octets for authentication, instead +// of the full 16 octets used by AEAD_AES_128_CCM. +#[cfg(feature = "aes-ccm")] +pub type Aes128Ccm8 = Ccm; +#[cfg(feature = "aes-ccm")] +pub type Aes256Ccm8 = Ccm; + +#[cfg(feature = "aes-gcm")] +pub type Aes128Gcm = aes_gcm::Aes128Gcm; + +#[cfg(feature = "aes-gcm")] +pub type Aes256Gcm = aes_gcm::Aes256Gcm; diff --git a/src/tls12/aead.rs b/src/tls12/aead.rs index eca37fa..d9985ee 100644 --- a/src/tls12/aead.rs +++ b/src/tls12/aead.rs @@ -3,3 +3,6 @@ pub mod chacha20; #[cfg(feature = "aes-gcm")] pub mod gcm; + +#[cfg(feature = "aes-ccm")] +pub mod ccm; diff --git a/src/tls12/aead/ccm.rs b/src/tls12/aead/ccm.rs new file mode 100644 index 0000000..3964336 --- /dev/null +++ b/src/tls12/aead/ccm.rs @@ -0,0 +1,132 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crate::aead::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; +use ::aead::{AeadCore, AeadInPlace}; +use crypto_common::typenum::Unsigned; +use crypto_common::{KeyInit, KeySizeUser}; +use paste::paste; +use rustls::crypto::cipher::{ + self, make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, KeyBlockShape, + MessageDecrypter, MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, + PrefixedPayload, Tls12AeadAlgorithm, +}; +use rustls::ConnectionTrafficSecrets; + +const EXPLICIT_NONCE_LEN: usize = 8; + +macro_rules! impl_ccm { +($name: ident, $aead: ty, $nonce_pos: expr, $overhead: expr) => { + paste! { + impl Tls12AeadAlgorithm for $name { + fn encrypter(&self, key: AeadKey, write_iv: &[u8], explicit: &[u8]) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + { + let mut iv: [u8; 12] = [0; 12]; + iv[..4].copy_from_slice(write_iv); + iv[4..].copy_from_slice(explicit); + iv + }, + )) + } + + fn decrypter(&self, dec_key: AeadKey, dec_iv: &[u8]) -> Box { + Box::new([]( + $aead::new_from_slice(dec_key.as_ref()).unwrap(), + dec_iv.try_into().unwrap(), + )) + } + + fn key_block_shape(&self) -> KeyBlockShape { + KeyBlockShape { + enc_key_len: $aead::key_size(), + fixed_iv_len: 4, + explicit_nonce_len: 8, + } + } + + fn extract_keys( + &self, + _: AeadKey, + _: &[u8], + _explicit: &[u8], + ) -> Result { + Err(cipher::UnsupportedOperationError) + } + } + + pub struct []($aead, [u8; 12]); + + impl MessageEncrypter for [] { + fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + let nonce = cipher::Nonce::new(&self.1.into(), seq).0; + let aad = make_tls12_aad(seq, m.typ, m.version, m.payload.len()); + payload.extend_from_slice(&nonce.as_ref()[4..]); // explicit + payload.extend_from_chunks(&m.payload); + + self.0 + .encrypt_in_place_detached(&nonce.into(), &aad, &mut payload.as_mut()[$nonce_pos..]) + .map(|tag| payload.extend(tag.as_ref() as &[u8])) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new(m.typ, m.version, payload)) + } + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + $nonce_pos + <$aead as AeadCore>::TagSize::USIZE + } + } + + pub struct []($aead, [u8; 4]); + + impl MessageDecrypter for [] { + fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { + type TagSize = <$aead as AeadCore>::TagSize; + + let payload = &m.payload; + + if payload.len() < $overhead { + return Err(rustls::Error::DecryptError); + } + + let nonce: aead::Nonce<$aead> = { + let mut nonce = [0u8; 12]; + nonce[..4].copy_from_slice(&self.1); // dec_iv + nonce[4..].copy_from_slice(&payload[..$nonce_pos]); + nonce.into() + }; + + let aad = make_tls12_aad(seq, m.typ, m.version, payload.len() - $overhead); + + let payload = &mut m.payload; + let tag_pos = { + let payload = &mut payload[$nonce_pos..]; + let tag_pos = payload.len() - TagSize::to_usize(); + let (msg, tag) = payload.split_at_mut(tag_pos); + + let tag = ccm::Tag::::from_slice(tag); + self.0 + .decrypt_in_place_detached(&nonce, &aad, msg, tag) + .map_err(|_| rustls::Error::DecryptError)?; + tag_pos + }; + + // We defer the truncation to here, because we may inadvertently shifted the + // original data if the decryption failed. Another way to avoid this is + // to clone the payload slice starting after the explicit nonce, + // but this will cause an additional cloning and copying + payload.rotate_left($nonce_pos); + payload.truncate(tag_pos); + Ok(m.into_plain_message()) + } + } + } +}; +} + +impl_ccm! {Aes128Ccm, crate::aead::aes::Aes128Ccm, EXPLICIT_NONCE_LEN, EXPLICIT_NONCE_LEN + 16} +impl_ccm! {Aes256Ccm, crate::aead::aes::Aes256Ccm, EXPLICIT_NONCE_LEN, EXPLICIT_NONCE_LEN + 16} +impl_ccm! {Aes128Ccm8, crate::aead::aes::Aes128Ccm8, EXPLICIT_NONCE_LEN, EXPLICIT_NONCE_LEN + 8} +impl_ccm! {Aes256Ccm8, crate::aead::aes::Aes256Ccm8, EXPLICIT_NONCE_LEN, EXPLICIT_NONCE_LEN + 8} diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs index 0b0c818..a9ac813 100644 --- a/src/tls12/aead/gcm.rs +++ b/src/tls12/aead/gcm.rs @@ -130,5 +130,5 @@ macro_rules! impl_gcm { }; } -impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, EXPLICIT_NONCE_LEN, OVERHEAD} -impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, EXPLICIT_NONCE_LEN, OVERHEAD} +impl_gcm! {Aes128Gcm, crate::aead::aes::Aes128Gcm, EXPLICIT_NONCE_LEN, OVERHEAD} +impl_gcm! {Aes256Gcm, crate::aead::aes::Aes256Gcm, EXPLICIT_NONCE_LEN, OVERHEAD} diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs index f0f874b..0279f77 100644 --- a/src/tls12/suites/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -12,6 +12,9 @@ use rustls::{CipherSuite, Tls12CipherSuite}; #[cfg(feature = "aes-gcm")] use crate::aead::{Aes128Gcm, Aes256Gcm}; +#[cfg(feature = "aes-ccm")] +use crate::aead::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; + #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; @@ -41,6 +44,62 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12Ciphe aead_alg: &Aes256Gcm, }; +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_128_CCM/ +#[cfg(feature = "aes-ccm")] +pub const TLS_ECDHE_ECDSA_WITH_AES_128_CCM: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + aead_alg: &Aes128Ccm, + prf_provider: &PrfUsingHmac(hmac::SHA256), +}; + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_256_CCM/ +#[cfg(feature = "aes-ccm")] +pub const TLS_ECDHE_ECDSA_WITH_AES_256_CCM: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + aead_alg: &Aes256Ccm, + prf_provider: &PrfUsingHmac(hmac::SHA256), +}; + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8/ +#[cfg(feature = "aes-ccm")] +pub const TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + aead_alg: &Aes128Ccm8, + prf_provider: &PrfUsingHmac(hmac::SHA256), +}; + +// https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8/ +#[cfg(feature = "aes-ccm")] +pub const TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: Tls12CipherSuite = Tls12CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + kx: KeyExchangeAlgorithm::ECDHE, + sign: TLS12_ECDSA_SCHEMES, + aead_alg: &Aes256Ccm8, + prf_provider: &PrfUsingHmac(hmac::SHA256), +}; + #[cfg(feature = "chacha20poly1305")] pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { @@ -59,6 +118,14 @@ pub const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), #[cfg(feature = "aes-gcm")] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), + #[cfg(feature = "aes-ccm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_CCM), + #[cfg(feature = "aes-ccm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_CCM), + #[cfg(feature = "aes-ccm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8), + #[cfg(feature = "aes-ccm")] + SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8), #[cfg(feature = "chacha20poly1305")] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), ]; diff --git a/src/tls13/aead.rs b/src/tls13/aead.rs index eca37fa..d9985ee 100644 --- a/src/tls13/aead.rs +++ b/src/tls13/aead.rs @@ -3,3 +3,6 @@ pub mod chacha20; #[cfg(feature = "aes-gcm")] pub mod gcm; + +#[cfg(feature = "aes-ccm")] +pub mod ccm; diff --git a/src/tls13/aead/ccm.rs b/src/tls13/aead/ccm.rs new file mode 100644 index 0000000..7a23e14 --- /dev/null +++ b/src/tls13/aead/ccm.rs @@ -0,0 +1,91 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crate::aead::{Aes128Ccm, Aes128Ccm8, DecryptBufferAdapter, EncryptBufferAdapter}; +use aead::AeadInPlace; +use crypto_common::{KeyInit, KeySizeUser}; +use paste::paste; +use rustls::crypto::cipher::{ + self, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, MessageDecrypter, + MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, + Tls13AeadAlgorithm, UnsupportedOperationError, +}; +use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion}; + +macro_rules! impl_ccm { +($name: ident, $aead: ty, $overhead: expr) => { + paste! { + impl Tls13AeadAlgorithm for $name { + fn encrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + iv, + )) + } + + fn decrypter(&self, key: AeadKey, iv: cipher::Iv) -> Box { + Box::new([]( + $aead::new_from_slice(key.as_ref()).unwrap(), + iv, + )) + } + + fn key_len(&self) -> usize { + $aead::key_size() + } + fn extract_keys( + &self, + _: AeadKey, + _: cipher::Iv, + ) -> Result { + Err(UnsupportedOperationError) + } + } + + pub struct []($aead, cipher::Iv); + + impl MessageEncrypter for [] { + fn encrypt(&mut self, m: OutboundPlainMessage<'_>, seq: u64) -> Result { + let total_len = self.encrypted_payload_len(m.payload.len()); + let mut payload = PrefixedPayload::with_capacity(total_len); + + let nonce = cipher::Nonce::new(&self.1, seq).0; + let aad = make_tls13_aad(total_len); + payload.extend_from_chunks(&m.payload); + payload.extend_from_slice(&m.typ.to_array()); + + self.0 + .encrypt_in_place(&nonce.into(), &aad, &mut EncryptBufferAdapter(&mut payload)) + .map_err(|_| rustls::Error::EncryptError) + .map(|_| OutboundOpaqueMessage::new( + ContentType::ApplicationData, + ProtocolVersion::TLSv1_2, + payload, + )) + } + + fn encrypted_payload_len(&self, payload_len: usize) -> usize { + payload_len + 1 + $overhead + } + } + + impl MessageDecrypter for [] { + fn decrypt<'a>(&mut self, mut m: InboundOpaqueMessage<'a>, seq: u64) -> Result, rustls::Error> { + let payload = &mut m.payload; + let nonce = cipher::Nonce::new(&self.1, seq).0; + let aad = make_tls13_aad(payload.len()); + + self.0 + .decrypt_in_place(&nonce.into(), &aad, &mut DecryptBufferAdapter(payload)) + .map_err(|_| rustls::Error::DecryptError)?; + + m.into_tls13_unpadded_message() + } + } + + } +}; +} + +impl_ccm! {Aes128Ccm, crate::aead::aes::Aes128Ccm, 16} +impl_ccm! {Aes128Ccm8, crate::aead::aes::Aes128Ccm8, 16} diff --git a/src/tls13/aead/gcm.rs b/src/tls13/aead/gcm.rs index 9dd30cd..04dc7d1 100644 --- a/src/tls13/aead/gcm.rs +++ b/src/tls13/aead/gcm.rs @@ -87,5 +87,5 @@ macro_rules! impl_gcm { }; } -impl_gcm! {Aes128Gcm, aes_gcm::Aes128Gcm, 16} -impl_gcm! {Aes256Gcm, aes_gcm::Aes256Gcm, 16} +impl_gcm! {Aes128Gcm, crate::aead::aes::Aes128Gcm, 16} +impl_gcm! {Aes256Gcm, crate::aead::aes::Aes256Gcm, 16} diff --git a/src/tls13/suites.rs b/src/tls13/suites.rs index 1ace1b6..4b0bd06 100644 --- a/src/tls13/suites.rs +++ b/src/tls13/suites.rs @@ -4,12 +4,12 @@ use rustls::SupportedCipherSuite; pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( SupportedCipherSuite, { - #[cfg(feature = "aes-gcm")] + #[cfg(feature = "aes")] { aes::TLS13_AES_SUITES } - #[cfg(not(feature = "aes-gcm"))] + #[cfg(not(feature = "aes"))] { &[] } @@ -28,7 +28,7 @@ pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( &[] ); -#[cfg(feature = "aes-gcm")] +#[cfg(feature = "aes")] pub mod aes; #[cfg(feature = "chacha20poly1305")] diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs index 9db122b..d6f8e89 100644 --- a/src/tls13/suites/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,8 +1,13 @@ +#[cfg(feature = "aes-ccm")] +use crate::aead::Aes128Ccm; +#[cfg(feature = "aes-gcm")] use crate::aead::{Aes128Gcm, Aes256Gcm}; +use crate::const_concat_slices; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; +#[cfg(feature = "aes-gcm")] pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { @@ -15,6 +20,7 @@ pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = quic: None, }); +#[cfg(feature = "aes-gcm")] pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { @@ -27,5 +33,55 @@ pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = quic: None, }); -pub const TLS13_AES_SUITES: &[SupportedCipherSuite] = - &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384]; +#[cfg(feature = "aes-ccm")] +pub const TLS13_AES_128_CCM_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls13(&Tls13CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS13_AES_128_CCM_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &HkdfUsingHmac(hmac::SHA256), + aead_alg: &Aes128Ccm, + quic: None, + }); + +#[cfg(feature = "aes-ccm")] +pub const TLS13_AES_128_CCM_8_SHA256: SupportedCipherSuite = + SupportedCipherSuite::Tls13(&Tls13CipherSuite { + common: CipherSuiteCommon { + suite: CipherSuite::TLS13_AES_128_CCM_8_SHA256, + hash_provider: hash::SHA256, + confidentiality_limit: u64::MAX, + }, + hkdf_provider: &HkdfUsingHmac(hmac::SHA256), + aead_alg: &Aes128Ccm, + quic: None, + }); + +pub const TLS13_AES_SUITES: &[SupportedCipherSuite] = const_concat_slices!( + SupportedCipherSuite, + { + #[cfg(feature = "aes-gcm")] + { + &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384] + } + + #[cfg(not(feature = "aes-gcm"))] + { + &[] + } + }, + { + #[cfg(feature = "aes-ccm")] + { + &[TLS13_AES_128_CCM_SHA256, TLS13_AES_128_CCM_8_SHA256] + } + + #[cfg(not(feature = "aes-ccm"))] + { + &[] + } + }, + &[] +); From 53eb41200ac308a9e28bfedfb4a4002fa8c5cebd Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 04:43:31 +0800 Subject: [PATCH 17/38] add a more comprehensive test method --- Cargo.lock | 37 +----- Cargo.toml | 14 +- tests/builder.rs | 198 +++++++++++++++++++--------- tests/fake_cert_client_verifier.rs | 71 ---------- tests/fake_cert_server_resolver.rs | 199 ++++++++++++++++++++++++++++- tests/fake_cert_server_verifier.rs | 59 --------- tests/fake_time.rs | 4 +- tests/mem_socket.rs | 103 +++++++++++++++ 8 files changed, 456 insertions(+), 229 deletions(-) delete mode 100644 tests/fake_cert_client_verifier.rs delete mode 100644 tests/fake_cert_server_verifier.rs create mode 100644 tests/mem_socket.rs diff --git a/Cargo.lock b/Cargo.lock index 6af9c36..22b1042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,9 +72,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "0.5.6" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" @@ -334,15 +334,6 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" -[[package]] -name = "flume" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835349a364636c2aaafda82d5514c32ac7463898207ae5f97d978a82ad26b517" -dependencies = [ - "spin 0.5.2", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -428,7 +419,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -449,17 +440,6 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "memory-socket" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d72eacb9607d926455717eb940ce0f994bbc3355867603405b50c109f43e7b81" -dependencies = [ - "bytes", - "flume", - "once_cell", -] - [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -711,7 +691,7 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", "windows-sys", ] @@ -773,6 +753,7 @@ dependencies = [ "aead", "aes", "aes-gcm", + "bytes", "ccm", "chacha20poly1305", "crypto-common", @@ -783,7 +764,6 @@ dependencies = [ "getrandom", "hmac", "itertools", - "memory-socket", "p256", "p384", "p521", @@ -796,7 +776,6 @@ dependencies = [ "rustls-pki-types", "rustls-webpki", "sec1", - "sha1", "sha2", "signature", "x25519-dalek", @@ -898,12 +877,6 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[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" diff --git a/Cargo.toml b/Cargo.toml index 8ce02a3..a5ae936 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,11 +54,21 @@ rand_core = { version = "0.6.4", default-features = false, features = [ rustls = { version = "0.23.19", default-features = false } webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false, optional = true } - [dev-dependencies] +# workaround to build on no_std targets getrandom = { version = "0.2", features = [ "custom", -] } # workaround to build on no_std targets +] } +itertools = "0.13.0" +sha2 = { version = "0.10.8", default-features = false, features = ["oid"] } +x509-cert = { version = "0.2.5", default-features = false, features = [ + "builder", + "pem" +] } +rsa = { version = "0.9.7", default-features = false, features = [ + "sha2", +] } +bytes = { version = "1.9.0", default-features = false } [features] default = ["std", "tls12", "zeroize", "full"] diff --git a/tests/builder.rs b/tests/builder.rs index bab5d85..22c2ce2 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -1,83 +1,165 @@ -use std::sync::Arc; +use std::io::{Read, Write}; +use std::sync::{Arc, OnceLock}; -use rustls::ClientConfig as RusTlsClientConfig; -use rustls::ServerConfig as RusTlsServerConfig; - -use rustls_rustcrypto::provider as rustcrypto_provider; - -mod fake_time; +use fake_cert_server_resolver::FakeServerCertResolver; use fake_time::FakeTime; - -mod fake_cert_server_verifier; -use fake_cert_server_verifier::FakeServerCertVerifier; - -mod fake_cert_client_verifier; -use fake_cert_client_verifier::FakeClientCertVerifier; +use itertools::iproduct; +use mem_socket::MemorySocket; +use rand_core::{OsRng, RngCore}; +use rustls::crypto::CryptoProvider; +use rustls::{ + ClientConfig as RusTlsClientConfig, RootCertStore, ServerConfig as RusTlsServerConfig, +}; +use rustls_rustcrypto::{provider as rustcrypto_provider, verify, Provider}; mod fake_cert_server_resolver; -use fake_cert_server_resolver::FakeServerCertResolver; +mod fake_time; -// Test integration between rustls and rustls in Client builder context -#[test] -fn integrate_client_builder_with_details_fake() { - let provider = rustcrypto_provider(); - let time_provider = FakeTime {}; +static SERVER_RESOLVER: OnceLock> = OnceLock::new(); - let fake_server_cert_verifier = FakeServerCertVerifier {}; +fn make_client_config(provider: CryptoProvider) -> RusTlsClientConfig { + let resolver = SERVER_RESOLVER.get_or_init(|| Arc::new(FakeServerCertResolver::new())); + let mut store = RootCertStore::empty(); - let builder_init = - RusTlsClientConfig::builder_with_details(Arc::new(provider), Arc::new(time_provider)); + store.add(resolver.rsa_root_cert()).unwrap(); + store.add(resolver.ecdsa_root_cert()).unwrap(); - let builder_default_versions = builder_init + RusTlsClientConfig::builder_with_details(Arc::new(provider), Arc::new(FakeTime {})) .with_safe_default_protocol_versions() - .expect("Default protocol versions error?"); + .expect("Default protocol versions error?") + .with_root_certificates(store) + // .dangerous() + // .with_custom_certificate_verifier(Arc::new(FakeServerCertVerifier {})) + .with_no_client_auth() +} - let dangerous_verifier = builder_default_versions - .dangerous() - .with_custom_certificate_verifier(Arc::new(fake_server_cert_verifier)); +fn make_server_config(provider: CryptoProvider) -> RusTlsServerConfig { + let resolver = SERVER_RESOLVER + .get_or_init(|| Arc::new(FakeServerCertResolver::new())) + .clone(); + RusTlsServerConfig::builder_with_details(Arc::new(provider), Arc::new(FakeTime {})) + .with_safe_default_protocol_versions() + .expect("Default protocol versions error?") + .with_no_client_auth() + .with_cert_resolver(resolver) +} +// Test integration between rustls and rustls in Client builder context +#[test] +fn integrate_client_builder_with_details_fake() { // Out of scope - let rustls_client_config = dangerous_verifier.with_no_client_auth(); + let rustls_client_config = make_client_config(rustcrypto_provider()); // RustCrypto is not fips assert!(!rustls_client_config.fips()); } -use rustls::DistinguishedName; - // Test integration between rustls and rustls in Server builder context #[test] fn integrate_server_builder_with_details_fake() { - let provider = rustcrypto_provider(); - let time_provider = FakeTime {}; - - let builder_init = - RusTlsServerConfig::builder_with_details(Arc::new(provider), Arc::new(time_provider)); - - let builder_default_versions = builder_init - .with_safe_default_protocol_versions() - .expect("Default protocol versions error?"); - - // A DistinguishedName is a Vec wrapped in internal types. - // DER or BER encoded Subject field from RFC 5280 for a single certificate. - // The Subject field is encoded as an RFC 5280 Name - //let b_wrap_in: &[u8] = b""; // TODO: should have constant somewhere - - let dummy_entry: &[u8] = b""; - - let client_dn = [DistinguishedName::in_sequence(dummy_entry)]; - - let client_cert_verifier = FakeClientCertVerifier { dn: client_dn }; + let rustls_server_config = make_server_config(rustcrypto_provider()); - let dangerous_verifier = - builder_default_versions.with_client_cert_verifier(Arc::new(client_cert_verifier)); + // RustCrypto is not fips + assert!(!rustls_server_config.fips()); +} - let server_cert_resolver = FakeServerCertResolver {}; +const CLIENT_MAGIC: &[u8; 18] = b"Hello from Client!"; +const SERVER_MAGIC: &[u8; 18] = b"Hello from Server!"; - // Out of scope - let rustls_client_config = - dangerous_verifier.with_cert_resolver(Arc::new(server_cert_resolver)); +// Test integration +#[test] +fn test_basic_round_trip() { + std::thread::scope(move |s| { + for provider in generate_providers() { + // Creates a pair of sockets that interconnect from client to server, and server to client + let (socket_c2s, socket_s2c) = MemorySocket::new_pair(); + + let mut random_data: [u8; 8192] = [0; 8192]; + OsRng.fill_bytes(&mut random_data); + + std::thread::Builder::new() + .name(format!( + "{:?}-{:?}-server", + provider.cipher_suites[0], provider.kx_groups[0] + )) + .spawn_scoped(s, { + let provider: CryptoProvider = provider.clone(); + move || { + let config = Arc::new(make_server_config(provider)); + let mut stream = socket_s2c; + let mut conn = rustls::ServerConnection::new(config.clone()) + .expect("failed to create server config"); + + let mut tls = rustls::Stream::new(&mut conn, &mut stream); + + { + let mut buf = [0; CLIENT_MAGIC.len()]; + tls.read_exact(&mut buf).unwrap(); + assert_eq!(&buf, CLIENT_MAGIC); + } + + tls.write_all(SERVER_MAGIC) + .expect("failed to write to client"); + tls.write_all(&random_data) + .expect("failed to write random data to client"); + tls.conn.send_close_notify(); + tls.flush().expect("failed to flush connection"); + } + }) + .unwrap(); + + std::thread::Builder::new() + .name(format!( + "{:?}-{:?}-client", + provider.cipher_suites[0], provider.kx_groups[0] + )) + .spawn_scoped(s, move || { + let mut sock = socket_c2s; + let server_name = "acme.com".try_into().expect("failed to get server name"); + let mut conn = rustls::ClientConnection::new( + Arc::new(make_client_config(provider)), + server_name, + ) + .expect("failed to create client config"); + let mut tls = rustls::Stream::new(&mut conn, &mut sock); + tls.write_all(CLIENT_MAGIC) + .expect("failed to write to server"); + + { + let mut buf = [0; SERVER_MAGIC.len()]; + tls.read_exact(&mut buf) + .expect("failed to read from server"); + assert_eq!(&buf, SERVER_MAGIC); + } + + { + let mut plaintext = Vec::new(); + tls.write_all(&random_data) + .expect("failed to write random data to server"); + tls.read_to_end(&mut plaintext) + .expect("failed to read from server"); + assert_eq!(plaintext, random_data); + } + }) + .unwrap(); + } + }); +} - // RustCrypto is not fips - assert!(!rustls_client_config.fips()); +fn generate_providers() -> impl Iterator { + let CryptoProvider { + cipher_suites, + kx_groups, + .. + } = rustcrypto_provider(); + + iproduct!(cipher_suites, kx_groups).map(|(cipher_suite, kx_group)| CryptoProvider { + cipher_suites: vec![cipher_suite], + kx_groups: vec![kx_group], + signature_verification_algorithms: verify::ALGORITHMS, + secure_random: &Provider, + key_provider: &Provider, + }) } + +mod mem_socket; diff --git a/tests/fake_cert_client_verifier.rs b/tests/fake_cert_client_verifier.rs deleted file mode 100644 index a8dc9cc..0000000 --- a/tests/fake_cert_client_verifier.rs +++ /dev/null @@ -1,71 +0,0 @@ -use rustls::DistinguishedName; -use rustls::Error; - -use rustls::SignatureScheme; - -use rustls::pki_types::CertificateDer; -use rustls::pki_types::UnixTime; -use rustls::DigitallySignedStruct; - -use rustls::client::danger::HandshakeSignatureValid; -use rustls::server::danger::ClientCertVerified; -use rustls::server::danger::ClientCertVerifier; - -#[derive(Debug)] -pub struct FakeClientCertVerifier { - pub dn: [DistinguishedName; 1], -} - -impl ClientCertVerifier for FakeClientCertVerifier { - fn root_hint_subjects(&self) -> &[DistinguishedName] { - &self.dn - } - fn verify_client_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _now: UnixTime, - ) -> Result { - Ok(ClientCertVerified::assertion()) - } - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - //SignatureScheme::Unknown(u16), - ] - } - fn offer_client_auth(&self) -> bool { - true - } - fn client_auth_mandatory(&self) -> bool { - false - } -} diff --git a/tests/fake_cert_server_resolver.rs b/tests/fake_cert_server_resolver.rs index 7028c8b..b029395 100644 --- a/tests/fake_cert_server_resolver.rs +++ b/tests/fake_cert_server_resolver.rs @@ -1,15 +1,202 @@ +use core::time::Duration; +use std::str::FromStr; use std::sync::Arc; -use rustls::server::ClientHello; - -use rustls::server::ResolvesServerCert; +use der::asn1::{GeneralizedTime, Ia5String}; +use der::Encode; +use itertools::iproduct; +use pkcs8::spki::{SignatureAlgorithmIdentifier, SubjectPublicKeyInfoOwned}; +use pkcs8::{EncodePrivateKey, EncodePublicKey}; +use pki_types::{CertificateDer, PrivateKeyDer}; +use rand_core::{OsRng, RngCore}; +use rsa::signature::Keypair; +use rustls::server::{ClientHello, ResolvesServerCert}; use rustls::sign::CertifiedKey; +use rustls::CipherSuite::{ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, +}; +use rustls_rustcrypto::sign::any_supported_type; +use sha2::Sha256; +use x509_cert::builder::{Builder, CertificateBuilder, Profile, RequestBuilder}; +use x509_cert::ext::pkix::name::GeneralName; +use x509_cert::ext::pkix::SubjectAltName; +use x509_cert::name::Name; +use x509_cert::serial_number::SerialNumber; +use x509_cert::time::{Time, Validity}; #[derive(Debug)] -pub struct FakeServerCertResolver; +pub struct FakeServerCertResolver { + rsa_cert_key: Arc, + ecdsa_cert_key: Arc, + rsa_root_cert: CertificateDer<'static>, + ecdsa_root_cert: CertificateDer<'static>, +} + +impl FakeServerCertResolver { + pub fn new() -> Self { + let (rsa_root_cert, rsa_root_key) = Self::generate_root_cert(|| { + // by running a binary search between 1024 bit and 2048 bit, 1034 bit is the first possible bit size after 1024 bit + rsa::pkcs1v15::SigningKey::::random(&mut OsRng, 1034).unwrap() + }); + let (ecdsa_root_cert, ecdsa_root_key) = + Self::generate_root_cert::<_, p256::ecdsa::DerSignature>(|| { + p256::ecdsa::SigningKey::random(&mut OsRng) + }); + + let (rsa_cert, rsa_key) = Self::generate_cert( + || { + // by running a binary search between 1024 bit and 2048 bit, 1034 bit is the first possible bit size after 1024 bit + rsa::pkcs1v15::SigningKey::::random(&mut OsRng, 1034).unwrap() + }, + rsa_root_key, + ); + let (ecdsa_cert, ecdsa_key) = Self::generate_cert::<_, _, p256::ecdsa::DerSignature>( + || p256::ecdsa::SigningKey::random(&mut OsRng), + ecdsa_root_key, + ); + + Self { + rsa_root_cert: rsa_root_cert.clone(), + ecdsa_root_cert: ecdsa_root_cert.clone(), + rsa_cert_key: Arc::new(CertifiedKey::new( + vec![rsa_cert, rsa_root_cert], + any_supported_type(&rsa_key).unwrap(), + )), + ecdsa_cert_key: Arc::new(CertifiedKey::new( + vec![ecdsa_cert, ecdsa_root_cert], + any_supported_type(&ecdsa_key).unwrap(), + )), + } + } + + pub fn rsa_root_cert(&self) -> CertificateDer<'static> { + self.rsa_root_cert.clone() + } + + pub fn ecdsa_root_cert(&self) -> CertificateDer<'static> { + self.ecdsa_root_cert.clone() + } + + fn generate_root_cert( + key_fn: impl Fn() -> Key, + ) -> (CertificateDer<'static>, Key) + where + Key: signature::Signer + + Keypair + + SignatureAlgorithmIdentifier + + EncodePrivateKey, + Signature: pkcs8::spki::SignatureBitStringEncoding, + ::VerifyingKey: EncodePublicKey, + { + let signing_key = key_fn(); + ( + CertificateBuilder::new( + Profile::Root, + SerialNumber::from(OsRng.next_u64()), + Validity { + not_before: Time::GeneralTime( + GeneralizedTime::from_unix_duration(Duration::ZERO).unwrap(), + ), + not_after: Time::INFINITY, + }, + Name::from_str("CN=ACME Corporation CA,O=ACME Corporation,C=US").unwrap(), + SubjectPublicKeyInfoOwned::from_key(signing_key.verifying_key()).unwrap(), + &signing_key, + ) + .unwrap() + .build::() + .unwrap() + .to_der() + .unwrap() + .into(), + signing_key, + ) + } + fn generate_cert( + key_fn: impl Fn() -> Key, + ca_key: CaKey, + ) -> (CertificateDer<'static>, PrivateKeyDer<'static>) + where + Key: signature::Signer + + Keypair + + SignatureAlgorithmIdentifier + + EncodePrivateKey, + + CaKey: signature::Signer + + Keypair + + SignatureAlgorithmIdentifier + + EncodePrivateKey, + Signature: pkcs8::spki::SignatureBitStringEncoding, + ::VerifyingKey: EncodePublicKey, + ::VerifyingKey: EncodePublicKey, + { + let signing_key = key_fn(); + + let request = RequestBuilder::new(Name::from_str("CN=acme.com").unwrap(), &signing_key) + .unwrap() + .build() + .unwrap(); + + let mut builder = CertificateBuilder::new( + Profile::Leaf { + issuer: Name::from_str("CN=ACME Corporation CA,O=ACME Corporation,C=US").unwrap(), + enable_key_agreement: true, + enable_key_encipherment: true, + }, + SerialNumber::from(OsRng.next_u64()), + Validity { + not_before: Time::GeneralTime( + GeneralizedTime::from_unix_duration(Duration::ZERO).unwrap(), + ), + not_after: Time::INFINITY, + }, + request.info.subject, + request.info.public_key, + &ca_key, + ) + .unwrap(); + builder + .add_extension(&SubjectAltName(vec![GeneralName::DnsName( + Ia5String::new(b"acme.com").unwrap(), + )])) + .unwrap(); + ( + builder + .build::() + .unwrap() + .to_der() + .unwrap() + .into(), + PrivateKeyDer::Pkcs8( + signing_key + .to_pkcs8_der() + .unwrap() + .as_bytes() + .to_vec() + .into(), + ), + ) + } +} impl ResolvesServerCert for FakeServerCertResolver { - fn resolve(&self, _client_hello: ClientHello<'_>) -> Option> { - None + fn resolve(&self, hello: ClientHello<'_>) -> Option> { + Some( + if iproduct!( + [ + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + ], + hello.cipher_suites() + ) + .any(|(a, &b)| a == b) + { + self.rsa_cert_key.clone() + } else { + self.ecdsa_cert_key.clone() + }, + ) } } diff --git a/tests/fake_cert_server_verifier.rs b/tests/fake_cert_server_verifier.rs deleted file mode 100644 index 2786058..0000000 --- a/tests/fake_cert_server_verifier.rs +++ /dev/null @@ -1,59 +0,0 @@ -use rustls::client::danger::HandshakeSignatureValid; -use rustls::client::danger::ServerCertVerified; -use rustls::client::danger::ServerCertVerifier; -use rustls::pki_types::CertificateDer; -use rustls::pki_types::ServerName; -use rustls::pki_types::UnixTime; -use rustls::DigitallySignedStruct; -use rustls::Error; -use rustls::SignatureScheme; - -#[derive(Debug)] -pub struct FakeServerCertVerifier; - -impl ServerCertVerifier for FakeServerCertVerifier { - fn verify_server_cert( - &self, - _end_entity: &CertificateDer<'_>, - _intermediates: &[CertificateDer<'_>], - _server_name: &ServerName<'_>, - _ocsp_response: &[u8], - _now: UnixTime, - ) -> Result { - Ok(ServerCertVerified::assertion()) - } - fn verify_tls12_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn verify_tls13_signature( - &self, - _message: &[u8], - _cert: &CertificateDer<'_>, - _dss: &DigitallySignedStruct, - ) -> Result { - Ok(HandshakeSignatureValid::assertion()) - } - fn supported_verify_schemes(&self) -> Vec { - vec![ - SignatureScheme::RSA_PKCS1_SHA1, - SignatureScheme::ECDSA_SHA1_Legacy, - SignatureScheme::RSA_PKCS1_SHA256, - SignatureScheme::ECDSA_NISTP256_SHA256, - SignatureScheme::RSA_PKCS1_SHA384, - SignatureScheme::ECDSA_NISTP384_SHA384, - SignatureScheme::RSA_PKCS1_SHA512, - SignatureScheme::ECDSA_NISTP521_SHA512, - SignatureScheme::RSA_PSS_SHA256, - SignatureScheme::RSA_PSS_SHA384, - SignatureScheme::RSA_PSS_SHA512, - SignatureScheme::ED25519, - SignatureScheme::ED448, - //SignatureScheme::Unknown(u16), - ] - } -} diff --git a/tests/fake_time.rs b/tests/fake_time.rs index 83dc3fa..12d82e9 100644 --- a/tests/fake_time.rs +++ b/tests/fake_time.rs @@ -1,3 +1,5 @@ +use core::time::Duration; + use rustls::pki_types::UnixTime; use rustls::time_provider::TimeProvider; @@ -6,6 +8,6 @@ pub struct FakeTime; impl TimeProvider for FakeTime { fn current_time(&self) -> Option { - None + Some(UnixTime::since_unix_epoch(Duration::ZERO)) } } diff --git a/tests/mem_socket.rs b/tests/mem_socket.rs new file mode 100644 index 0000000..a44182f --- /dev/null +++ b/tests/mem_socket.rs @@ -0,0 +1,103 @@ +use std::{ + io::{self, ErrorKind, Read, Write}, + sync::mpsc::{channel, Receiver, Sender}, +}; + +use bytes::{Buf, Bytes, BytesMut}; + +// The code is derived from: https://github.com/bmwill/memory-socket/blob/74110b18318c261e86d08aa53a7abe3e2a881538/src/lib.rs#L271-L405 +pub struct MemorySocket { + incoming: Receiver, + outgoing: Sender, + write_buffer: BytesMut, + current_buffer: Option, + seen_eof: bool, +} + +impl MemorySocket { + fn new(incoming: Receiver, outgoing: Sender) -> Self { + Self { + incoming, + outgoing, + write_buffer: BytesMut::new(), + current_buffer: None, + seen_eof: false, + } + } + + pub fn new_pair() -> (Self, Self) { + let (a_tx, a_rx) = channel(); + let (b_tx, b_rx) = channel(); + let a = Self::new(a_rx, b_tx); + let b = Self::new(b_rx, a_tx); + + (a, b) + } +} + +impl Read for MemorySocket { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let mut bytes_read = 0; + + loop { + // If we've already filled up the buffer then we can return + if bytes_read == buf.len() { + return Ok(bytes_read); + } + + match self.current_buffer { + // We still have data to copy to `buf` + Some(ref mut current_buffer) if current_buffer.has_remaining() => { + let bytes_to_read = + core::cmp::min(buf.len() - bytes_read, current_buffer.remaining()); + debug_assert!(bytes_to_read > 0); + + current_buffer + .take(bytes_to_read) + .copy_to_slice(&mut buf[bytes_read..(bytes_read + bytes_to_read)]); + bytes_read += bytes_to_read; + } + + // Either we've exhausted our current buffer or we don't have one + _ => { + // If we've read anything up to this point return the bytes read + if bytes_read > 0 { + return Ok(bytes_read); + } + + self.current_buffer = match self.incoming.recv() { + Ok(buf) => Some(buf), + + // The remote side hung up, if this is the first time we've seen EOF then + // we should return `Ok(0)` otherwise an UnexpectedEof Error + Err(_) => { + if self.seen_eof { + return Err(ErrorKind::UnexpectedEof.into()); + } else { + self.seen_eof = true; + return Ok(0); + } + } + } + } + } + } + } +} + +impl Write for MemorySocket { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.write_buffer.extend_from_slice(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + if !self.write_buffer.is_empty() { + self.outgoing + .send(self.write_buffer.split().freeze()) + .map_err(|_| ErrorKind::BrokenPipe.into()) + } else { + Ok(()) + } + } +} From 634e2124168fb7fd5603594dd3986ce5cc558a04 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 05:04:47 +0800 Subject: [PATCH 18/38] fix getrandom by fixating feature when building for wasm --- Cargo.lock | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 18 +++++++++----- 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22b1042..25749b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,6 +64,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -352,8 +358,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -413,6 +421,16 @@ dependencies = [ "either", ] +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -971,6 +989,60 @@ 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.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index a5ae936..a70d192 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ categories = ["cryptography", "no-std"] keywords = ["rustls", "tls"] edition = "2021" rust-version = "1.75" -resolver = "1" # Hack to enable the `custom` feature of `getrandom` +resolver = "2" # Ensure all dependencies + feats are mapped to crate features for correct usage # default features often have std breaking no_std and potentially other unwanted @@ -54,21 +54,27 @@ rand_core = { version = "0.6.4", default-features = false, features = [ rustls = { version = "0.23.19", default-features = false } webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false, optional = true } +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { version = "0.2", features = [ + "js" +] } + [dev-dependencies] +bytes = { version = "1.9.0", default-features = false } # workaround to build on no_std targets getrandom = { version = "0.2", features = [ - "custom", + "custom" ] } itertools = "0.13.0" +rsa = { version = "0.9.7", default-features = false, features = [ + "sha2", +] } +rustls = { version = "0.23.19", default-features = false, features = ["std"] } sha2 = { version = "0.10.8", default-features = false, features = ["oid"] } x509-cert = { version = "0.2.5", default-features = false, features = [ "builder", "pem" ] } -rsa = { version = "0.9.7", default-features = false, features = [ - "sha2", -] } -bytes = { version = "1.9.0", default-features = false } [features] default = ["std", "tls12", "zeroize", "full"] From 9d44f14f84dbd388bec7b80baa07de1240355d89 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 05:10:12 +0800 Subject: [PATCH 19/38] fix getrandom problem with unsupported target --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a70d192..4676814 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,9 @@ sha2 = { version = "0.10.8", default-features = false } signature = { version = "2.2.0", default-features = false, optional = true } x25519-dalek = { version = "2", default-features = false, optional = true } +getrandom = { version = "0.2", default-features = false, features = [ + "custom" +] } paste = { version = "1.0.15", default-features = false } pki-types = { package = "rustls-pki-types", version = "1.10.0", default-features = false } rand_core = { version = "0.6.4", default-features = false, features = [ @@ -61,10 +64,6 @@ getrandom = { version = "0.2", features = [ [dev-dependencies] bytes = { version = "1.9.0", default-features = false } -# workaround to build on no_std targets -getrandom = { version = "0.2", features = [ - "custom" -] } itertools = "0.13.0" rsa = { version = "0.9.7", default-features = false, features = [ "sha2", @@ -101,6 +100,7 @@ std = [ "rustls/std", "ed25519-dalek?/std", "pkcs1?/std", + "getrandom/std" ] alloc = ["webpki?/alloc", "ecdsa?/alloc", "signature?/alloc", "ccm?/alloc"] zeroize = ["ed25519-dalek?/zeroize", "x25519-dalek?/zeroize"] From f2eba454fa53c040f0fca23cf94c00b6be581a5e Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:05:00 +0800 Subject: [PATCH 20/38] enable ccm for openssl test suite --- validation/local_ping_pong_openssl/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/validation/local_ping_pong_openssl/src/lib.rs b/validation/local_ping_pong_openssl/src/lib.rs index e4b659d..ff46fb5 100644 --- a/validation/local_ping_pong_openssl/src/lib.rs +++ b/validation/local_ping_pong_openssl/src/lib.rs @@ -74,7 +74,6 @@ mod test { } #[test] - #[should_panic] // no_shared_cipher fn vs_openssl_as_client_ccm_sha256() { let cipher_suites = OpenSslCipherSuites { TLS_AES_128_GCM_SHA256: false, @@ -87,7 +86,6 @@ mod test { } #[test] - #[should_panic] // no_shared_cipher fn vs_openssl_as_client_ccm8_sha256() { let cipher_suites = OpenSslCipherSuites { TLS_AES_128_GCM_SHA256: false, From bfac1b03bf1ea607cf384deef7787f6a607deeb3 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:15:47 +0800 Subject: [PATCH 21/38] fix length for Aes128Ccm8 --- src/tls12/aead/ccm.rs | 2 +- src/tls12/aead/gcm.rs | 2 +- src/tls13/aead/ccm.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tls12/aead/ccm.rs b/src/tls12/aead/ccm.rs index 3964336..a7db7f2 100644 --- a/src/tls12/aead/ccm.rs +++ b/src/tls12/aead/ccm.rs @@ -42,7 +42,7 @@ macro_rules! impl_ccm { KeyBlockShape { enc_key_len: $aead::key_size(), fixed_iv_len: 4, - explicit_nonce_len: 8, + explicit_nonce_len: EXPLICIT_NONCE_LEN, } } diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs index a9ac813..eff79ae 100644 --- a/src/tls12/aead/gcm.rs +++ b/src/tls12/aead/gcm.rs @@ -43,7 +43,7 @@ macro_rules! impl_gcm { KeyBlockShape { enc_key_len: $aead::key_size(), fixed_iv_len: 4, - explicit_nonce_len: 8, + explicit_nonce_len: EXPLICIT_NONCE_LEN, } } diff --git a/src/tls13/aead/ccm.rs b/src/tls13/aead/ccm.rs index 7a23e14..f85f452 100644 --- a/src/tls13/aead/ccm.rs +++ b/src/tls13/aead/ccm.rs @@ -88,4 +88,4 @@ macro_rules! impl_ccm { } impl_ccm! {Aes128Ccm, crate::aead::aes::Aes128Ccm, 16} -impl_ccm! {Aes128Ccm8, crate::aead::aes::Aes128Ccm8, 16} +impl_ccm! {Aes128Ccm8, crate::aead::aes::Aes128Ccm8, 8} From edd6c4e79cf0e92a2a4f0f0ecce4b43316db14e0 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:24:50 +0800 Subject: [PATCH 22/38] fix wrong aead algorithm for TLS13_AES_128_CCM_8_SHA256 --- src/tls13/suites/aes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs index d6f8e89..48b3079 100644 --- a/src/tls13/suites/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,7 +1,7 @@ #[cfg(feature = "aes-ccm")] use crate::aead::Aes128Ccm; #[cfg(feature = "aes-gcm")] -use crate::aead::{Aes128Gcm, Aes256Gcm}; +use crate::aead::{Aes128Gcm, Aes256Gcm, Aes128Ccm8}; use crate::const_concat_slices; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; @@ -55,7 +55,7 @@ pub const TLS13_AES_128_CCM_8_SHA256: SupportedCipherSuite = confidentiality_limit: u64::MAX, }, hkdf_provider: &HkdfUsingHmac(hmac::SHA256), - aead_alg: &Aes128Ccm, + aead_alg: &Aes128Ccm8, quic: None, }); From 5c11f64d754e7f61b06ed068b91c1bb0f8b021eb Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:25:06 +0800 Subject: [PATCH 23/38] update Cargo.lock for OpenSSL test --- validation/local_ping_pong_openssl/Cargo.lock | 132 ++++++++++++++++-- 1 file changed, 120 insertions(+), 12 deletions(-) diff --git a/validation/local_ping_pong_openssl/Cargo.lock b/validation/local_ping_pong_openssl/Cargo.lock index d6eebf0..bed8abb 100644 --- a/validation/local_ping_pong_openssl/Cargo.lock +++ b/validation/local_ping_pong_openssl/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "aead" @@ -70,6 +70,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + [[package]] name = "byteorder" version = "1.5.0" @@ -82,6 +88,18 @@ version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +[[package]] +name = "ccm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae3c82e4355234767756212c570e29833699ab63e6ffd161887314cc5b43847" +dependencies = [ + "aead", + "cipher", + "ctr", + "subtle", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -328,8 +346,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -380,6 +400,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "js-sys" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -411,6 +441,12 @@ dependencies = [ "rustls-rustcrypto", ] +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -532,11 +568,24 @@ dependencies = [ "sha2", ] +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem-rfc7468" @@ -703,9 +752,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -733,9 +782,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.5" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabcee0551bd1aa3e18e5adbf2c0544722014b899adb31bd186ec638d3da97e" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "once_cell", "rustls-pki-types", @@ -746,26 +795,31 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-rustcrypto" -version = "0.1.0" +version = "0.0.2-alpha" dependencies = [ "aead", + "aes", "aes-gcm", + "ccm", "chacha20poly1305", "crypto-common", "der", "digest", "ecdsa", "ed25519-dalek", + "getrandom", "hmac", "p256", "p384", + "p521", "paste", + "pkcs1", "pkcs8", "rand_core", "rsa", @@ -780,9 +834,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -941,6 +995,60 @@ 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.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" + [[package]] name = "windows-sys" version = "0.52.0" From 7b4a773783a3f4092d79d874d1bbfbbedfffd02e Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:28:17 +0800 Subject: [PATCH 24/38] fixup! fix wrong aead algorithm for TLS13_AES_128_CCM_8_SHA256 --- src/tls13/suites/aes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs index 48b3079..fc02cd7 100644 --- a/src/tls13/suites/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,7 +1,7 @@ #[cfg(feature = "aes-ccm")] use crate::aead::Aes128Ccm; #[cfg(feature = "aes-gcm")] -use crate::aead::{Aes128Gcm, Aes256Gcm, Aes128Ccm8}; +use crate::aead::{Aes128Ccm8, Aes128Gcm, Aes256Gcm}; use crate::const_concat_slices; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; From a625d9ca157d045ac1fea12e6d4ec10285e85eb9 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 10:57:08 +0800 Subject: [PATCH 25/38] update readme to expand the supported cipher suites --- README.md | 68 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index ec27143..61208ba 100644 --- a/README.md +++ b/README.md @@ -17,21 +17,52 @@ Note that RustCrypto performance is generally inferior than ring, but in exchang ## Supported Cipher Suites -- TLS_ECDHE_ECDSA_WITH_AES_128_CCM -- TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 -- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_ECDSA_WITH_AES_256_CCM -- TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 -- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 -- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 -- TLS13_AES_128_CCM_SHA256 -- TLS13_AES_128_CCM_8_SHA256 -- TLS13_AES_128_GCM_SHA256 -- TLS13_AES_256_GCM_SHA384 -- TLS13_CHACHA20_POLY1305_SHA256 +Only the recommended ([TLS1.2](https://ciphersuite.info/cs/?security=recommended&singlepage=true&tls=tls12), [TLS1.3](https://ciphersuite.info/cs/?security=recommended&singlepage=true&tls=tls13)) and secure ([TLS1.2](https://ciphersuite.info/cs/?security=secure&singlepage=true&tls=tls12), [TLS1.3](https://ciphersuite.info/cs/?security=secure&singlepage=true&tls=tls13)) suites will be chosen + +For TLS 1.3: + +- [x] (Recommended) TLS_AES_128_GCM_SHA256 +- [x] (Recommended) TLS_AES_256_GCM_SHA384 +- [x] (Recommended) TLS_CHACHA20_POLY1305_SHA256 +- [x] (Secure) TLS_AES_128_CCM_8_SHA256 +- [x] (Secure) TLS_AES_128_CCM_SHA256 + +For TLS 1.2: + +- [ ] (Recommended) TLS_ECCPWD_WITH_AES_128_GCM_SHA256 +- [ ] (Recommended) TLS_ECCPWD_WITH_AES_256_GCM_SHA384 +- [x] (Recommended) TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +- [x] (Recommended) TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +- [ ] (Recommended) TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 +- [ ] (Recommended) TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 +- [ ] (Recommended) TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +- [ ] (Recommended) TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +- [x] (Recommended) TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +- [ ] (Recommended) TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 +- [ ] (Recommended) TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 +- [ ] (Recommended) TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 +- [ ] (Secure) TLS_ECCPWD_WITH_AES_128_CCM_SHA256 +- [ ] (Secure) TLS_ECCPWD_WITH_AES_256_CCM_SHA384 +- [x] (Secure) TLS_ECDHE_ECDSA_WITH_AES_128_CCM +- [x] (Secure) TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +- [x] (Secure) TLS_ECDHE_ECDSA_WITH_AES_256_CCM +- [x] (Secure) TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +- [ ] (Secure) TLS_ECDHE_PSK_WITH_AES_128_CCM_8_SHA256 +- [ ] (Secure) TLS_ECDHE_PSK_WITH_AES_128_CCM_SHA256 +- [x] (Secure) TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +- [x] (Secure) TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +- [ ] (Secure) TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 +- [ ] (Secure) TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 +- [ ] (Secure) TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +- [ ] (Secure) TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +- [x] (Secure) TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + +\* PSK support is currently blocked due to [it not currently being supported in Rustls as of 2024](https://github.com/rustls/rustls/issues/174). +If you want this feature, consider financially supporting the Rustls project by being a funder in [Prossimo](https://www.memorysafety.org/initiative/rustls/) + +\* While both [CAMELLIA](https://github.com/RustCrypto/block-ciphers/tree/master/camellia) and [ARIA](https://github.com/RustCrypto/block-ciphers/tree/master/aria) block cipher are in RustCrypto, they are still in 0.1.0 and not currently viable for production use + +\* As RustCrypto do not have a [Dragonfly](https://www.ietf.org/proceedings/83/slides/slides-83-cfrg-0.pdf) implementation, nor it is planned yet, [RFC8492](https://datatracker.ietf.org/doc/html/rfc8492) and thus ECCPWD family of cipher suites would be hard to implement for the known future ## License @@ -50,8 +81,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. -[//]: # (badges) - +[//]: # "badges" [crate-image]: https://img.shields.io/crates/v/rustls-rustcrypto [crate-link]: https://crates.io/crates/rustls-rustcrypto [docs-image]: https://docs.rs/rustls-rustcrypto/badge.svg @@ -62,8 +92,6 @@ dual licensed as above, without any additional terms or conditions. [rustc-image]: https://img.shields.io/badge/rustc-1.75+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/434751-TLS - -[//]: # (links) - +[//]: # "links" [RustCrypto]: https://github.com/RustCrypto/ [rustls]: https://github.com/rustls/rustls/ From b8598daee304d4a750fa60088a4b6955fbb4e961 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Sun, 8 Dec 2024 11:12:34 +0800 Subject: [PATCH 26/38] update readme to remove production warning --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 61208ba..9f631e4 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ [RustCrypto]-based provider implementation for version 0.23 of [rustls], maintained by the RustCrypto organization. -## ⚠️USE THIS AT YOUR OWN RISK! DO NOT USE THIS IN PRODUCTION⚠️ +## ⚠️CAUTION⚠️ -Not only that this is incomplete that only few selected TLS suites implemented (it should be well enough to cover 70% of the usage), but the elephant in the room is that neither did rustls nor RustCrypto packages were formally verified and certified with FIPS compliance. +While a basic test suite that tests all available cipher suites and key exchange combinations passes, and it is cross-validated with OpenSSL, and is also running in ESP32 for experimental (but near-production) secure communication, please be reminded that (as of 2024) not all RustCrypto packages are formally verified and optimized for specific architecture, and none of the packages in RustCrypto are certified with FIPS compliance. Note that RustCrypto performance is generally inferior than ring, but in exchange you got a pure Rust implementation that theoretically compiles everywhere Rust was ported to. In our case, we need to have `std` but foundational support for future `no_std` expansion is already here. From 3d554e7b0107a85f36b33b5f558d36227cd54dbb Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:44:49 +0800 Subject: [PATCH 27/38] remove aes feature from aes-gcm and manually define the type instead --- Cargo.lock | 1 - Cargo.toml | 12 ++++++------ src/aead.rs | 19 ++++--------------- src/aead/aes.rs | 6 ++++-- src/aead/ccm.rs | 11 +++++++++++ src/aead/gcm.rs | 5 +++++ src/tls12/aead.rs | 4 ++-- src/tls12/aead/ccm.rs | 2 +- src/tls12/aead/gcm.rs | 2 +- src/tls12/suites/ecdsa.rs | 4 ++-- src/tls12/suites/rsa.rs | 2 +- src/tls13/aead.rs | 4 ++-- src/tls13/aead/ccm.rs | 3 ++- src/tls13/aead/gcm.rs | 3 ++- src/tls13/suites/aes.rs | 4 ++-- 15 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 src/aead/ccm.rs create mode 100644 src/aead/gcm.rs diff --git a/Cargo.lock b/Cargo.lock index 25749b2..70615ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,7 +30,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" dependencies = [ "aead", - "aes", "cipher", "ctr", "ghash", diff --git a/Cargo.toml b/Cargo.toml index 4676814..2bc751b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,9 +20,7 @@ resolver = "2" [dependencies] aes = { version = "0.8.4", default-features = false, optional = true } aead = { version = "0.5.2", default-features = false, optional = true } -aes-gcm = { version = "0.10.3", default-features = false, features = [ - "aes", -], optional = true } +aes-gcm = { version = "0.10.3", default-features = false, optional = true } ccm = { version = "0.5.0", optional = true, default-features = false } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } @@ -136,8 +134,8 @@ rsa-pss = ["rsa"] rsa-full = ["rsa-pkcs1", "rsa-pss"] aead = ["dep:aead"] -aes-gcm = ["aes", "dep:aes-gcm", "aead"] -aes-ccm = ["aes", "dep:ccm", "aead"] +aes-gcm = ["dep:aes-gcm", "aes", "gcm", "aead"] +aes-ccm = ["aes", "ccm", "aead"] chacha20poly1305 = ["dep:chacha20poly1305", "aead"] aead-full = ["aes-gcm", "aes-ccm", "chacha20poly1305"] @@ -165,4 +163,6 @@ pkcs8 = [ signature = ["dep:signature"] rand = ["dep:rand_core", "signature?/rand_core"] -aes = ["dep:aes"] \ No newline at end of file +aes = ["dep:aes"] +ccm = ["dep:ccm"] +gcm = [] \ No newline at end of file diff --git a/src/aead.rs b/src/aead.rs index ea6ed8f..a5ad58f 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -6,23 +6,12 @@ pub const CHACHAPOLY1305_OVERHEAD: usize = 16; #[cfg(feature = "chacha20poly1305")] pub struct ChaCha20Poly1305; -#[cfg(feature = "aes-gcm")] -pub struct Aes128Gcm; -#[cfg(feature = "aes-gcm")] -pub struct Aes256Gcm; +#[cfg(feature = "gcm")] +pub mod gcm; -#[cfg(feature = "aes-ccm")] -pub struct Aes128Ccm; - -#[cfg(feature = "aes-ccm")] -pub struct Aes256Ccm; - -#[cfg(feature = "aes-ccm")] -pub struct Aes128Ccm8; - -#[cfg(feature = "aes-ccm")] -pub struct Aes256Ccm8; +#[cfg(feature = "ccm")] +pub mod ccm; pub(crate) struct EncryptBufferAdapter<'a>(pub(crate) &'a mut PrefixedPayload); diff --git a/src/aead/aes.rs b/src/aead/aes.rs index 482d6ea..0272b93 100644 --- a/src/aead/aes.rs +++ b/src/aead/aes.rs @@ -1,5 +1,7 @@ #[cfg(feature = "aes-ccm")] use aes::{Aes128, Aes256}; +#[cfg(feature = "aes-gcm")] +use aes_gcm::AesGcm; #[cfg(feature = "aes-ccm")] use ccm::{ consts::{U12, U16, U8}, @@ -30,7 +32,7 @@ pub type Aes128Ccm8 = Ccm; pub type Aes256Ccm8 = Ccm; #[cfg(feature = "aes-gcm")] -pub type Aes128Gcm = aes_gcm::Aes128Gcm; +pub type Aes128Gcm = AesGcm; #[cfg(feature = "aes-gcm")] -pub type Aes256Gcm = aes_gcm::Aes256Gcm; +pub type Aes256Gcm = AesGcm; diff --git a/src/aead/ccm.rs b/src/aead/ccm.rs new file mode 100644 index 0000000..caa9fe2 --- /dev/null +++ b/src/aead/ccm.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "aes-ccm")] +pub struct Aes128Ccm; + +#[cfg(feature = "aes-ccm")] +pub struct Aes256Ccm; + +#[cfg(feature = "aes-ccm")] +pub struct Aes128Ccm8; + +#[cfg(feature = "aes-ccm")] +pub struct Aes256Ccm8; diff --git a/src/aead/gcm.rs b/src/aead/gcm.rs new file mode 100644 index 0000000..5dbdfbf --- /dev/null +++ b/src/aead/gcm.rs @@ -0,0 +1,5 @@ +#[cfg(feature = "aes-gcm")] +pub struct Aes128Gcm; + +#[cfg(feature = "aes-gcm")] +pub struct Aes256Gcm; diff --git a/src/tls12/aead.rs b/src/tls12/aead.rs index d9985ee..f34c173 100644 --- a/src/tls12/aead.rs +++ b/src/tls12/aead.rs @@ -1,8 +1,8 @@ #[cfg(feature = "chacha20poly1305")] pub mod chacha20; -#[cfg(feature = "aes-gcm")] +#[cfg(feature = "gcm")] pub mod gcm; -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] pub mod ccm; diff --git a/src/tls12/aead/ccm.rs b/src/tls12/aead/ccm.rs index a7db7f2..5fcccfd 100644 --- a/src/tls12/aead/ccm.rs +++ b/src/tls12/aead/ccm.rs @@ -1,7 +1,7 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; -use crate::aead::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; +use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; use ::aead::{AeadCore, AeadInPlace}; use crypto_common::typenum::Unsigned; use crypto_common::{KeyInit, KeySizeUser}; diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs index eff79ae..4073f26 100644 --- a/src/tls12/aead/gcm.rs +++ b/src/tls12/aead/gcm.rs @@ -1,7 +1,7 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; -use crate::aead::{Aes128Gcm, Aes256Gcm}; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; use ::aead::{AeadCore, AeadInPlace}; use crypto_common::typenum::Unsigned; use crypto_common::{KeyInit, KeySizeUser}; diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs index 0279f77..7f5a61e 100644 --- a/src/tls12/suites/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -10,10 +10,10 @@ use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorith use rustls::{CipherSuite, Tls12CipherSuite}; #[cfg(feature = "aes-gcm")] -use crate::aead::{Aes128Gcm, Aes256Gcm}; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; #[cfg(feature = "aes-ccm")] -use crate::aead::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; +use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; diff --git a/src/tls12/suites/rsa.rs b/src/tls12/suites/rsa.rs index d395dba..b94017a 100644 --- a/src/tls12/suites/rsa.rs +++ b/src/tls12/suites/rsa.rs @@ -10,7 +10,7 @@ use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorith use rustls::{CipherSuite, Tls12CipherSuite}; #[cfg(feature = "aes-gcm")] -use crate::aead::{Aes128Gcm, Aes256Gcm}; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; diff --git a/src/tls13/aead.rs b/src/tls13/aead.rs index d9985ee..f34c173 100644 --- a/src/tls13/aead.rs +++ b/src/tls13/aead.rs @@ -1,8 +1,8 @@ #[cfg(feature = "chacha20poly1305")] pub mod chacha20; -#[cfg(feature = "aes-gcm")] +#[cfg(feature = "gcm")] pub mod gcm; -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] pub mod ccm; diff --git a/src/tls13/aead/ccm.rs b/src/tls13/aead/ccm.rs index f85f452..0ca62dd 100644 --- a/src/tls13/aead/ccm.rs +++ b/src/tls13/aead/ccm.rs @@ -1,7 +1,8 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; -use crate::aead::{Aes128Ccm, Aes128Ccm8, DecryptBufferAdapter, EncryptBufferAdapter}; +use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8}; +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; use aead::AeadInPlace; use crypto_common::{KeyInit, KeySizeUser}; use paste::paste; diff --git a/src/tls13/aead/gcm.rs b/src/tls13/aead/gcm.rs index 04dc7d1..ccc7a48 100644 --- a/src/tls13/aead/gcm.rs +++ b/src/tls13/aead/gcm.rs @@ -1,7 +1,8 @@ #[cfg(feature = "alloc")] use alloc::boxed::Box; -use crate::aead::{Aes128Gcm, Aes256Gcm, DecryptBufferAdapter, EncryptBufferAdapter}; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +use crate::aead::{DecryptBufferAdapter, EncryptBufferAdapter}; use aead::AeadInPlace; use crypto_common::{KeyInit, KeySizeUser}; use paste::paste; diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs index fc02cd7..87a7c84 100644 --- a/src/tls13/suites/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,7 +1,7 @@ #[cfg(feature = "aes-ccm")] -use crate::aead::Aes128Ccm; +use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8}; #[cfg(feature = "aes-gcm")] -use crate::aead::{Aes128Ccm8, Aes128Gcm, Aes256Gcm}; +use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; use crate::const_concat_slices; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; From 3f8520d4369a57fe6c60b3593f919317d71deb2e Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:46:16 +0800 Subject: [PATCH 28/38] add a static assertion to make sure at least one suite is available --- src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 7020455..7067345 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -118,3 +118,8 @@ pub mod verify; #[cfg(feature = "tls12")] pub mod tls12; pub mod tls13; + +const _: () = assert!( + ALL_CIPHER_SUITES.len() != 0, + "At least one cipher suite should be enabled" +); From 74fabd893f2f51a3728adcfc19c2f7c67add1ad6 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:46:54 +0800 Subject: [PATCH 29/38] use spki independently --- Cargo.lock | 1 + Cargo.toml | 3 ++- tests/fake_cert_server_resolver.rs | 24 +++++++----------------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 70615ab..a5f9f73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -795,6 +795,7 @@ dependencies = [ "sec1", "sha2", "signature", + "spki", "x25519-dalek", "x509-cert", ] diff --git a/Cargo.toml b/Cargo.toml index 2bc751b..8e2b7b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,7 @@ rsa = { version = "0.9.7", default-features = false, features = [ ] } rustls = { version = "0.23.19", default-features = false, features = ["std"] } sha2 = { version = "0.10.8", default-features = false, features = ["oid"] } +spki = { version = "0.7.3", features = ["alloc"] } x509-cert = { version = "0.2.5", default-features = false, features = [ "builder", "pem" @@ -129,7 +130,7 @@ kx-p521 = ["p521", "p521/ecdh", "kx"] kx-full = ["kx-x25519", "kx-p256", "kx-p384", "kx-p521"] rsa = ["dep:rsa", "rsa/sha2", "verify", "signature", "pkcs1"] -rsa-pkcs1 = ["rsa"] +rsa-pkcs1 = ["rsa", "pkcs1"] rsa-pss = ["rsa"] rsa-full = ["rsa-pkcs1", "rsa-pss"] diff --git a/tests/fake_cert_server_resolver.rs b/tests/fake_cert_server_resolver.rs index b029395..c826aed 100644 --- a/tests/fake_cert_server_resolver.rs +++ b/tests/fake_cert_server_resolver.rs @@ -5,11 +5,9 @@ use std::sync::Arc; use der::asn1::{GeneralizedTime, Ia5String}; use der::Encode; use itertools::iproduct; -use pkcs8::spki::{SignatureAlgorithmIdentifier, SubjectPublicKeyInfoOwned}; use pkcs8::{EncodePrivateKey, EncodePublicKey}; use pki_types::{CertificateDer, PrivateKeyDer}; use rand_core::{OsRng, RngCore}; -use rsa::signature::Keypair; use rustls::server::{ClientHello, ResolvesServerCert}; use rustls::sign::CertifiedKey; use rustls::CipherSuite::{ @@ -18,6 +16,8 @@ use rustls::CipherSuite::{ }; use rustls_rustcrypto::sign::any_supported_type; use sha2::Sha256; +use signature::{Keypair, Signer}; +use spki::{SignatureAlgorithmIdentifier, SignatureBitStringEncoding, SubjectPublicKeyInfoOwned}; use x509_cert::builder::{Builder, CertificateBuilder, Profile, RequestBuilder}; use x509_cert::ext::pkix::name::GeneralName; use x509_cert::ext::pkix::SubjectAltName; @@ -82,11 +82,8 @@ impl FakeServerCertResolver { key_fn: impl Fn() -> Key, ) -> (CertificateDer<'static>, Key) where - Key: signature::Signer - + Keypair - + SignatureAlgorithmIdentifier - + EncodePrivateKey, - Signature: pkcs8::spki::SignatureBitStringEncoding, + Key: Signer + Keypair + SignatureAlgorithmIdentifier + EncodePrivateKey, + Signature: SignatureBitStringEncoding, ::VerifyingKey: EncodePublicKey, { let signing_key = key_fn(); @@ -118,16 +115,9 @@ impl FakeServerCertResolver { ca_key: CaKey, ) -> (CertificateDer<'static>, PrivateKeyDer<'static>) where - Key: signature::Signer - + Keypair - + SignatureAlgorithmIdentifier - + EncodePrivateKey, - - CaKey: signature::Signer - + Keypair - + SignatureAlgorithmIdentifier - + EncodePrivateKey, - Signature: pkcs8::spki::SignatureBitStringEncoding, + Key: Signer + Keypair + SignatureAlgorithmIdentifier + EncodePrivateKey, + CaKey: Signer + Keypair + SignatureAlgorithmIdentifier + EncodePrivateKey, + Signature: SignatureBitStringEncoding, ::VerifyingKey: EncodePublicKey, ::VerifyingKey: EncodePublicKey, { From eb1f2c35352fde4ba35a94239d763a9030d7f87a Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Mon, 9 Dec 2024 21:56:35 +0800 Subject: [PATCH 30/38] remove std and alloc implied feature to bare minimum instead --- Cargo.toml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8e2b7b8..525bc7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,21 +88,10 @@ format = ["pem", "pkcs1", "pkcs8", "sec1"] logging = ["rustls/logging"] tls12 = ["rustls/tls12"] -# Only enable feature in upstream if there is an overall effect e.g. aead/alloc in-place -# zeroize is another typical that can be turned off - -# TODO: go through all of these that what gets exposed re: std error type -std = [ - "alloc", - "webpki?/std", - "pki-types/std", - "rustls/std", - "ed25519-dalek?/std", - "pkcs1?/std", - "getrandom/std" -] -alloc = ["webpki?/alloc", "ecdsa?/alloc", "signature?/alloc", "ccm?/alloc"] -zeroize = ["ed25519-dalek?/zeroize", "x25519-dalek?/zeroize"] +# RustCrypto is preparing to migrate to core::error::Error +# and in before most of the use case for std is just std::error::Error +std = ["alloc"] +alloc = ["ecdsa?/alloc", "signature?/alloc"] nist = [] p256 = ["dep:p256", "nist"] From 051219e50e1344701ac031442092e19b4da9eb1e Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 00:45:26 +0800 Subject: [PATCH 31/38] save the base name for round trip test --- tests/builder.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/builder.rs b/tests/builder.rs index 22c2ce2..ce0fdab 100644 --- a/tests/builder.rs +++ b/tests/builder.rs @@ -71,6 +71,10 @@ const SERVER_MAGIC: &[u8; 18] = b"Hello from Server!"; fn test_basic_round_trip() { std::thread::scope(move |s| { for provider in generate_providers() { + let base_name = format!( + "{:?}-{:?}", + provider.cipher_suites[0], provider.kx_groups[0] + ); // Creates a pair of sockets that interconnect from client to server, and server to client let (socket_c2s, socket_s2c) = MemorySocket::new_pair(); @@ -78,10 +82,7 @@ fn test_basic_round_trip() { OsRng.fill_bytes(&mut random_data); std::thread::Builder::new() - .name(format!( - "{:?}-{:?}-server", - provider.cipher_suites[0], provider.kx_groups[0] - )) + .name(format!("{base_name}-server")) .spawn_scoped(s, { let provider: CryptoProvider = provider.clone(); move || { @@ -109,10 +110,7 @@ fn test_basic_round_trip() { .unwrap(); std::thread::Builder::new() - .name(format!( - "{:?}-{:?}-client", - provider.cipher_suites[0], provider.kx_groups[0] - )) + .name(format!("{base_name}-client")) .spawn_scoped(s, move || { let mut sock = socket_c2s; let server_name = "acme.com".try_into().expect("failed to get server name"); From 16c1411eb8a349bb697e70150c6592f4c07779d9 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 01:11:37 +0800 Subject: [PATCH 32/38] feature revamp and implementing the last hash feature todo --- Cargo.lock | 52 ++-------- Cargo.toml | 179 ++++++++++++++++++++++++----------- src/aead/aes.rs | 28 +++--- src/hash.rs | 8 +- src/hmac.rs | 5 +- src/kx.rs | 4 +- src/kx/nist.rs | 13 ++- src/lib.rs | 22 +++-- src/sign.rs | 6 +- src/sign/ecdsa.rs | 2 +- src/sign/ecdsa/nist.rs | 7 +- src/sign/eddsa/ed25519.rs | 8 +- src/sign/rsa.rs | 41 ++++---- src/tls12/suites.rs | 6 +- src/tls12/suites/ecdsa.rs | 28 +++--- src/tls12/suites/rsa.rs | 14 +-- src/tls12/suites/schemes.rs | 18 ++-- src/tls13/suites.rs | 5 +- src/tls13/suites/aes.rs | 34 ++++--- src/tls13/suites/chacha20.rs | 1 + src/verify.rs | 24 +++-- src/verify/ecdsa.rs | 2 +- src/verify/ecdsa/nist.rs | 8 +- src/verify/rsa.rs | 20 ++-- 24 files changed, 319 insertions(+), 216 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a5f9f73..a661161 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,7 @@ dependencies = [ "cfg-if", "cipher", "cpufeatures", + "zeroize", ] [[package]] @@ -34,6 +35,7 @@ dependencies = [ "ctr", "ghash", "subtle", + "zeroize", ] [[package]] @@ -284,7 +286,6 @@ checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", - "serde", "sha2", "subtle", "zeroize", @@ -357,7 +358,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", "wasm-bindgen", @@ -420,16 +420,6 @@ dependencies = [ "either", ] -[[package]] -name = "js-sys" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -441,9 +431,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libm" @@ -579,16 +569,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkcs8" version = "0.10.2" @@ -596,8 +576,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", - "pkcs5", "spki", + "subtle", ] [[package]] @@ -778,6 +758,7 @@ dependencies = [ "digest", "ecdsa", "ed25519-dalek", + "elliptic-curve", "getrandom", "hmac", "itertools", @@ -796,6 +777,7 @@ dependencies = [ "sha2", "signature", "spki", + "typenum", "x25519-dalek", "x509-cert", ] @@ -831,26 +813,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -[[package]] -name = "serde" -version = "1.0.215" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.215" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "sha1" version = "0.10.6" diff --git a/Cargo.toml b/Cargo.toml index 525bc7d..35af8a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,35 +18,33 @@ resolver = "2" # Ensure all dependencies + feats are mapped to crate features for correct usage # default features often have std breaking no_std and potentially other unwanted [dependencies] -aes = { version = "0.8.4", default-features = false, optional = true } +# Cryptographic dependencies aead = { version = "0.5.2", default-features = false, optional = true } +aes = { version = "0.8.4", default-features = false, optional = true } aes-gcm = { version = "0.10.3", default-features = false, optional = true } -ccm = { version = "0.5.0", optional = true, default-features = false } +ccm = { version = "0.5.0", default-features = false, optional = true } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } der = { version = "0.7.9", default-features = false, optional = true } digest = { version = "0.10.7", default-features = false } ecdsa = { version = "0.16.9", default-features = false, optional = true } ed25519-dalek = { version = "2", default-features = false, optional = true } +elliptic-curve = { version = "0.13.8", default-features = false, optional = true } hmac = { version = "0.12.1", default-features = false } p256 = { version = "0.13.2", default-features = false, optional = true } p384 = { version = "0.13.0", default-features = false, optional = true } p521 = { version = "0.13.3", default-features = false, optional = true } pkcs1 = { version = "0.7.5", default-features = false, optional = true } -pkcs8 = { version = "0.10.2", default-features = false, features = [ - "pkcs5", -], optional = true } -rsa = { version = "0.9.7", default-features = false, features = [ - "sha2", -], optional = true } +pkcs8 = { version = "0.10.2", default-features = false, optional = true } +rsa = { version = "0.9.7", default-features = false, optional = true } sec1 = { version = "0.7.3", default-features = false, optional = true } sha2 = { version = "0.10.8", default-features = false } signature = { version = "2.2.0", default-features = false, optional = true } +typenum = { version = "1.17.0", features = ["no_std", "const-generics"] } x25519-dalek = { version = "2", default-features = false, optional = true } -getrandom = { version = "0.2", default-features = false, features = [ - "custom" -] } +# External groups +getrandom = { version = "0.2", default-features = false, features = ["custom"] } paste = { version = "1.0.15", default-features = false } pki-types = { package = "rustls-pki-types", version = "1.10.0", default-features = false } rand_core = { version = "0.6.4", default-features = false, features = [ @@ -56,32 +54,27 @@ rustls = { version = "0.23.19", default-features = false } webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false, optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -getrandom = { version = "0.2", features = [ - "js" -] } +getrandom = { version = "0.2", features = ["wasm-bindgen"] } [dev-dependencies] bytes = { version = "1.9.0", default-features = false } -itertools = "0.13.0" -rsa = { version = "0.9.7", default-features = false, features = [ - "sha2", -] } +itertools = { version = "0.13.0", default-features = false } +rsa = { version = "0.9.7", default-features = false, features = ["sha2"] } rustls = { version = "0.23.19", default-features = false, features = ["std"] } -sha2 = { version = "0.10.8", default-features = false, features = ["oid"] } -spki = { version = "0.7.3", features = ["alloc"] } +sha2 = { version = "0.10.8", default-features = false } +spki = { version = "0.7.3", default-features = false, features = ["alloc"] } x509-cert = { version = "0.2.5", default-features = false, features = [ "builder", - "pem" ] } [features] -default = ["std", "tls12", "zeroize", "full"] +default = ["std", "tls12", "zeroize", "full", "fast"] full = [ "aead-full", - "ecdsa-full", - "eddsa-full", + "sign-full", + "verify-full", "kx-full", - "rsa-full", + "hash-full", "format", ] format = ["pem", "pkcs1", "pkcs8", "sec1"] @@ -90,8 +83,29 @@ tls12 = ["rustls/tls12"] # RustCrypto is preparing to migrate to core::error::Error # and in before most of the use case for std is just std::error::Error -std = ["alloc"] -alloc = ["ecdsa?/alloc", "signature?/alloc"] +std = ["alloc", "rustls/std"] +alloc = [ + "ecdsa?/alloc", + "elliptic-curve?/alloc", + "pkcs8?/alloc", + "sec1?/alloc", + "signature?/alloc", +] +zeroize = [ + "aes-gcm?/zeroize", + "aes?/zeroize", + "der?/zeroize", + "ed25519-dalek?/zeroize", + "pkcs1?/zeroize", + "sec1?/zeroize", + "x25519-dalek?/zeroize", +] +subtle = ["digest/subtle", "pkcs8?/subtle", "sec1?/subtle"] +fast = [ + "ed25519-dalek?/fast", + "rsa?/u64_digit", + "x25519-dalek?/precomputed-tables", +] nist = [] p256 = ["dep:p256", "nist"] @@ -99,60 +113,113 @@ p384 = ["dep:p384", "nist"] p521 = ["dep:p521", "nist"] ed25519 = ["dep:ed25519-dalek"] -verify = ["dep:webpki"] - -ecdsa = ["dep:ecdsa", "verify", "signature", "rand", "der"] -ecdsa-p256 = ["p256", "p256/ecdsa", "ecdsa"] -ecdsa-p384 = ["p384", "p384/ecdsa", "ecdsa"] -ecdsa-p521 = ["p521", "p521/ecdsa", "ecdsa"] +ecdsa = ["dep:ecdsa", "verify", "signature", "rand", "der", "elliptic-curve"] +ecdsa-p256 = ["ecdsa", "p256", "p256/ecdsa"] +ecdsa-p384 = ["ecdsa", "p384", "p384/ecdsa"] +ecdsa-p521 = ["ecdsa", "p521", "p521/ecdsa"] ecdsa-full = ["ecdsa-p256", "ecdsa-p384", "ecdsa-p521"] -eddsa = ["verify", "signature"] -eddsa-ed25519 = ["ed25519", "eddsa"] +eddsa = ["verify", "signature", "elliptic-curve"] +eddsa-ed25519 = ["eddsa", "ed25519"] eddsa-full = ["eddsa-ed25519"] -kx = ["rand"] -kx-x25519 = ["dep:x25519-dalek", "kx"] -kx-p256 = ["p256", "p256/ecdh", "kx"] -kx-p384 = ["p384", "p384/ecdh", "kx"] -kx-p521 = ["p521", "p521/ecdh", "kx"] +kx = ["rand", "elliptic-curve"] +kx-x25519 = ["kx", "dep:x25519-dalek"] +kx-nist = ["sec1"] +kx-p256 = ["kx", "p256", "kx-nist", "p256/ecdh"] +kx-p384 = ["kx", "p384", "kx-nist", "p384/ecdh"] +kx-p521 = ["kx", "p521", "kx-nist", "p521/ecdh"] kx-full = ["kx-x25519", "kx-p256", "kx-p384", "kx-p521"] -rsa = ["dep:rsa", "rsa/sha2", "verify", "signature", "pkcs1"] +rsa = ["dep:rsa", "rsa/sha2", "pkcs1"] rsa-pkcs1 = ["rsa", "pkcs1"] rsa-pss = ["rsa"] -rsa-full = ["rsa-pkcs1", "rsa-pss"] aead = ["dep:aead"] -aes-gcm = ["dep:aes-gcm", "aes", "gcm", "aead"] -aes-ccm = ["aes", "ccm", "aead"] -chacha20poly1305 = ["dep:chacha20poly1305", "aead"] -aead-full = ["aes-gcm", "aes-ccm", "chacha20poly1305"] +aead-aes-gcm = ["aead", "aes-gcm"] +aead-aes-ccm = ["aead", "aes-ccm"] +aead-chacha20poly1305 = ["aead", "chacha20poly1305"] +aead-full = ["aead-aes-gcm", "aead-aes-ccm", "aead-chacha20poly1305"] + +sign = ["signature", "der"] +sign-ecdsa-nist = ["sign"] +sign-ecdsa-p256 = ["sign-ecdsa-nist", "ecdsa-p256"] +sign-ecdsa-p384 = ["sign-ecdsa-nist", "ecdsa-p384"] +sign-ecdsa-p521 = ["sign-ecdsa-nist", "ecdsa-p521"] +sign-eddsa = ["sign"] +sign-eddsa-ed25519 = ["sign-eddsa", "eddsa-ed25519"] +sign-rsa = ["sign", "rsa"] +sign-rsa-pkcs1 = ["sign-rsa", "rsa-pkcs1"] +sign-rsa-pss = ["sign-rsa", "rsa-pss"] +sign-full = [ + "sign-ecdsa-p256", + "sign-ecdsa-p384", + "sign-ecdsa-p521", + "sign-eddsa-ed25519", + "sign-rsa-pkcs1", + "sign-rsa-pss", +] + +verify = ["dep:webpki"] +verify-ecdsa-nist = ["verify"] +verify-ecdsa-p256 = ["verify-ecdsa-nist", "ecdsa-p256"] +verify-ecdsa-p256-sha256 = ["verify-ecdsa-p256", "hash-sha256"] +verify-ecdsa-p256-sha384 = ["verify-ecdsa-p256", "hash-sha384"] +verify-ecdsa-p384 = ["verify-ecdsa-nist", "ecdsa-p384"] +verify-ecdsa-p384-sha256 = ["verify-ecdsa-p384", "hash-sha256"] +verify-ecdsa-p384-sha384 = ["verify-ecdsa-p384", "hash-sha384"] +verify-eddsa-ed25519 = ["verify", "eddsa-ed25519"] +verify-rsa-pkcs1 = ["verify", "rsa-pkcs1"] +verify-rsa-pkcs1-sha256 = ["verify-rsa-pkcs1", "hash-sha256"] +verify-rsa-pkcs1-sha384 = ["verify-rsa-pkcs1", "hash-sha384"] +verify-rsa-pkcs1-sha512 = ["verify-rsa-pkcs1", "hash-sha512"] +verify-rsa-pss = ["verify", "rsa-pss"] +verify-rsa-pss-sha256 = ["verify-rsa-pss", "hash-sha256"] +verify-rsa-pss-sha384 = ["verify-rsa-pss", "hash-sha384"] +verify-rsa-pss-sha512 = ["verify-rsa-pss", "hash-sha512"] +verify-full = [ + "verify-ecdsa-p256-sha256", + "verify-ecdsa-p256-sha384", + "verify-ecdsa-p384-sha256", + "verify-ecdsa-p384-sha384", + "verify-eddsa-ed25519", + "verify-rsa-pkcs1-sha256", + "verify-rsa-pkcs1-sha384", + "verify-rsa-pkcs1-sha512", + "verify-rsa-pss-sha256", + "verify-rsa-pss-sha384", + "verify-rsa-pss-sha512", +] -# TODO hash = [] +hash-sha224 = ["hash"] hash-sha256 = ["hash"] hash-sha384 = ["hash"] hash-sha512 = ["hash"] -hash-full = ["hash-sha256", "hash-sha384", "hash-sha512"] +hash-full = ["hash-sha224", "hash-sha256", "hash-sha384", "hash-sha512"] # Formats der = ["dep:der"] -sec1 = ["dep:sec1", "der"] -pem = ["sec1?/pem", "pkcs8?/pem", "p256?/pem", "p384?/pem", "p521?/pem", "der"] -pkcs1 = ["dep:pkcs1", "der"] +sec1 = ["dep:sec1", "elliptic-curve?/sec1"] +pem = ["elliptic-curve?/pem", "ecdsa?/pem"] +pkcs1 = ["dep:pkcs1"] pkcs8 = [ "dep:pkcs8", + "ecdsa?/pkcs8", "ed25519-dalek?/pkcs8", - "sec1?/pkcs8", + "elliptic-curve?/pkcs8", "p256?/pkcs8", "p384?/pkcs8", "p521?/pkcs8", - "der", + "sec1?/pkcs8", ] -signature = ["dep:signature"] -rand = ["dep:rand_core", "signature?/rand_core"] aes = ["dep:aes"] +aes-ccm = ["aes", "ccm"] +aes-gcm = ["dep:aes-gcm", "aes", "gcm"] ccm = ["dep:ccm"] -gcm = [] \ No newline at end of file +chacha20poly1305 = ["dep:chacha20poly1305"] +elliptic-curve = ["dep:elliptic-curve"] +gcm = [] +rand = ["dep:rand_core", "signature?/rand_core"] +signature = ["dep:signature"] \ No newline at end of file diff --git a/src/aead/aes.rs b/src/aead/aes.rs index 0272b93..099544d 100644 --- a/src/aead/aes.rs +++ b/src/aead/aes.rs @@ -1,13 +1,17 @@ -#[cfg(feature = "aes-ccm")] use aes::{Aes128, Aes256}; -#[cfg(feature = "aes-gcm")] + +#[cfg(feature = "gcm")] use aes_gcm::AesGcm; -#[cfg(feature = "aes-ccm")] -use ccm::{ - consts::{U12, U16, U8}, - Ccm, + +#[cfg(feature = "ccm")] +use { + ccm::Ccm, + typenum::{U16, U8}, }; +#[cfg(any(feature = "gcm", feature = "ccm"))] +use typenum::U12; + // The AEAD_AES_128_CCM authenticated encryption algorithm works as // specified in [CCM], using AES-128 as the block cipher, by providing // the key, nonce, associated data, and plaintext to that mode of @@ -17,22 +21,22 @@ use ccm::{ // the nonce length n is 12, // the tag length t is 16, and // the value of q is 3. -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] pub type Aes128Ccm = Ccm; -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] pub type Aes256Ccm = Ccm; // The AEAD_AES_128_CCM_8 authenticated encryption algorithm is // identical to the AEAD_AES_128_CCM algorithm (see Section 5.3 of // [RFC5116]), except that it uses 8 octets for authentication, instead // of the full 16 octets used by AEAD_AES_128_CCM. -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] pub type Aes128Ccm8 = Ccm; -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] pub type Aes256Ccm8 = Ccm; -#[cfg(feature = "aes-gcm")] +#[cfg(feature = "gcm")] pub type Aes128Gcm = AesGcm; -#[cfg(feature = "aes-gcm")] +#[cfg(feature = "gcm")] pub type Aes256Gcm = AesGcm; diff --git a/src/hash.rs b/src/hash.rs index c8b93ad..7221fb8 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -55,7 +55,11 @@ macro_rules! impl_hash { }; } -// impl_hash! {SHA224, Sha224, hash::HashAlgorithm::SHA224} +#[cfg(feature = "hash-sha224")] +impl_hash! {SHA224, ::sha2::Sha224, hash::HashAlgorithm::SHA224} +#[cfg(feature = "hash-sha256")] impl_hash! {SHA256, ::sha2::Sha256, hash::HashAlgorithm::SHA256} +#[cfg(feature = "hash-sha384")] impl_hash! {SHA384, ::sha2::Sha384, hash::HashAlgorithm::SHA384} -// impl_hash! {SHA512, Sha512, hash::HashAlgorithm::SHA512} +#[cfg(feature = "hash-sha512")] +impl_hash! {SHA512, ::sha2::Sha512, hash::HashAlgorithm::SHA512} diff --git a/src/hmac.rs b/src/hmac.rs index e7e671f..5e235cc 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -51,6 +51,9 @@ macro_rules! impl_hmac { }; } +#[cfg(feature = "hash-sha256")] impl_hmac! {SHA256, ::sha2::Sha256} +#[cfg(feature = "hash-sha384")] impl_hmac! {SHA384, ::sha2::Sha384} -// impl_hmac! {SHA512, Sha512} +#[cfg(feature = "hash-sha512")] +impl_hmac! {SHA512, ::sha2::Sha512} diff --git a/src/kx.rs b/src/kx.rs index 1075669..0d7d27d 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -7,9 +7,11 @@ pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ &nist::SecP256R1, #[cfg(feature = "kx-p384")] &nist::SecP384R1, + #[cfg(feature = "kx-p521")] + &nist::SecP521R1, ]; -#[cfg(feature = "nist")] +#[cfg(feature = "kx-nist")] pub mod nist; #[cfg(feature = "kx-x25519")] diff --git a/src/kx/nist.rs b/src/kx/nist.rs index a2c3ea4..645b2a4 100644 --- a/src/kx/nist.rs +++ b/src/kx/nist.rs @@ -1,16 +1,16 @@ -#[cfg(all(feature = "alloc", any(feature = "kx-p256", feature = "kx-p384")))] +#[cfg(all(feature = "alloc", feature = "kx-nist"))] use alloc::boxed::Box; -#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] +#[cfg(feature = "kx-nist")] use crypto::{SharedSecret, SupportedKxGroup}; -#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] +#[cfg(feature = "kx-nist")] use paste::paste; -#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] +#[cfg(feature = "kx-nist")] use rustls::crypto; -#[cfg(any(feature = "kx-p256", feature = "kx-p384"))] +#[cfg(feature = "kx-nist")] macro_rules! impl_kx { ($name:ident, $kx_name:ty, $secret:ty, $public_key:ty) => { paste! { @@ -71,3 +71,6 @@ impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, ::p256::ecdh::EphemeralSecre #[cfg(feature = "kx-p384")] impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, ::p384::ecdh::EphemeralSecret, ::p384::PublicKey} + +#[cfg(feature = "kx-p521")] +impl_kx! {SecP521R1, rustls::NamedGroup::secp521r1, ::p521::ecdh::EphemeralSecret, ::p521::PublicKey} diff --git a/src/lib.rs b/src/lib.rs index 7067345..df901fc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,11 +76,11 @@ impl KeyProvider for Provider { &self, #[allow(unused_variables)] key_der: PrivateKeyDer<'static>, ) -> Result, rustls::Error> { - #[cfg(feature = "signature")] + #[cfg(feature = "sign")] { sign::any_supported_type(&key_der) } - #[cfg(not(feature = "signature"))] + #[cfg(not(feature = "sign"))] { Err(rustls::Error::General("not key providers supported".into())) } @@ -105,21 +105,27 @@ pub const ALL_CIPHER_SUITES: &[SupportedCipherSuite] = misc::const_concat_slices #[cfg(feature = "aead")] pub mod aead; +#[cfg(feature = "hash")] pub mod hash; +#[cfg(feature = "hash")] pub mod hmac; - +#[cfg(feature = "kx")] pub mod kx; - pub mod misc; -#[cfg(feature = "signature")] +#[cfg(feature = "sign")] pub mod sign; -pub mod verify; - #[cfg(feature = "tls12")] pub mod tls12; pub mod tls13; +#[cfg(feature = "verify")] +pub mod verify; const _: () = assert!( - ALL_CIPHER_SUITES.len() != 0, + !ALL_CIPHER_SUITES.is_empty(), "At least one cipher suite should be enabled" ); + +const _: () = assert!( + !kx::ALL_KX_GROUPS.is_empty(), + "At least one key exchange algorithm should be enabled" +); diff --git a/src/sign.rs b/src/sign.rs index 3e0132b..5cc4baa 100644 --- a/src/sign.rs +++ b/src/sign.rs @@ -42,15 +42,17 @@ where /// Returns an error if the key couldn't be decoded. #[allow(unused_variables)] pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { - #[cfg(all(feature = "der", feature = "rsa"))] + #[cfg(feature = "sign-rsa")] if let Ok(key) = rsa::RsaSigningKey::try_from(der) { return Ok(Arc::new(key) as _); } + #[cfg(feature = "sign-ecdsa-nist")] if let Ok(key) = any_ecdsa_type(der) { return Ok(key); } + #[cfg(feature = "sign-eddsa")] if let Ok(key) = any_eddsa_type(der) { return Ok(key); } @@ -64,6 +66,7 @@ pub fn any_supported_type(der: &PrivateKeyDer<'_>) -> Result /// /// Returns an error if the key couldn't be decoded. #[allow(unused_variables)] +#[cfg(feature = "sign-ecdsa-nist")] pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { #[cfg(all(feature = "der", feature = "ecdsa-p256"))] if let Ok(key) = ecdsa::nist::EcdsaSigningKeyP256::try_from(der) { @@ -83,6 +86,7 @@ pub fn any_ecdsa_type(der: &PrivateKeyDer<'_>) -> Result, ru /// /// Returns an error if the key couldn't be decoded. #[allow(unused_variables)] +#[cfg(feature = "sign-eddsa")] pub fn any_eddsa_type(der: &PrivateKeyDer<'_>) -> Result, rustls::Error> { // TODO: Add support for Ed448 #[cfg(all(feature = "der", feature = "eddsa-ed25519"))] diff --git a/src/sign/ecdsa.rs b/src/sign/ecdsa.rs index 9e8a797..1931d6e 100644 --- a/src/sign/ecdsa.rs +++ b/src/sign/ecdsa.rs @@ -1,2 +1,2 @@ -#[cfg(feature = "nist")] +#[cfg(feature = "sign-ecdsa-nist")] pub mod nist; diff --git a/src/sign/ecdsa/nist.rs b/src/sign/ecdsa/nist.rs index 664cc2d..8b95d53 100644 --- a/src/sign/ecdsa/nist.rs +++ b/src/sign/ecdsa/nist.rs @@ -68,8 +68,11 @@ macro_rules! impl_ecdsa { }; } -#[cfg(feature = "ecdsa-p256")] +#[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] impl_ecdsa! {P256, SignatureScheme::ECDSA_NISTP256_SHA256, ::p256::ecdsa::SigningKey, ::p256::ecdsa::DerSignature} -#[cfg(feature = "ecdsa-p384")] +#[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] impl_ecdsa! {P384, SignatureScheme::ECDSA_NISTP384_SHA384, ::p384::ecdsa::SigningKey, ::p384::ecdsa::DerSignature} + +// #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha512"))] +// impl_ecdsa! {P521, SignatureScheme::ECDSA_NISTP521_SHA512, ::p521::ecdsa::SigningKey, ::p521::ecdsa::DerSignature} diff --git a/src/sign/eddsa/ed25519.rs b/src/sign/eddsa/ed25519.rs index 1651ae3..14a385c 100644 --- a/src/sign/eddsa/ed25519.rs +++ b/src/sign/eddsa/ed25519.rs @@ -1,12 +1,16 @@ #[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, string::ToString, sync::Arc}; +use alloc::{boxed::Box, sync::Arc}; +#[cfg(all(feature = "alloc", feature = "der"))] +use alloc::{format, string::ToString}; use crate::sign::GenericSigner; use core::marker::PhantomData; use ed25519_dalek::SigningKey; -use pki_types::PrivateKeyDer; use rustls::{sign::Signer, SignatureAlgorithm, SignatureScheme}; +#[cfg(feature = "der")] +use pki_types::PrivateKeyDer; + #[derive(Debug)] pub struct Ed25519SigningKey(Arc); diff --git a/src/sign/rsa.rs b/src/sign/rsa.rs index 34c6199..1822089 100644 --- a/src/sign/rsa.rs +++ b/src/sign/rsa.rs @@ -1,25 +1,34 @@ #[cfg(feature = "alloc")] -use alloc::{boxed::Box, format, string::ToString, sync::Arc}; - -use pki_types::PrivateKeyDer; +use alloc::{boxed::Box, sync::Arc}; +#[cfg(all(feature = "alloc", feature = "der"))] +use alloc::{format, string::ToString}; use rsa::RsaPrivateKey; use rustls::sign::{Signer, SigningKey}; use rustls::{SignatureAlgorithm, SignatureScheme}; -use sha2::{Sha256, Sha384, Sha512}; + +#[cfg(feature = "hash-sha256")] +use sha2::Sha256; +#[cfg(feature = "hash-sha384")] +use sha2::Sha384; +#[cfg(feature = "hash-sha512")] +use sha2::Sha512; + +#[cfg(feature = "der")] +use pki_types::PrivateKeyDer; const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] SignatureScheme::RSA_PSS_SHA512, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] SignatureScheme::RSA_PSS_SHA384, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] SignatureScheme::RSA_PSS_SHA256, - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] SignatureScheme::RSA_PKCS1_SHA512, - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] SignatureScheme::RSA_PKCS1_SHA384, - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] SignatureScheme::RSA_PKCS1_SHA256, ]; @@ -69,21 +78,21 @@ impl SigningKey for RsaSigningKey { } match scheme { - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] SignatureScheme::RSA_PSS_SHA512 => signer! {::rsa::pss::SigningKey::}, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] SignatureScheme::RSA_PSS_SHA384 => signer! {::rsa::pss::SigningKey::}, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] SignatureScheme::RSA_PSS_SHA256 => signer! {::rsa::pss::SigningKey::}, - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] SignatureScheme::RSA_PKCS1_SHA512 => { signer! {::rsa::pkcs1v15::SigningKey::} } - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] SignatureScheme::RSA_PKCS1_SHA384 => { signer! {::rsa::pkcs1v15::SigningKey::} } - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] SignatureScheme::RSA_PKCS1_SHA256 => { signer! {::rsa::pkcs1v15::SigningKey::} } diff --git a/src/tls12/suites.rs b/src/tls12/suites.rs index 41dfac4..06eca35 100644 --- a/src/tls12/suites.rs +++ b/src/tls12/suites.rs @@ -15,12 +15,12 @@ pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( } }, { - #[cfg(feature = "rsa")] + #[cfg(any(feature = "rsa-pss", feature = "rsa-pkcs1"))] { rsa::TLS_ECDHE_RSA_SUITES } - #[cfg(not(feature = "rsa"))] + #[cfg(not(any(feature = "rsa-pss", feature = "rsa-pkcs1")))] { &[] } @@ -29,6 +29,6 @@ pub const TLS12_SUITES: &[SupportedCipherSuite] = const_concat_slices!( #[cfg(feature = "ecdsa")] pub mod ecdsa; -#[cfg(feature = "rsa")] +#[cfg(any(feature = "rsa-pss", feature = "rsa-pkcs1"))] pub mod rsa; pub mod schemes; diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs index 7f5a61e..63a4443 100644 --- a/src/tls12/suites/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -18,7 +18,7 @@ use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; -#[cfg(feature = "aes-gcm")] +#[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, @@ -31,7 +31,7 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12Ciphe prf_provider: &PrfUsingHmac(hmac::SHA256), }; -#[cfg(feature = "aes-gcm")] +#[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, @@ -45,7 +45,7 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12Ciphe }; // https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_128_CCM/ -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] pub const TLS_ECDHE_ECDSA_WITH_AES_128_CCM: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CCM, @@ -59,7 +59,7 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_128_CCM: Tls12CipherSuite = Tls12CipherSuite }; // https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_256_CCM/ -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] pub const TLS_ECDHE_ECDSA_WITH_AES_256_CCM: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_CCM, @@ -73,7 +73,7 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_256_CCM: Tls12CipherSuite = Tls12CipherSuite }; // https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8/ -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] pub const TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, @@ -87,7 +87,7 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: Tls12CipherSuite = Tls12CipherSuit }; // https://ciphersuite.info/cs/TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8/ -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] pub const TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, @@ -100,7 +100,7 @@ pub const TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: Tls12CipherSuite = Tls12CipherSuit prf_provider: &PrfUsingHmac(hmac::SHA256), }; -#[cfg(feature = "chacha20poly1305")] +#[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, @@ -114,18 +114,18 @@ pub const TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls1 }; pub const TLS_ECDHE_ECDSA_SUITES: &[SupportedCipherSuite] = &[ - #[cfg(feature = "aes-gcm")] + #[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), - #[cfg(feature = "aes-gcm")] + #[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), - #[cfg(feature = "aes-ccm")] + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_CCM), - #[cfg(feature = "aes-ccm")] + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_CCM), - #[cfg(feature = "aes-ccm")] + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8), - #[cfg(feature = "aes-ccm")] + #[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8), - #[cfg(feature = "chacha20poly1305")] + #[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), ]; diff --git a/src/tls12/suites/rsa.rs b/src/tls12/suites/rsa.rs index b94017a..d00189e 100644 --- a/src/tls12/suites/rsa.rs +++ b/src/tls12/suites/rsa.rs @@ -15,7 +15,7 @@ use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; -#[cfg(feature = "aes-gcm")] +#[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, @@ -28,7 +28,7 @@ pub const TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: Tls12CipherSuite = Tls12CipherS prf_provider: &PrfUsingHmac(hmac::SHA256), }; -#[cfg(feature = "aes-gcm")] +#[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, @@ -37,11 +37,11 @@ pub const TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: Tls12CipherSuite = Tls12CipherS }, kx: KeyExchangeAlgorithm::ECDHE, sign: TLS12_RSA_SCHEMES, - prf_provider: &PrfUsingHmac(hmac::SHA384), aead_alg: &Aes256Gcm, + prf_provider: &PrfUsingHmac(hmac::SHA384), }; -#[cfg(feature = "chacha20poly1305")] +#[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite { common: CipherSuiteCommon { suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, @@ -55,10 +55,10 @@ pub const TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12C }; pub const TLS_ECDHE_RSA_SUITES: &[SupportedCipherSuite] = &[ - #[cfg(feature = "aes-gcm")] + #[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), - #[cfg(feature = "aes-gcm")] + #[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), - #[cfg(feature = "chacha20poly1305")] + #[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] SupportedCipherSuite::Tls12(&TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), ]; diff --git a/src/tls12/suites/schemes.rs b/src/tls12/suites/schemes.rs index 2b3deb9..873dcf6 100644 --- a/src/tls12/suites/schemes.rs +++ b/src/tls12/suites/schemes.rs @@ -3,11 +3,11 @@ use rustls::SignatureScheme; #[cfg(feature = "ecdsa")] pub const TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[ - #[cfg(feature = "ecdsa-p256")] + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] SignatureScheme::ECDSA_NISTP256_SHA256, - #[cfg(feature = "ecdsa-p384")] + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] SignatureScheme::ECDSA_NISTP384_SHA384, - #[cfg(feature = "ecdsa-p521")] + #[cfg(all(feature = "ecdsa-p521", feature = "hash-sha512"))] SignatureScheme::ECDSA_NISTP521_SHA512, #[cfg(feature = "eddsa-ed25519")] SignatureScheme::ED25519, @@ -15,16 +15,16 @@ pub const TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[ #[cfg(feature = "rsa")] pub const TLS12_RSA_SCHEMES: &[SignatureScheme] = &[ - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] SignatureScheme::RSA_PKCS1_SHA256, - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] SignatureScheme::RSA_PKCS1_SHA384, - #[cfg(feature = "rsa-pkcs1")] + #[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] SignatureScheme::RSA_PKCS1_SHA512, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] SignatureScheme::RSA_PSS_SHA256, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] SignatureScheme::RSA_PSS_SHA384, - #[cfg(feature = "rsa-pss")] + #[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] SignatureScheme::RSA_PSS_SHA512, ]; diff --git a/src/tls13/suites.rs b/src/tls13/suites.rs index 4b0bd06..c849e48 100644 --- a/src/tls13/suites.rs +++ b/src/tls13/suites.rs @@ -17,7 +17,10 @@ pub const TLS13_SUITES: &[SupportedCipherSuite] = const_concat_slices!( { #[cfg(feature = "chacha20poly1305")] { - &[chacha20::TLS13_CHACHA20_POLY1305_SHA256] + &[ + #[cfg(feature = "hash-sha256")] + chacha20::TLS13_CHACHA20_POLY1305_SHA256, + ] } #[cfg(not(feature = "chacha20poly1305"))] diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs index 87a7c84..c8d4919 100644 --- a/src/tls13/suites/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,13 +1,13 @@ -#[cfg(feature = "aes-ccm")] +#[cfg(feature = "ccm")] use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8}; -#[cfg(feature = "aes-gcm")] +#[cfg(feature = "gcm")] use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; use crate::const_concat_slices; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; -#[cfg(feature = "aes-gcm")] +#[cfg(all(feature = "gcm", feature = "hash-sha256"))] pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { @@ -20,7 +20,7 @@ pub const TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = quic: None, }); -#[cfg(feature = "aes-gcm")] +#[cfg(all(feature = "gcm", feature = "hash-sha384"))] pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { @@ -33,7 +33,7 @@ pub const TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = quic: None, }); -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "ccm", feature = "hash-sha256"))] pub const TLS13_AES_128_CCM_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { @@ -46,7 +46,7 @@ pub const TLS13_AES_128_CCM_SHA256: SupportedCipherSuite = quic: None, }); -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "ccm", feature = "hash-sha256"))] pub const TLS13_AES_128_CCM_8_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { @@ -62,23 +62,33 @@ pub const TLS13_AES_128_CCM_8_SHA256: SupportedCipherSuite = pub const TLS13_AES_SUITES: &[SupportedCipherSuite] = const_concat_slices!( SupportedCipherSuite, { - #[cfg(feature = "aes-gcm")] + #[cfg(feature = "gcm")] { - &[TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384] + &[ + #[cfg(feature = "hash-sha256")] + TLS13_AES_128_GCM_SHA256, + #[cfg(feature = "hash-sha384")] + TLS13_AES_256_GCM_SHA384, + ] } - #[cfg(not(feature = "aes-gcm"))] + #[cfg(not(feature = "gcm"))] { &[] } }, { - #[cfg(feature = "aes-ccm")] + #[cfg(feature = "ccm")] { - &[TLS13_AES_128_CCM_SHA256, TLS13_AES_128_CCM_8_SHA256] + &[ + #[cfg(feature = "hash-sha256")] + TLS13_AES_128_CCM_SHA256, + #[cfg(feature = "hash-sha256")] + TLS13_AES_128_CCM_8_SHA256, + ] } - #[cfg(not(feature = "aes-ccm"))] + #[cfg(not(feature = "ccm"))] { &[] } diff --git a/src/tls13/suites/chacha20.rs b/src/tls13/suites/chacha20.rs index ceae440..6d87d07 100644 --- a/src/tls13/suites/chacha20.rs +++ b/src/tls13/suites/chacha20.rs @@ -3,6 +3,7 @@ use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon}; use rustls::{CipherSuite, SupportedCipherSuite, Tls13CipherSuite}; +#[cfg(feature = "hash-sha256")] pub const TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = SupportedCipherSuite::Tls13(&Tls13CipherSuite { common: CipherSuiteCommon { diff --git a/src/verify.rs b/src/verify.rs index 668e879..7e0ec87 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -49,13 +49,13 @@ pub const ALL: &[&'static dyn SignatureVerificationAlgorithm] = const_concat_sli #[cfg(feature = "ecdsa")] { &[ - #[cfg(feature = "ecdsa-p256")] + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] ecdsa::nist::ECDSA_P256_SHA256, - #[cfg(feature = "ecdsa-p256")] + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha384"))] ecdsa::nist::ECDSA_P256_SHA384, - #[cfg(feature = "ecdsa-p384")] + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha256"))] ecdsa::nist::ECDSA_P384_SHA256, - #[cfg(feature = "ecdsa-p384")] + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] ecdsa::nist::ECDSA_P384_SHA384, ] } @@ -69,8 +69,11 @@ pub const ALL: &[&'static dyn SignatureVerificationAlgorithm] = const_concat_sli #[cfg(feature = "rsa-pkcs1")] { &[ + #[cfg(feature = "hash-sha256")] rsa::RSA_PKCS1_SHA256, + #[cfg(feature = "hash-sha384")] rsa::RSA_PKCS1_SHA384, + #[cfg(feature = "hash-sha512")] rsa::RSA_PKCS1_SHA512, ] } @@ -84,8 +87,11 @@ pub const ALL: &[&'static dyn SignatureVerificationAlgorithm] = const_concat_sli #[cfg(feature = "rsa-pss")] { &[ + #[cfg(feature = "hash-sha256")] rsa::RSA_PSS_SHA256, + #[cfg(feature = "hash-sha384")] rsa::RSA_PSS_SHA384, + #[cfg(feature = "hash-sha512")] rsa::RSA_PSS_SHA512, ] } @@ -109,7 +115,7 @@ pub const MAPPING: &[( #[cfg(feature = "ecdsa")] { &[ - #[cfg(feature = "ecdsa-p384")] + #[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] ( SignatureScheme::ECDSA_NISTP384_SHA384, &[ @@ -118,7 +124,7 @@ pub const MAPPING: &[( ecdsa::nist::ECDSA_P256_SHA384, ], ), - #[cfg(feature = "ecdsa-p256")] + #[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] ( SignatureScheme::ECDSA_NISTP256_SHA256, &[ @@ -139,8 +145,11 @@ pub const MAPPING: &[( #[cfg(feature = "rsa-pkcs1")] { &[ + #[cfg(feature = "hash-sha256")] (SignatureScheme::RSA_PKCS1_SHA256, &[rsa::RSA_PKCS1_SHA256]), + #[cfg(feature = "hash-sha384")] (SignatureScheme::RSA_PKCS1_SHA384, &[rsa::RSA_PKCS1_SHA384]), + #[cfg(feature = "hash-sha512")] (SignatureScheme::RSA_PKCS1_SHA512, &[rsa::RSA_PKCS1_SHA512]), ] } @@ -154,8 +163,11 @@ pub const MAPPING: &[( #[cfg(feature = "rsa-pss")] { &[ + #[cfg(feature = "hash-sha256")] (SignatureScheme::RSA_PSS_SHA256, &[rsa::RSA_PSS_SHA256]), + #[cfg(feature = "hash-sha384")] (SignatureScheme::RSA_PSS_SHA384, &[rsa::RSA_PSS_SHA384]), + #[cfg(feature = "hash-sha512")] (SignatureScheme::RSA_PSS_SHA512, &[rsa::RSA_PSS_SHA512]), ] } diff --git a/src/verify/ecdsa.rs b/src/verify/ecdsa.rs index 9e8a797..2d5c7c7 100644 --- a/src/verify/ecdsa.rs +++ b/src/verify/ecdsa.rs @@ -1,2 +1,2 @@ -#[cfg(feature = "nist")] +#[cfg(feature = "verify-ecdsa-nist")] pub mod nist; diff --git a/src/verify/ecdsa/nist.rs b/src/verify/ecdsa/nist.rs index 59343c2..581d92b 100644 --- a/src/verify/ecdsa/nist.rs +++ b/src/verify/ecdsa/nist.rs @@ -54,11 +54,11 @@ macro_rules! impl_generic_ecdsa_verifer { }; } -#[cfg(feature = "ecdsa-p256")] +#[cfg(all(feature = "ecdsa-p256", feature = "hash-sha256"))] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA256, alg_id::ECDSA_P256, alg_id::ECDSA_SHA256, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha256} -#[cfg(feature = "ecdsa-p256")] +#[cfg(all(feature = "ecdsa-p256", feature = "hash-sha384"))] impl_generic_ecdsa_verifer! {ECDSA_P256_SHA384, alg_id::ECDSA_P256, alg_id::ECDSA_SHA384, ::p256::ecdsa::VerifyingKey, ::p256::ecdsa::DerSignature, ::sha2::Sha384} -#[cfg(feature = "ecdsa-p384")] +#[cfg(all(feature = "ecdsa-p384", feature = "hash-sha256"))] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA256, alg_id::ECDSA_P384, alg_id::ECDSA_SHA256, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha256} -#[cfg(feature = "ecdsa-p384")] +#[cfg(all(feature = "ecdsa-p384", feature = "hash-sha384"))] impl_generic_ecdsa_verifer! {ECDSA_P384_SHA384, alg_id::ECDSA_P384, alg_id::ECDSA_SHA384, ::p384::ecdsa::VerifyingKey, ::p384::ecdsa::DerSignature, ::sha2::Sha384} diff --git a/src/verify/rsa.rs b/src/verify/rsa.rs index e125d82..c273176 100644 --- a/src/verify/rsa.rs +++ b/src/verify/rsa.rs @@ -1,9 +1,15 @@ use paste::paste; use pki_types::{AlgorithmIdentifier, InvalidSignature, SignatureVerificationAlgorithm}; -use sha2::{Sha256, Sha384, Sha512}; use signature::Verifier; use webpki::alg_id; +#[cfg(feature = "hash-sha256")] +use sha2::Sha256; +#[cfg(feature = "hash-sha384")] +use sha2::Sha384; +#[cfg(feature = "hash-sha512")] +use sha2::Sha512; + macro_rules! impl_generic_rsa_verifer { ( $name:ident, @@ -57,7 +63,7 @@ macro_rules! impl_generic_rsa_verifer { }; } -#[cfg(feature = "rsa-pkcs1")] +#[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha256"))] impl_generic_rsa_verifer!( RSA_PKCS1_SHA256, alg_id::RSA_ENCRYPTION, @@ -66,7 +72,7 @@ impl_generic_rsa_verifer!( ::rsa::pkcs1v15::Signature ); -#[cfg(feature = "rsa-pkcs1")] +#[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha384"))] impl_generic_rsa_verifer!( RSA_PKCS1_SHA384, alg_id::RSA_ENCRYPTION, @@ -75,7 +81,7 @@ impl_generic_rsa_verifer!( ::rsa::pkcs1v15::Signature ); -#[cfg(feature = "rsa-pkcs1")] +#[cfg(all(feature = "rsa-pkcs1", feature = "hash-sha512"))] impl_generic_rsa_verifer!( RSA_PKCS1_SHA512, alg_id::RSA_ENCRYPTION, @@ -84,7 +90,7 @@ impl_generic_rsa_verifer!( ::rsa::pkcs1v15::Signature ); -#[cfg(feature = "rsa-pss")] +#[cfg(all(feature = "rsa-pss", feature = "hash-sha256"))] impl_generic_rsa_verifer!( RSA_PSS_SHA256, alg_id::RSA_ENCRYPTION, @@ -92,7 +98,7 @@ impl_generic_rsa_verifer!( ::rsa::pss::VerifyingKey, ::rsa::pss::Signature ); -#[cfg(feature = "rsa-pss")] +#[cfg(all(feature = "rsa-pss", feature = "hash-sha384"))] impl_generic_rsa_verifer!( RSA_PSS_SHA384, alg_id::RSA_ENCRYPTION, @@ -100,7 +106,7 @@ impl_generic_rsa_verifer!( ::rsa::pss::VerifyingKey, ::rsa::pss::Signature ); -#[cfg(feature = "rsa-pss")] +#[cfg(all(feature = "rsa-pss", feature = "hash-sha512"))] impl_generic_rsa_verifer!( RSA_PSS_SHA512, alg_id::RSA_ENCRYPTION, From a7d55e362b96322bffc81a5f3f2c352de9838d59 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 20:17:24 +0800 Subject: [PATCH 33/38] allow p521 to be tested by openssl --- validation/local_ping_pong_openssl/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/validation/local_ping_pong_openssl/src/lib.rs b/validation/local_ping_pong_openssl/src/lib.rs index ff46fb5..55da94b 100644 --- a/validation/local_ping_pong_openssl/src/lib.rs +++ b/validation/local_ping_pong_openssl/src/lib.rs @@ -116,7 +116,6 @@ mod test { vs_openssl_as_client(group_list, OpenSslCipherSuites::default()); } #[test] - #[should_panic] // no support fn vs_openssl_as_client_group_p521() { let mut group_list = OpenSslGroupsList::all_false(); group_list.P521 = true; From 1ed2a273c5451c3e8971f72780b4a13401764c5e Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 20:18:56 +0800 Subject: [PATCH 34/38] add x448 support --- Cargo.lock | 31 ++++++++++++ Cargo.toml | 7 ++- src/kx.rs | 5 ++ src/kx/x448.rs | 48 +++++++++++++++++++ validation/local_ping_pong_openssl/src/lib.rs | 1 - 5 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 src/kx/x448.rs diff --git a/Cargo.lock b/Cargo.lock index a661161..ef6c31c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -160,6 +160,17 @@ dependencies = [ "libc", ] +[[package]] +name = "crrl" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca032663238726938d4ca23189575167143599eb219b591270c0d268ca9259b0" +dependencies = [ + "rand_core", + "sha2", + "sha3", +] + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -420,6 +431,15 @@ dependencies = [ "either", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -753,6 +773,7 @@ dependencies = [ "bytes", "ccm", "chacha20poly1305", + "crrl", "crypto-common", "der", "digest", @@ -835,6 +856,16 @@ dependencies = [ "digest", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "shlex" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index 35af8a3..d24fc00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ aes = { version = "0.8.4", default-features = false, optional = true } aes-gcm = { version = "0.10.3", default-features = false, optional = true } ccm = { version = "0.5.0", default-features = false, optional = true } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } +crrl = { version = "0.9.0", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } der = { version = "0.7.9", default-features = false, optional = true } digest = { version = "0.10.7", default-features = false } @@ -124,12 +125,13 @@ eddsa-ed25519 = ["eddsa", "ed25519"] eddsa-full = ["eddsa-ed25519"] kx = ["rand", "elliptic-curve"] +kx-x448 = ["kx", "x448"] kx-x25519 = ["kx", "dep:x25519-dalek"] kx-nist = ["sec1"] kx-p256 = ["kx", "p256", "kx-nist", "p256/ecdh"] kx-p384 = ["kx", "p384", "kx-nist", "p384/ecdh"] kx-p521 = ["kx", "p521", "kx-nist", "p521/ecdh"] -kx-full = ["kx-x25519", "kx-p256", "kx-p384", "kx-p521"] +kx-full = ["kx-x448", "kx-x25519", "kx-p256", "kx-p384", "kx-p521"] rsa = ["dep:rsa", "rsa/sha2", "pkcs1"] rsa-pkcs1 = ["rsa", "pkcs1"] @@ -222,4 +224,5 @@ chacha20poly1305 = ["dep:chacha20poly1305"] elliptic-curve = ["dep:elliptic-curve"] gcm = [] rand = ["dep:rand_core", "signature?/rand_core"] -signature = ["dep:signature"] \ No newline at end of file +signature = ["dep:signature"] +x448 = ["dep:crrl", "crrl/x448"] \ No newline at end of file diff --git a/src/kx.rs b/src/kx.rs index 0d7d27d..f65b91f 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -1,6 +1,8 @@ use rustls::crypto::SupportedKxGroup; pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ + #[cfg(feature = "kx-x448")] + &x448::X448, #[cfg(feature = "kx-x25519")] &x25519::X25519, #[cfg(feature = "kx-p256")] @@ -16,3 +18,6 @@ pub mod nist; #[cfg(feature = "kx-x25519")] pub mod x25519; + +#[cfg(feature = "kx-x448")] +pub mod x448; \ No newline at end of file diff --git a/src/kx/x448.rs b/src/kx/x448.rs new file mode 100644 index 0000000..b1dc882 --- /dev/null +++ b/src/kx/x448.rs @@ -0,0 +1,48 @@ +#[cfg(feature = "alloc")] +use alloc::boxed::Box; + +use crrl::x448::{x448, x448_base}; +use crypto::{SharedSecret, SupportedKxGroup}; +use rand_core::RngCore; +use rustls::crypto::{self, ActiveKeyExchange}; + +#[derive(Debug)] +pub struct X448; + +impl crypto::SupportedKxGroup for X448 { + fn name(&self) -> rustls::NamedGroup { + rustls::NamedGroup::X448 + } + + fn start(&self) -> Result, rustls::Error> { + let priv_key = { + let mut bytes = [0u8; 56]; + rand_core::OsRng.fill_bytes(&mut bytes); + bytes + }; + let pub_key = x448_base(&priv_key); + Ok(Box::new(X448KeyExchange { priv_key, pub_key })) + } +} + +pub struct X448KeyExchange { + priv_key: [u8; 56], + pub_key: [u8; 56], +} + +impl ActiveKeyExchange for X448KeyExchange { + fn complete(self: Box, peer: &[u8]) -> Result { + let peer_public: [u8; 56] = peer + .try_into() + .map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; + Ok(x448(&peer_public, &self.priv_key).as_ref().into()) + } + + fn pub_key(&self) -> &[u8] { + self.pub_key.as_slice() + } + + fn group(&self) -> rustls::NamedGroup { + X448.name() + } +} diff --git a/validation/local_ping_pong_openssl/src/lib.rs b/validation/local_ping_pong_openssl/src/lib.rs index 55da94b..a76579f 100644 --- a/validation/local_ping_pong_openssl/src/lib.rs +++ b/validation/local_ping_pong_openssl/src/lib.rs @@ -128,7 +128,6 @@ mod test { vs_openssl_as_client(group_list, OpenSslCipherSuites::default()); } #[test] - #[should_panic] // no support fn vs_openssl_as_client_group_x448() { let mut group_list = OpenSslGroupsList::all_false(); group_list.X448 = true; From a74fa6d142acf49b374e84b9b8e8dc2e2902e19d Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 20:36:26 +0800 Subject: [PATCH 35/38] patch crrl for mishandling dependencies --- Cargo.lock | 3 +-- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ef6c31c..e21957b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,8 +163,7 @@ dependencies = [ [[package]] name = "crrl" version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca032663238726938d4ca23189575167143599eb219b591270c0d268ca9259b0" +source = "git+https://github.com/stevefan1999-personal/crrl#7e502920ebedccce4aaa930d4c9a26787f157101" dependencies = [ "rand_core", "sha2", diff --git a/Cargo.toml b/Cargo.toml index d24fc00..d608eb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ aes = { version = "0.8.4", default-features = false, optional = true } aes-gcm = { version = "0.10.3", default-features = false, optional = true } ccm = { version = "0.5.0", default-features = false, optional = true } chacha20poly1305 = { version = "0.10.1", default-features = false, optional = true } -crrl = { version = "0.9.0", default-features = false, optional = true } +crrl = { git = "https://github.com/stevefan1999-personal/crrl", version = "0.9.0", default-features = false, optional = true } crypto-common = { version = "0.1.6", default-features = false } der = { version = "0.7.9", default-features = false, optional = true } digest = { version = "0.10.7", default-features = false } From b22eabf6803a38bc0e4f5b6ad97ee0f478af7695 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 20:37:40 +0800 Subject: [PATCH 36/38] remove unnecessary mod redirection --- src/kx.rs | 2 +- src/tls12/aead/ccm.rs | 2 +- src/tls12/aead/gcm.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kx.rs b/src/kx.rs index f65b91f..faead0b 100644 --- a/src/kx.rs +++ b/src/kx.rs @@ -20,4 +20,4 @@ pub mod nist; pub mod x25519; #[cfg(feature = "kx-x448")] -pub mod x448; \ No newline at end of file +pub mod x448; diff --git a/src/tls12/aead/ccm.rs b/src/tls12/aead/ccm.rs index 5fcccfd..23f9c8b 100644 --- a/src/tls12/aead/ccm.rs +++ b/src/tls12/aead/ccm.rs @@ -3,7 +3,6 @@ use alloc::boxed::Box; use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; use ::aead::{AeadCore, AeadInPlace}; -use crypto_common::typenum::Unsigned; use crypto_common::{KeyInit, KeySizeUser}; use paste::paste; use rustls::crypto::cipher::{ @@ -12,6 +11,7 @@ use rustls::crypto::cipher::{ PrefixedPayload, Tls12AeadAlgorithm, }; use rustls::ConnectionTrafficSecrets; +use typenum::Unsigned; const EXPLICIT_NONCE_LEN: usize = 8; diff --git a/src/tls12/aead/gcm.rs b/src/tls12/aead/gcm.rs index 4073f26..fa718d4 100644 --- a/src/tls12/aead/gcm.rs +++ b/src/tls12/aead/gcm.rs @@ -3,7 +3,6 @@ use alloc::boxed::Box; use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; use ::aead::{AeadCore, AeadInPlace}; -use crypto_common::typenum::Unsigned; use crypto_common::{KeyInit, KeySizeUser}; use paste::paste; use rustls::crypto::cipher::{ @@ -12,6 +11,7 @@ use rustls::crypto::cipher::{ PrefixedPayload, Tls12AeadAlgorithm, }; use rustls::ConnectionTrafficSecrets; +use typenum::Unsigned; const EXPLICIT_NONCE_LEN: usize = 8; const OVERHEAD: usize = EXPLICIT_NONCE_LEN + 16; From 4b6bbc7bc3ddcb4cf8d4a1b46d0e94d6aa0f7e39 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 21:09:42 +0800 Subject: [PATCH 37/38] don't include the root cert in the cert chain for the fake resolver --- tests/fake_cert_server_resolver.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/fake_cert_server_resolver.rs b/tests/fake_cert_server_resolver.rs index c826aed..55ce20b 100644 --- a/tests/fake_cert_server_resolver.rs +++ b/tests/fake_cert_server_resolver.rs @@ -60,11 +60,11 @@ impl FakeServerCertResolver { rsa_root_cert: rsa_root_cert.clone(), ecdsa_root_cert: ecdsa_root_cert.clone(), rsa_cert_key: Arc::new(CertifiedKey::new( - vec![rsa_cert, rsa_root_cert], + vec![rsa_cert], any_supported_type(&rsa_key).unwrap(), )), ecdsa_cert_key: Arc::new(CertifiedKey::new( - vec![ecdsa_cert, ecdsa_root_cert], + vec![ecdsa_cert], any_supported_type(&ecdsa_key).unwrap(), )), } From 7ffad43195e8bba48b25b105bdb898eda4aea1b9 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 10 Dec 2024 23:36:11 +0800 Subject: [PATCH 38/38] simplify and reinforce feature selection --- Cargo.toml | 2 +- src/sign/eddsa/ed25519.rs | 2 +- src/tls12/suites/ecdsa.rs | 11 +++++++---- src/tls12/suites/rsa.rs | 7 +++++-- src/tls13/suites/aes.rs | 8 +++++--- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d608eb1..aa86c8e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -202,7 +202,7 @@ hash-full = ["hash-sha224", "hash-sha256", "hash-sha384", "hash-sha512"] # Formats der = ["dep:der"] -sec1 = ["dep:sec1", "elliptic-curve?/sec1"] +sec1 = ["dep:sec1", "elliptic-curve?/sec1", "sec1/pkcs8"] pem = ["elliptic-curve?/pem", "ecdsa?/pem"] pkcs1 = ["dep:pkcs1"] pkcs8 = [ diff --git a/src/sign/eddsa/ed25519.rs b/src/sign/eddsa/ed25519.rs index 14a385c..c090888 100644 --- a/src/sign/eddsa/ed25519.rs +++ b/src/sign/eddsa/ed25519.rs @@ -26,7 +26,7 @@ impl TryFrom<&PrivateKeyDer<'_>> for Ed25519SigningKey { SigningKey::from_pkcs8_der(der.secret_pkcs8_der()) .map_err(|e| format!("failed to decrypt private key: {e}")) } - #[cfg(all(feature = "pkcs8", feature = "sec1"))] + #[cfg(feature = "sec1")] PrivateKeyDer::Sec1(sec1) => { use sec1::DecodeEcPrivateKey; SigningKey::from_sec1_der(sec1.secret_sec1_der()) diff --git a/src/tls12/suites/ecdsa.rs b/src/tls12/suites/ecdsa.rs index 63a4443..fa8d5cb 100644 --- a/src/tls12/suites/ecdsa.rs +++ b/src/tls12/suites/ecdsa.rs @@ -9,13 +9,16 @@ use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorith #[cfg(feature = "aead")] use rustls::{CipherSuite, Tls12CipherSuite}; -#[cfg(feature = "aes-gcm")] -use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +#[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] +use crate::aead::gcm::Aes128Gcm; + +#[cfg(all(feature = "aes-gcm", feature = "hash-sha384"))] +use crate::aead::gcm::Aes256Gcm; -#[cfg(feature = "aes-ccm")] +#[cfg(all(feature = "aes-ccm", feature = "hash-sha256"))] use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8, Aes256Ccm, Aes256Ccm8}; -#[cfg(feature = "chacha20poly1305")] +#[cfg(all(feature = "chacha20poly1305", feature = "hash-sha256"))] use crate::aead::ChaCha20Poly1305; #[cfg(all(feature = "aes-gcm", feature = "hash-sha256"))] diff --git a/src/tls12/suites/rsa.rs b/src/tls12/suites/rsa.rs index d00189e..d084532 100644 --- a/src/tls12/suites/rsa.rs +++ b/src/tls12/suites/rsa.rs @@ -9,8 +9,11 @@ use rustls::crypto::{tls12::PrfUsingHmac, CipherSuiteCommon, KeyExchangeAlgorith #[cfg(feature = "aead")] use rustls::{CipherSuite, Tls12CipherSuite}; -#[cfg(feature = "aes-gcm")] -use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +#[cfg(all(feature = "gcm", feature = "hash-sha256"))] +use crate::aead::gcm::Aes128Gcm; + +#[cfg(all(feature = "gcm", feature = "hash-sha384"))] +use crate::aead::gcm::Aes256Gcm; #[cfg(feature = "chacha20poly1305")] use crate::aead::ChaCha20Poly1305; diff --git a/src/tls13/suites/aes.rs b/src/tls13/suites/aes.rs index c8d4919..02dfd7e 100644 --- a/src/tls13/suites/aes.rs +++ b/src/tls13/suites/aes.rs @@ -1,7 +1,9 @@ -#[cfg(feature = "ccm")] +#[cfg(all(feature = "ccm", feature = "hash-sha256"))] use crate::aead::ccm::{Aes128Ccm, Aes128Ccm8}; -#[cfg(feature = "gcm")] -use crate::aead::gcm::{Aes128Gcm, Aes256Gcm}; +#[cfg(all(feature = "gcm", feature = "hash-sha256"))] +use crate::aead::gcm::Aes128Gcm; +#[cfg(all(feature = "gcm", feature = "hash-sha384"))] +use crate::aead::gcm::Aes256Gcm; use crate::const_concat_slices; use crate::{hash, hmac}; use rustls::crypto::{tls13::HkdfUsingHmac, CipherSuiteCommon};